diff options
170 files changed, 2159 insertions, 1696 deletions
diff --git a/main/Directory.Build.props b/main/Directory.Build.props index 7f3b96a752..dcf4897bf3 100644 --- a/main/Directory.Build.props +++ b/main/Directory.Build.props @@ -17,7 +17,7 @@ <NuGetVersionMicrosoftTestPlatform>16.2.0</NuGetVersionMicrosoftTestPlatform> <NuGetVersionMonoDevelopAnalyzers>0.1.0.2</NuGetVersionMonoDevelopAnalyzers> <NuGetVersionNewtonsoftJson>12.0.2</NuGetVersionNewtonsoftJson> - <NuGetVersionNuGet>5.3.0-rtm.6192</NuGetVersionNuGet> + <NuGetVersionNuGet>5.4.0</NuGetVersionNuGet> <NuGetVersionNUnit2>2.7.0</NuGetVersionNUnit2> <NuGetVersionNUnit3>3.9.0</NuGetVersionNUnit3> <NuGetVersionVSCodeDebugProtocol>15.8.20719.1</NuGetVersionVSCodeDebugProtocol> diff --git a/main/build/MacOSX/BinaryCompatBaseline.txt b/main/build/MacOSX/BinaryCompatBaseline.txt index 849b3189f5..70dfcec3c1 100755 --- a/main/build/MacOSX/BinaryCompatBaseline.txt +++ b/main/build/MacOSX/BinaryCompatBaseline.txt @@ -126,13 +126,13 @@ In assembly 'MonoDevelop.MSBuildBuilder, Version=1.0.0.0, Culture=neutral, Publi In assembly 'MonoDevelop.MSBuildBuilder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3ead7498f347467b': unable to resolve reference to 'Microsoft.Build.Utilities.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' In assembly 'MonoDevelop.MSBuildResolver, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3ead7498f347467b': unable to resolve reference to 'Microsoft.Build.Framework, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' In assembly 'MonoTouch.Design.Client.Mac, Version=0.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756': unable to resolve reference to 'MonoTouch.Hosting, Version=0.0.0.0, Culture=neutral, PublicKeyToken=5caa9e03e69a5abd' -In assembly 'NuGet.Protocol, Version=5.3.0.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35': Unable to resolve member reference 'System.IdentityModel.Tokens.SecurityToken System.ServiceModel.Security.IWSTrustChannelContract::Issue(System.IdentityModel.Protocols.WSTrust.RequestSecurityToken)' from assembly 'System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -In assembly 'NuGet.Protocol, Version=5.3.0.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35': Unable to resolve member reference 'System.Void System.IdentityModel.Protocols.WSTrust.RequestSecurityToken::.ctor()' from assembly 'System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -In assembly 'NuGet.Protocol, Version=5.3.0.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35': Unable to resolve member reference 'System.Void System.ServiceModel.Security.WSTrustChannelFactory::.ctor(System.ServiceModel.Channels.Binding,System.String)' from assembly 'System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -In assembly 'NuGet.Protocol, Version=5.3.0.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35': Unable to resolve member reference 'System.Void System.ServiceModel.Security.WSTrustChannelFactory::set_TrustVersion(System.ServiceModel.Security.TrustVersion)' from assembly 'System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -In assembly 'NuGet.Protocol, Version=5.3.0.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35': Unable to resolve type reference 'System.IdentityModel.Protocols.WSTrust.RequestSecurityToken' in 'System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -In assembly 'NuGet.Protocol, Version=5.3.0.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35': Unable to resolve type reference 'System.ServiceModel.Security.IWSTrustChannelContract' in 'System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -In assembly 'NuGet.Protocol, Version=5.3.0.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35': Unable to resolve type reference 'System.ServiceModel.Security.WSTrustChannelFactory' in 'System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' +In assembly 'NuGet.Protocol, Version=5.4.0.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35': Unable to resolve member reference 'System.IdentityModel.Tokens.SecurityToken System.ServiceModel.Security.IWSTrustChannelContract::Issue(System.IdentityModel.Protocols.WSTrust.RequestSecurityToken)' from assembly 'System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' +In assembly 'NuGet.Protocol, Version=5.4.0.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35': Unable to resolve member reference 'System.Void System.IdentityModel.Protocols.WSTrust.RequestSecurityToken::.ctor()' from assembly 'System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' +In assembly 'NuGet.Protocol, Version=5.4.0.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35': Unable to resolve member reference 'System.Void System.ServiceModel.Security.WSTrustChannelFactory::.ctor(System.ServiceModel.Channels.Binding,System.String)' from assembly 'System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' +In assembly 'NuGet.Protocol, Version=5.4.0.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35': Unable to resolve member reference 'System.Void System.ServiceModel.Security.WSTrustChannelFactory::set_TrustVersion(System.ServiceModel.Security.TrustVersion)' from assembly 'System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' +In assembly 'NuGet.Protocol, Version=5.4.0.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35': Unable to resolve type reference 'System.IdentityModel.Protocols.WSTrust.RequestSecurityToken' in 'System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' +In assembly 'NuGet.Protocol, Version=5.4.0.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35': Unable to resolve type reference 'System.ServiceModel.Security.IWSTrustChannelContract' in 'System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' +In assembly 'NuGet.Protocol, Version=5.4.0.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35': Unable to resolve type reference 'System.ServiceModel.Security.WSTrustChannelFactory' in 'System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' In assembly 'nunit.engine, Version=3.9.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb': Unable to resolve member reference 'Mono.Collections.Generic.Collection`1<Mono.Cecil.TypeReference> Mono.Cecil.TypeDefinition::get_Interfaces()' from assembly 'Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756' In assembly 'System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a': Unable to resolve member reference 'System.Boolean System.Net.ComNetOS::IsWin7orLater' from assembly 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' In assembly 'System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a': Unable to resolve member reference 'System.Diagnostics.TraceSource System.Net.Logging::get_Http()' from assembly 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' @@ -148,6 +148,8 @@ In assembly 'Xamarin.AndroidDesigner.Mac, Version=0.0.0.0, Culture=neutral, Publ In assembly 'Xamarin.AzureSupport, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3ead7498f347467b': unable to resolve reference to 'Microsoft.Developer.IdentityService.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' In assembly 'Xamarin.AzureSupport, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3ead7498f347467b': unable to resolve reference to 'Xamarin.Ide.Identity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' In assembly 'Xamarin.iOSDesigner.MonoDevelop, Version=0.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756': unable to resolve reference to 'MonoTouch.Hosting, Version=0.0.0.0, Culture=neutral, PublicKeyToken=5caa9e03e69a5abd' -In assembly 'Xamarin.Mac, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065': Unable to resolve member reference 'System.Net.Http.Headers.HttpHeaderKind System.Net.Http.Headers.HttpHeaders::GetKnownHeaderKind(System.String)' from assembly 'System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' -In assembly 'Xamarin.Mac, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065': Unable to resolve type reference 'System.Net.Http.Headers.HttpHeaderKind' in 'System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' +In assembly 'Xamarin.Mac, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065': Unable to resolve member reference 'System.Boolean System.Net.Http.Headers.HeaderDescriptor::TryGet(System.String,System.Net.Http.Headers.HeaderDescriptor&)' from assembly 'System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' +In assembly 'Xamarin.Mac, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065': Unable to resolve member reference 'System.Net.Http.Headers.HttpHeaderType System.Net.Http.Headers.HeaderDescriptor::get_HeaderType()' from assembly 'System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' +In assembly 'Xamarin.Mac, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065': Unable to resolve type reference 'System.Net.Http.Headers.HeaderDescriptor' in 'System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' +In assembly 'Xamarin.Mac, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065': Unable to resolve type reference 'System.Net.Http.Headers.HttpHeaderType' in 'System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' In assembly 'XamarinStudio.MSDeploy, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null': unable to resolve reference to 'Microsoft.Build, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' diff --git a/main/build/MacOSX/monostub.mm b/main/build/MacOSX/monostub.mm index bab07f5967..57424d4ef3 100644 --- a/main/build/MacOSX/monostub.mm +++ b/main/build/MacOSX/monostub.mm @@ -227,6 +227,12 @@ load_xammac() XAMARIN_CREATE_CLASSES (); } + void *ptr = dlsym(libxammac, "xamarin_marshal_objectivec_exception_mode"); + *(int*)ptr = 2; // MarshalObjectiveCExceptionModeThrowManagedException + + ptr = dlsym(libxammac, "xamarin_marshal_managed_exception_mode"); + *(int*)ptr = 2; // MarshalManagedExceptionModeThrowObjectiveCException + return libxammac; } diff --git a/main/external/debugger-libs b/main/external/debugger-libs -Subproject 281e01ea5505c0b49fbca37f994db845a5e07e4 +Subproject 44a15150f60d1500edc6dca1983056ed747ebee diff --git a/main/external/vs-editor-api b/main/external/vs-editor-api -Subproject 109220f5a283245ed9ffb70f82ca061d4d6d3da +Subproject 07690d994608d557268caf0726711d3bf52a9bb diff --git a/main/external/xwt b/main/external/xwt -Subproject 485b51769c480295511348657c60287c8b7b093 +Subproject 9a22465b52c7dbaae321a514b046edebd6a0efb diff --git a/main/src/addins/AspNet/MonoDevelop.AspNet.csproj b/main/src/addins/AspNet/MonoDevelop.AspNet.csproj index b9cb30001a..745f737986 100644 --- a/main/src/addins/AspNet/MonoDevelop.AspNet.csproj +++ b/main/src/addins/AspNet/MonoDevelop.AspNet.csproj @@ -72,11 +72,6 @@ <Name>MonoDevelop.Xml</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> </ItemGroup> <ItemGroup> <Reference Include="System" /> diff --git a/main/src/addins/AspNet/Tests/MonoDevelop.AspNet.Tests.csproj b/main/src/addins/AspNet/Tests/MonoDevelop.AspNet.Tests.csproj index caa9916dab..48f291c505 100644 --- a/main/src/addins/AspNet/Tests/MonoDevelop.AspNet.Tests.csproj +++ b/main/src/addins/AspNet/Tests/MonoDevelop.AspNet.Tests.csproj @@ -48,11 +48,6 @@ <Name>MonoDevelop.Ide</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\..\MonoDevelop.DesignerSupport\MonoDevelop.DesignerSupport.csproj"> <Project>{2C24D515-4A2C-445C-8419-C09231913CFA}</Project> <Name>MonoDevelop.DesignerSupport</Name> diff --git a/main/src/addins/CSharpBinding/AspNet/CSharpBinding.AspNet.csproj b/main/src/addins/CSharpBinding/AspNet/CSharpBinding.AspNet.csproj index ddeea9f747..c12fa966e8 100644 --- a/main/src/addins/CSharpBinding/AspNet/CSharpBinding.AspNet.csproj +++ b/main/src/addins/CSharpBinding/AspNet/CSharpBinding.AspNet.csproj @@ -51,16 +51,6 @@ <Name>MonoDevelop.Refactoring</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> - <ProjectReference Include="..\..\..\..\external\nrefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj"> - <Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project> - <Name>ICSharpCode.NRefactory.CSharp</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\..\Deployment\MonoDevelop.Deployment\MonoDevelop.Deployment.csproj"> <Project>{9BC670A8-1851-40EC-9685-279F4C98433D}</Project> <Name>MonoDevelop.Deployment</Name> diff --git a/main/src/addins/CSharpBinding/CSharpBinding.addin.xml b/main/src/addins/CSharpBinding/CSharpBinding.addin.xml index dff822e330..5ce1d72d91 100644 --- a/main/src/addins/CSharpBinding/CSharpBinding.addin.xml +++ b/main/src/addins/CSharpBinding/CSharpBinding.addin.xml @@ -225,17 +225,6 @@ </Extension> <!-- - <Extension path = "/MonoDevelop/Refactoring/CodeActions"> - <Action mimeType="text/x-csharp" - _title = "Move type to another file" - _description = "Moves current type to another file that matches the name of the type." - class = "MonoDevelop.CSharp.Refactoring.CodeActions.MoveTypeToFile" /> - <Action mimeType="text/x-csharp" - _title = "Convert to enum" - _description = "Converts constant fields to enumeration" - class = "MonoDevelop.CSharp.Refactoring.CodeActions.ConvertToEnumAction" /> - </Extension> - <Extension path = "/MonoDevelop/Refactoring/CodeIssues"> <CodeIssue mimeType="text/x-csharp" severity = "Error" class="MonoDevelop.CSharp.Refactoring.CodeIssues.MonoTODOIssue"/> </Extension> --> diff --git a/main/src/addins/CSharpBinding/CSharpBinding.csproj b/main/src/addins/CSharpBinding/CSharpBinding.csproj index 479d10513f..c4fcfe8138 100644 --- a/main/src/addins/CSharpBinding/CSharpBinding.csproj +++ b/main/src/addins/CSharpBinding/CSharpBinding.csproj @@ -188,7 +188,6 @@ <Compile Include="MonoDevelop.CSharp.CodeRefactorings\PredefinedCodeRefactoringProviderNames.cs" /> <Compile Include="MonoDevelop.CSharp.Diagnostics\IDEDiagnosticIds.cs" /> <Compile Include="MonoDevelop.CSharp.Diagnostics\MonoTODO\MonoTODODiagnosticAnalyzer.cs" /> - <Compile Include="MonoDevelop.CSharp.CodeRefactorings\ConvertToEnum\ConvertToEnumDialog.cs" /> <Compile Include="MonoDevelop.CSharp.Refactoring\CSharpFeaturesTextEditorExtension.cs" /> <Compile Include="MonoDevelop.CSharp.Refactoring\RenameHandler.cs" /> <Compile Include="MonoDevelop.CSharp.Refactoring\FindReferencesHandler.cs" /> @@ -284,9 +283,6 @@ <Compile Include="MonoDevelop.CSharp.Debugger\CSharpBreakpointSpanResolver.cs" /> </ItemGroup> <ItemGroup> - <None Include="MonoDevelop.CSharp.CodeRefactorings\ConvertToEnum\ConvertToEnumCodeRefactoringProvider.cs" /> - </ItemGroup> - <ItemGroup> <InternalsVisibleTo Include="MonoDevelop.Ide.Tests" /> <InternalsVisibleTo Include="MonoDevelop.CSharpBinding.AspNet" /> <InternalsVisibleTo Include="MonoDevelop.CSharpBinding.Tests" /> diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeRefactorings/ConvertToEnum/ConvertToEnumCodeRefactoringProvider.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeRefactorings/ConvertToEnum/ConvertToEnumCodeRefactoringProvider.cs deleted file mode 100644 index 03a55232b1..0000000000 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeRefactorings/ConvertToEnum/ConvertToEnumCodeRefactoringProvider.cs +++ /dev/null @@ -1,504 +0,0 @@ -// -// Author: -// Luís Reis <luiscubal@gmail.com> -// -// Copyright (c) 2013 Luís Reis -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Collections.Generic; -using System.Linq; -using ICSharpCode.NRefactory.Semantics; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.TypeSystem.Implementation; -using ICSharpCode.NRefactory.PatternMatching; -using MonoDevelop.CodeActions; -using ICSharpCode.NRefactory; -using System.Threading; -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory.CSharp.Refactoring; -using ICSharpCode.Decompiler.ILAst; -using MonoDevelop.Core; -using MonoDevelop.Ide.Editor; - -namespace MonoDevelop.CSharp.Refactoring.CodeActions -{ - /// <summary> - /// Generates an enumeration from const fields - /// </summary> - class ConvertToEnumAction : MonoDevelop.CodeActions.CodeActionProvider - { - public override IEnumerable<MonoDevelop.CodeActions.CodeAction> GetActions (TextEditor editor, DocumentContext doc, object refactoringContext, MonoDevelop.Ide.Editor.DocumentLocation loc, CancellationToken cancellationToken) - { - var mdCtx = refactoringContext as MDRefactoringContext; - - if (mdCtx == null || mdCtx.IsInvalid) - yield break; - - VariableInitializer currentVariable = mdCtx.GetNode<VariableInitializer>(); - if (currentVariable == null) { - yield break; - } - - FieldDeclaration currentField = currentVariable.Parent as FieldDeclaration; - if (currentField == null) { - yield break; - } - - if (!currentField.Modifiers.HasFlag(Modifiers.Const)) { - yield break; - } - - PrimitiveType baseType = TypeToIntegerPrimitive(mdCtx, currentField.ReturnType); - if (baseType == null) { - //Can't make enums of these types - yield break; - } - - TypeDeclaration containerType = currentVariable.GetParent<TypeDeclaration>(); - - //Get all the fields/variables that the enum can possibly cover - //Don't check the name just yet. That'll come later. - - var constFields = containerType.Members.OfType<FieldDeclaration>() - .Where(field => field.GetParent<TypeDeclaration>() == containerType && field.HasModifier(Modifiers.Const)).ToList(); - - var constVariables = constFields.SelectMany(field => field.Variables).ToList(); - - //Now, it's time to check the name of the selected variable - //We'll use this to search for prefixes later - - var names = constVariables.Select(variable => variable.Name).ToList(); - string currentName = currentVariable.Name; - - //Now, find the common name prefixes - //If the variable is called 'A_B_C_D', then 'A', 'A_B' and 'A_B_C' are - //the potentially available prefixes. - //Note that the common prefixes are the ones that more than one variable - //has. - //Each prefix has an associated action. - - foreach (var prefix in GetCommonPrefixes (currentName, names)) { - string title = string.Format(GettextCatalog.GetString("Create enum '{0}'"), prefix); - - yield return new DefaultCodeAction(title, (ctx, script) => { - PrepareToRunAction (prefix, baseType, containerType, constVariables, cancellationToken, ctx, script); - }); - } - } - - void PrepareToRunAction (string prefix, PrimitiveType baseType, TypeDeclaration containerType, List<VariableInitializer> variables, CancellationToken cancellationToken, RefactoringContext context, Script script) - { - List<string> names = variables.Select(variable => variable.Name).ToList(); - Dictionary<string, string> newNames = names.ToDictionary(originalName => originalName, originalName => { - if (!originalName.StartsWith(prefix)) { - return originalName; - } - int startName = prefix.Length; - while (startName < originalName.Length - 1 && originalName[startName] == '_') { - ++startName; - } - return originalName.Substring(startName); - }); - - string enumName; - using (var dialog = new ConvertToEnumDialog (prefix, variables, variables.Where(variable => variable.Name.StartsWith(prefix, StringComparison.InvariantCulture) - && VariableHasSpecifiedIntegerType(context, variable, baseType)).ToList(), newNames)) - { - if (dialog.Run (/*MonoDevelop.Ide.IdeApp.Workbench.RootWindow*/) != Xwt.Command.Ok) { - return; - } - enumName = dialog.EnumName; - variables = dialog.SelectedVariables; - newNames = dialog.NewNames; - } - - RunAction (context, baseType, enumName, newNames, containerType, variables, script); - - } - - void RunAction(RefactoringContext context, AstType baseType, string enumName, Dictionary<string, string> newNames, TypeDeclaration containerTypeDeclaration, List<VariableInitializer> variables, Script script) - { - var names = variables.Select (variable => variable.Name).ToList (); - var containerType = (context.Resolve(containerTypeDeclaration) as TypeResolveResult).Type; - - var fields = containerTypeDeclaration.Members.OfType<FieldDeclaration>().Where(field => field.Modifiers.HasFlag(Modifiers.Const)).ToList(); - List<VariableInitializer> variableUnitsToRemove = new List<VariableInitializer>(variables); - List<FieldDeclaration> fieldsToRemove = new List<FieldDeclaration>(); - - foreach (var field in fields) { - if (field.Variables.All(variableUnitsToRemove.Contains)) { - fieldsToRemove.Add(field); - - variableUnitsToRemove.RemoveAll(field.Variables.Contains); - } - } - - var generatedEnum = CreateEnumDeclaration(baseType, enumName, variables, names, newNames); - - AstNode root = GetRootNodeOf(containerTypeDeclaration); - var newRoot = root.Clone(); - - FixIdentifiers(context, enumName, variables, containerType, baseType, names, newNames, root, newRoot); - foreach (var member in root.Descendants.OfType<MemberReferenceExpression>().Where (member => names.Contains (member.MemberName))) { - if (variables.Any(variable => variable.Descendants.Contains(member))) { - //Already handled - continue; - } - - var resolvedIdentifier = context.Resolve(member) as MemberResolveResult; - if (resolvedIdentifier == null) { - continue; - } - - if (resolvedIdentifier.Type.Equals(containerType)) { - continue; - } - - var equivalentMember = GetEquivalentNodeFor(root, newRoot, member); - MemberReferenceExpression memberToReplace = (MemberReferenceExpression)equivalentMember; - - var replacement = CreateReplacementMemberReference(enumName, baseType, newNames, memberToReplace); - memberToReplace.ReplaceWith(replacement); - } - - //Fix the file - InsertAfterEquivalent(root, newRoot, containerTypeDeclaration.LBraceToken, generatedEnum, Roles.TypeMemberRole); - - foreach (var variableToRemove in variableUnitsToRemove) { - GetEquivalentNodeFor(root, newRoot, variableToRemove).Remove(); - } - foreach (var fieldToRemove in fieldsToRemove) { - GetEquivalentNodeFor(root, newRoot, fieldToRemove).Remove(); - } - - script.Replace(root, newRoot); - - ReplaceVariableReferences(context, root, baseType, enumName, script, newNames, variables); - } - - static void ReplaceVariableReferences(RefactoringContext context, AstNode root, AstType baseType, string enumName, Script script, Dictionary<string, string> newNames, IEnumerable<VariableInitializer> variables) - { - var resolveResults = variables.Select(context.Resolve).Cast<MemberResolveResult> (); - var resolvedFields = resolveResults.Select(resolveResult => resolveResult.Member); - script.DoGlobalOperationOn(resolvedFields, (newCtx, newScript, foundNodes) => { - foreach (var foundNode in foundNodes) { - TypeDeclaration newContainerType = foundNode.GetParent<TypeDeclaration>(); - if (root.Descendants.OfType<TypeDeclaration>().Select(type => ((TypeResolveResult)context.Resolve(type)).Type.FullName).ToList().Contains(((TypeResolveResult)newCtx.Resolve(newContainerType)).Type.FullName)) { - //This file has already been fixed - return; - } - var identifierExpr = foundNode as IdentifierExpression; - if (identifierExpr != null) { - newScript.Replace(identifierExpr, CreateIdentifierReplacement(enumName, baseType, newNames, identifierExpr)); - continue; - } - var memberRef = foundNode as MemberReferenceExpression; - if (memberRef != null) { - var replacement = CreateReplacementMemberReference(enumName, baseType, newNames, memberRef); - newScript.Replace(memberRef, replacement); - } - } - }); - } - - TypeDeclaration CreateEnumDeclaration(AstType baseType, string enumName, List<VariableInitializer> variables, List<string> names, Dictionary<string, string> newNames) - { - TypeDeclaration generatedEnum = new TypeDeclaration(); - generatedEnum.ClassType = ClassType.Enum; - generatedEnum.BaseTypes.Add(baseType.Clone()); - generatedEnum.Name = enumName; - generatedEnum.Modifiers = GetCombinedModifier((Modifiers)variables.Select(variable => ((FieldDeclaration)variable.Parent).Modifiers).Aggregate(0, (prev, newModifier) => prev | (int)newModifier)); - foreach (var variable in variables) { - var generatedMember = new EnumMemberDeclaration(); - generatedMember.Name = newNames[variable.Name]; - var value = variable.Initializer.Clone(); - foreach (var identifier in value.DescendantsAndSelf.OfType<IdentifierExpression>().Where(identifier => names.Contains(identifier.Identifier))) { - var newIdentifier = new IdentifierExpression(newNames[identifier.Identifier]); - if (identifier == value) { - value = newIdentifier; - break; - } - identifier.ReplaceWith(newIdentifier); - } - generatedMember.Initializer = value; - generatedEnum.Members.Add(generatedMember); - } - return generatedEnum; - } - - /// <summary> - /// Determines whether the initialized variable has the specified primitive integer type - /// </summary> - /// <returns><c>true</c> if the initialized variable has the specified type; otherwise, <c>false</c>.</returns> - /// <param name="context">The context to use.</param> - /// <param name="variable">The variable initializer to check.</param> - /// <param name="type">The type to compare with.</param> - bool VariableHasSpecifiedIntegerType(RefactoringContext context, VariableInitializer variable, AstType type) - { - return TypeToIntegerPrimitive(context, variable.GetParent<FieldDeclaration>().ReturnType).Match(type).Success; - } - - static Dictionary<string, PrimitiveType> primitiveTypes = new Dictionary<string, PrimitiveType>(); - - static ConvertToEnumAction() - { - primitiveTypes.Add(typeof(byte).FullName, new PrimitiveType("byte")); - primitiveTypes.Add(typeof(sbyte).FullName, new PrimitiveType("sbyte")); - - primitiveTypes.Add(typeof(short).FullName, new PrimitiveType("short")); - primitiveTypes.Add(typeof(int).FullName, new PrimitiveType("int")); - primitiveTypes.Add(typeof(long).FullName, new PrimitiveType("long")); - - primitiveTypes.Add(typeof(ushort).FullName, new PrimitiveType("ushort")); - primitiveTypes.Add(typeof(uint).FullName, new PrimitiveType("uint")); - primitiveTypes.Add(typeof(ulong).FullName, new PrimitiveType("ulong")); - } - - /// <summary> - /// Gets a PrimitiveType instance from an AstType. - /// Only returns integer types (and never the char type) - /// </summary> - /// <returns>The integer primitive.</returns> - /// <param name="context">The context to use.</param> - /// <param name="type">The AstType to get the primitive from.</param> - PrimitiveType TypeToIntegerPrimitive(RefactoringContext context, AstType type) - { - var resolvedType = context.ResolveType(type) as DefaultResolvedTypeDefinition; - - PrimitiveType primitiveType; - if (!primitiveTypes.TryGetValue(resolvedType.FullName, out primitiveType)) { - return null; - } - - return primitiveType; - } - - static Expression CreateReplacementMemberReference(string enumName, AstType baseType, Dictionary<string, string> newNames, MemberReferenceExpression memberToReplace) - { - return new ParenthesizedExpression(new CastExpression(baseType.Clone(), new MemberReferenceExpression(new MemberReferenceExpression(memberToReplace.Target.Clone(), enumName), newNames [memberToReplace.MemberName]))); - } - - void FixIdentifiers(RefactoringContext context, string enumName, List<VariableInitializer> variables, IType containerType, AstType baseType, List<string> names, Dictionary<string, string> newNames, AstNode root, AstNode newRoot) - { - foreach (var identifier in root.Descendants.OfType<IdentifierExpression> ().Where (identifier => names.Contains (identifier.Identifier))) { - if (variables.Any(variable => variable.Descendants.Contains(identifier))) { - //Already handled - continue; - } - var resolvedIdentifier = context.Resolve(identifier) as MemberResolveResult; - if (resolvedIdentifier == null) { - continue; - } - if (resolvedIdentifier.Type.Equals(containerType)) { - continue; - } - var replacement = CreateIdentifierReplacement(enumName, baseType, newNames, identifier); - GetEquivalentNodeFor(root, newRoot, identifier).ReplaceWith(replacement); - } - } - - static ParenthesizedExpression CreateIdentifierReplacement(string enumName, AstType baseType, Dictionary<string, string> newNames, IdentifierExpression identifier) - { - var replacement = new ParenthesizedExpression(new CastExpression(baseType.Clone(), new MemberReferenceExpression(new IdentifierExpression(enumName), newNames [identifier.Identifier]))); - return replacement; - } - - /// <summary> - /// Finds the corresponding node in another ("new") AST. - /// Assumes entities have not been renamed and no statements have been removed. - /// </summary> - /// <returns>The equivalent node in the new AST.</returns> - /// <param name="root">The root of the first ("old") AST.</param> - /// <param name="newRoot">The root of the new AST.</param> - /// <param name="nodeToFind">Node (from the old AST) to find in the new one.</param> - AstNode GetEquivalentNodeFor(AstNode root, AstNode newRoot, AstNode nodeToFind) - { - if (nodeToFind == null) { - throw new ArgumentNullException("nodeToFind"); - } - - if (nodeToFind.Parent != root) { - AstNode foundRoot = GetEquivalentNodeFor(root, newRoot, nodeToFind.Parent); - if (foundRoot == null) { - //If the equivalent of the parent does not exist in the new AST, - //then neither does this node. - return null; - } - newRoot = foundRoot; - root = nodeToFind.Parent; - } - - //At this point, the roots are the parents of the nodes to check - //root is the parent of the nodeToFind, and newRoot is the parent of the node to return - - var block = root as BlockStatement; - if (block != null && nodeToFind.Role == BlockStatement.StatementRole) { - //This could be a problem if statements were removed in the new AST, - //but fortunately that's not the problem we're trying to solve. - return ((BlockStatement)newRoot).Statements.ElementAt(block.TakeWhile(statement => statement != nodeToFind).Count()); - } - - //First, we'll narrow down the search - the equivalent node *always* has the same type and role as nodeToFind - //The Role check will help e.g. in binary expressions (where there is a 'Left' and a 'Right' role) - var candidates = newRoot.Children.Where(child => child.GetType() == nodeToFind.GetType() && child.Role == nodeToFind.Role); - var entity = nodeToFind as EntityDeclaration; - if (entity != null) { - var field = nodeToFind as FieldDeclaration; - if (field != null) { - //Fields have to be treated separately because fields have no names - candidates = candidates.Where(candidate => IsEquivalentField((FieldDeclaration) candidate, field)); - } - else { - //Some entities can be distinguished by name. - candidates = candidates.Where(candidate => ((EntityDeclaration)candidate).Name == entity.Name); - - var method = nodeToFind as MethodDeclaration; - if (method != null) { - //Methods, however, can be overloaded - so their names aren't enough. - candidates = candidates.Where(candidate => CheckIfMethodsHaveSameParameters((MethodDeclaration) candidate, method)); - } - } - } - - var ns = nodeToFind as NamespaceDeclaration; - if (ns != null) { - candidates = candidates.Where(candidate => ((NamespaceDeclaration)candidate).Name == ns.Name).ToList(); - if (candidates.Count() > 1) { - throw new NotImplementedException("Two or more namespace declarations with the same name are siblings. This case is not currently supported by this action."); - } - } - - var initializer = nodeToFind as VariableInitializer; - if (initializer != null) { - candidates = candidates.Where(candidate => ((VariableInitializer)candidate).Name == initializer.Name); - } - - var equivalentNode = candidates.SingleOrDefault(); - return equivalentNode; - } - - bool IsEquivalentField(FieldDeclaration field1, FieldDeclaration field2) { - return field1.Variables.Any(variable1 => { - return field2.Variables.Any(variable2 => variable1.Name == variable2.Name); - }); - } - - bool CheckIfMethodsHaveSameParameters(MethodDeclaration methodDeclaration, MethodDeclaration comparedMethod) - { - if (methodDeclaration.Parameters.Count != comparedMethod.Parameters.Count) { - return false; - } - - ParameterDeclaration param1 = methodDeclaration.Parameters.FirstOrDefault(); - ParameterDeclaration param2 = comparedMethod.Parameters.FirstOrDefault(); - - while (param1 != null) { - //If the names or initializers are different, this will still match. - //But if the type or order changes, this will complain - if (!param1.Type.Match(param2.Type).Success) { - return false; - } - - param1 = (ParameterDeclaration) param1.GetNextSibling(node => node is ParameterDeclaration); - param2 = (ParameterDeclaration) param2.GetNextSibling(node => node is ParameterDeclaration); - } - - return true; - } - - void InsertAfterEquivalent<T>(AstNode root, AstNode newRoot, AstNode prevNode, T newNode, Role<T> role) - where T : AstNode - { - AstNode equivalentPrevNode = GetEquivalentNodeFor(root, newRoot, prevNode); - equivalentPrevNode.Parent.InsertChildAfter<T>(equivalentPrevNode, newNode, role); - } - - /// <summary> - /// Gets the least permissive access modifier that still allows access to - /// fields or methods with the specified modifiers. - /// This will ignore all modifiers unrelated to access - such as const and readonly - /// </summary> - /// <returns>A modifier that is at least as permissive as all provided modifiers.</returns> - /// <param name="modifiers">The modifiers to use.</param> - Modifiers GetCombinedModifier(Modifiers modifiers) - { - if (modifiers.HasFlag(Modifiers.Public)) - return Modifiers.Public; - - Modifiers combinedModifier = 0; - if (modifiers.HasFlag(Modifiers.Protected)) { - combinedModifier |= Modifiers.Protected; - } - if (modifiers.HasFlag(Modifiers.Internal)) { - combinedModifier |= Modifiers.Internal; - } - - //No modifier if the fields are all private. - return combinedModifier; - } - - /// <summary> - /// Gets all prefixes that more than one name have. - /// </summary> - /// <returns>The common prefixes.</returns> - /// <param name="currentName">The name to use.</param> - /// <param name="names">The names to check.</param> - IEnumerable<string> GetCommonPrefixes(string currentName, IEnumerable<string> names) - { - //Find the indexes that 'split' words in the variable name - var boundariesForCurrentWord = GetWordsBoundaries(currentName); - - //Get the candidate prefixes - List<string> proposedPrefixes = boundariesForCurrentWord.Select(boundary => currentName.Substring(0, boundary)).ToList(); - - //Return only the prefixes that more than one variable has. - return proposedPrefixes.Where(prefix => names.Count(name => name.StartsWith(prefix, StringComparison.InvariantCulture)) > 1); - } - - List<int> GetWordsBoundaries(string name) - { - List<int> foundBoundaries = new List<int>(); - for (int i = 1; i < name.Length - 1; ++i) { - char chr = name [i]; - if (chr == '_') { - foundBoundaries.Add(i); - continue; - } - - if (char.IsUpper(chr) && char.IsLower(name [i - 1])) { - foundBoundaries.Add(i); - continue; - } - } - - return foundBoundaries; - } - - AstNode GetRootNodeOf(AstNode node) - { - while (node.Parent != null) { - node = node.Parent; - } - - return node; - } - } -} - diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeRefactorings/ConvertToEnum/ConvertToEnumDialog.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeRefactorings/ConvertToEnum/ConvertToEnumDialog.cs deleted file mode 100644 index cfb078973a..0000000000 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeRefactorings/ConvertToEnum/ConvertToEnumDialog.cs +++ /dev/null @@ -1,122 +0,0 @@ -// -// ConvertToEnumDialog.cs -// -// Author: -// Luís Reis <luiscubal@gmail.com> -// -// Copyright (c) 2013 Luís Reis -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Linq; -using MonoDevelop.Core; -using System.Collections.Generic; -using ICSharpCode.NRefactory.CSharp; - -namespace MonoDevelop.CSharp.Refactoring.CodeActions -{ - class ConvertToEnumDialog : Xwt.Dialog - { - Xwt.TextEntry enumNameEntry; - Xwt.ListView variableList; - Xwt.ListStore variableStore; - Xwt.DataField<bool> enabledField; - Xwt.ListViewColumn enabledColumn; - Xwt.DataField<string> oldNameField; - Xwt.ListViewColumn oldNameColumn; - Xwt.DataField<string> newNameField; - Xwt.ListViewColumn newNameColumn; - List<VariableInitializer> variables; - - public ConvertToEnumDialog(string proposedEnumName, List<VariableInitializer> variables, List<VariableInitializer> defaultActiveVariables, Dictionary<string, string> newNames) { - this.variables = variables; - - Title = GettextCatalog.GetString("Convert fields to enumeration"); - - Xwt.VBox vbox = new Xwt.VBox (); - - vbox.PackStart(new Xwt.Label(GettextCatalog.GetString("Name of enum"))); - - enumNameEntry = new Xwt.TextEntry (); - enumNameEntry.Text = proposedEnumName; - vbox.PackStart (enumNameEntry); - - vbox.PackStart (new Xwt.Label (GettextCatalog.GetString ("Variables to include"))); - - variableList = new Xwt.ListView (); - enabledField = new Xwt.DataField<bool> (); - oldNameField = new Xwt.DataField<string> (); - newNameField = new Xwt.DataField<string> (); - - variableStore = new Xwt.ListStore (enabledField, oldNameField, newNameField); - variableList.DataSource = variableStore; - - enabledColumn = new Xwt.ListViewColumn (GettextCatalog.GetString ("Included"), new Xwt.CheckBoxCellView(enabledField) { Editable = true }); - variableList.Columns.Add (enabledColumn); - oldNameColumn = new Xwt.ListViewColumn(GettextCatalog.GetString("Field name"), new Xwt.TextCellView(oldNameField) { Editable = false }); - variableList.Columns.Add (oldNameColumn); - newNameColumn = new Xwt.ListViewColumn(GettextCatalog.GetString("Enum name"), new Xwt.TextCellView(newNameField) { Editable = true, }); - variableList.Columns.Add (newNameColumn); - - for (int i = 0; i < variables.Count; ++i) { - var variable = variables[i]; - - variableStore.AddRow (); - variableStore.SetValue (i, enabledField, defaultActiveVariables.Contains(variable)); - variableStore.SetValue (i, oldNameField, variable.Name); - - variableStore.SetValue (i, newNameField, newNames [variable.Name]); - } - - vbox.PackStart (variableList, true, true); - - vbox.PackStart (new Xwt.Label (GettextCatalog.GetString ("Warning: This may take a while..."))); - - Content = vbox; - - Buttons.Add (new Xwt.DialogButton (Xwt.Command.Ok)); - Buttons.Add (new Xwt.DialogButton (Xwt.Command.Cancel)); - } - - public string EnumName { - get { return enumNameEntry.Text; } - } - - public List<VariableInitializer> SelectedVariables - { - get { - return variables.Where((variable, idx) => variableStore.GetValue<bool>(idx, enabledField)).ToList(); - } - } - - public Dictionary<string, string> NewNames - { - get { - var newNames = new Dictionary<string, string> (); - - for (int i = 0; i < variableStore.RowCount; ++i) { - newNames[variableStore.GetValue<string>(i, oldNameField)] = variableStore.GetValue<string>(i, newNameField); - } - - return newNames; - } - } - } -} - diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindBaseSymbolsHandler.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindBaseSymbolsHandler.cs index 2b34ab179c..54e6a6d731 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindBaseSymbolsHandler.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindBaseSymbolsHandler.cs @@ -46,7 +46,7 @@ namespace MonoDevelop.CSharp.Navigation Task FindSymbols (ISymbol sym, CancellationTokenSource cancellationTokenSource) { if (sym == null) - return Task.FromResult (0); + return Task.CompletedTask; return Task.Run (delegate { var searchMonitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true); using (var monitor = searchMonitor.WithCancellationSource (cancellationTokenSource)) { diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindDerivedSymbolsHandler.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindDerivedSymbolsHandler.cs index 1817574614..331cb5f694 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindDerivedSymbolsHandler.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindDerivedSymbolsHandler.cs @@ -64,7 +64,7 @@ namespace MonoDevelop.CSharp.Refactoring static Task FindDerivedSymbols (ISymbol symbol, CancellationTokenSource cancellationTokenSource) { if (symbol == null) - return Task.FromResult (0); + return Task.CompletedTask; var solution = IdeApp.Workbench.ActiveDocument?.DocumentContext.AnalysisDocument?.Project?.Solution ?? IdeApp.TypeSystemService.Workspace.CurrentSolution; return Task.Run (async delegate { var searchMonitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true); diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindImplementingMembersHandler.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindImplementingMembersHandler.cs index 5c337577ab..d93f884120 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindImplementingMembersHandler.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindImplementingMembersHandler.cs @@ -83,7 +83,7 @@ namespace MonoDevelop.CSharp.Navigation Task FindImplementingSymbols (Compilation compilation, RefactoringSymbolInfo info, CancellationTokenSource cancellationTokenSource) { if (!TryGetInterfaceType (info, out var interfaceType, out var implementingType)) - return Task.FromResult (0); + return Task.CompletedTask; return Task.Run (delegate { var searchMonitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true); diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CSharpCompilerParameters.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CSharpCompilerParameters.cs index 965dd89dd2..ccedc00488 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CSharpCompilerParameters.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Project/CSharpCompilerParameters.cs @@ -142,7 +142,7 @@ namespace MonoDevelop.CSharp.Project ParentConfiguration.OutputDirectory ); - var outputKind = OutputTypeToOutputKind (outputType); + var outputKind = outputType == null ? GetOutputKindFromProject (project) : OutputTypeToOutputKind (outputType); bool isLibrary = outputKind == OutputKind.DynamicallyLinkedLibrary; string mainTypeName = project.MainClass; if (isLibrary || mainTypeName == string.Empty) { @@ -175,6 +175,20 @@ namespace MonoDevelop.CSharp.Project return options; } + static OutputKind GetOutputKindFromProject (CSharpProject project) + { + switch (project.CompileTarget) { + case CompileTarget.Exe: + return OutputKind.ConsoleApplication; + case CompileTarget.WinExe: + return OutputKind.WindowsApplication; + case CompileTarget.Module: + return OutputKind.NetModule; + default: + return OutputKind.DynamicallyLinkedLibrary; + } + } + static OutputKind OutputTypeToOutputKind (string outputType) { switch (outputType.ToLowerInvariant ()) { diff --git a/main/src/addins/ChangeLogAddIn/ChangeLogAddIn.csproj b/main/src/addins/ChangeLogAddIn/ChangeLogAddIn.csproj index da22a433ef..b1dfbffbf8 100644 --- a/main/src/addins/ChangeLogAddIn/ChangeLogAddIn.csproj +++ b/main/src/addins/ChangeLogAddIn/ChangeLogAddIn.csproj @@ -26,11 +26,6 @@ <Name>MonoDevelop.VersionControl</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\MonoDevelop.Debugger\MonoDevelop.Debugger.csproj"> <Project>{2357AABD-08C7-4808-A495-8FF2D3CDFDB0}</Project> <Name>MonoDevelop.Debugger</Name> diff --git a/main/src/addins/MacPlatform/MacPlatform.cs b/main/src/addins/MacPlatform/MacPlatform.cs index 656634f242..4414821843 100644 --- a/main/src/addins/MacPlatform/MacPlatform.cs +++ b/main/src/addins/MacPlatform/MacPlatform.cs @@ -287,6 +287,18 @@ namespace MonoDevelop.MacIntegration { oldHandler = NSGetUncaughtExceptionHandler (); NSSetUncaughtExceptionHandler (uncaughtHandler); + + ObjCRuntime.Runtime.MarshalManagedException += (sender, args) => { + LoggingService.LogInternalError (args.Exception); + }; + + ObjCRuntime.Runtime.MarshalObjectiveCException += (sender, args) => { + try { + throw new MarshalledObjCException (args.Exception); + } catch (MarshalledObjCException e) { + LoggingService.LogInternalError ("MarshalObjCException", e); + } + }; } public override Xwt.Toolkit LoadNativeToolkit () @@ -352,10 +364,15 @@ namespace MonoDevelop.MacIntegration // At this point, Cocoa should have been initialized; it is initialized along with Gtk+ at the beginning of IdeStartup.Run // If LaunchReason is still Unknown at this point, it means we have missed the NSApplicationDidLaunch notification for some reason and - // we fall back to it being a Normal startup to unblock anything waiting for that notification. + // we fall back to the AppDelegate's version to unblock anything waiting for that notification. if (IdeApp.LaunchReason == IdeApp.LaunchType.Unknown) { - LoggingService.LogWarning ("Missed NSApplicationDidLaunch notification, assuming normal startup"); - IdeApp.LaunchReason = IdeApp.LaunchType.Normal; + if (appDelegate.LaunchReason != AppDelegate.LaunchType.Unknown) { + IdeApp.LaunchReason = appDelegate.LaunchReason == AppDelegate.LaunchType.Normal ? IdeApp.LaunchType.Normal : IdeApp.LaunchType.LaunchedFromFileManager; + } else { + // Fall back to Normal if even the app delegate doesn't know + LoggingService.LogWarning ("Unknown startup reason, assuming Normal"); + IdeApp.LaunchReason = IdeApp.LaunchType.Normal; + } } ideAppleEvents = new MacIdeAppleEvents (); @@ -418,6 +435,14 @@ namespace MonoDevelop.MacIntegration } } + internal override void MakeAccessibilityAnnouncement (string text) + { + using var message = new NSString (text); + using var dictionary = new NSDictionary (NSAccessibilityNotificationUserInfoKeys.AnnouncementKey, message, + NSAccessibilityNotificationUserInfoKeys.PriorityKey, NSAccessibilityPriorityLevel.High); + NSAccessibility.PostNotification (NSApplication.SharedApplication.AccessibilityMainWindow, NSAccessibilityNotifications.AnnouncementRequestedNotification, dictionary); + } + protected override string OnGetMimeTypeForUri (string uri) { var ext = Path.GetExtension (uri); diff --git a/main/src/addins/MacPlatform/MainToolbar/StatusBar.cs b/main/src/addins/MacPlatform/MainToolbar/StatusBar.cs index 1780680d9b..bbc28308a2 100644 --- a/main/src/addins/MacPlatform/MainToolbar/StatusBar.cs +++ b/main/src/addins/MacPlatform/MainToolbar/StatusBar.cs @@ -931,20 +931,12 @@ namespace MonoDevelop.MacIntegration.MainToolbar if (changed) { ReconstructString (); // announce new status if vo/a11y is enabled - if (MonoDevelop.Ide.Desktop.PlatformService.AccessibilityInUse) { - MakeAccessibilityAnnouncement (text); + if (IdeServices.DesktopService.AccessibilityInUse) { + IdeServices.DesktopService.MakeAccessibilityAnnouncement (text); } } } - static void MakeAccessibilityAnnouncement (string text) - { - using var message = new NSString (text); - using var dictionary = new NSDictionary (NSAccessibilityNotificationUserInfoKeys.AnnouncementKey, message, - NSAccessibilityNotificationUserInfoKeys.PriorityKey, NSAccessibilityPriorityLevel.High); - NSAccessibility.PostNotification (NSApplication.SharedApplication.AccessibilityMainWindow, NSAccessibilityNotifications.AnnouncementRequestedNotification, dictionary); - } - bool LoadText (string message, bool isMarkup, MessageType statusType) { message = message ?? ""; diff --git a/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore.Scaffolding/ScaffolderTemplateConfigurePage.cs b/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore.Scaffolding/ScaffolderTemplateConfigurePage.cs index f336fee108..26544416ed 100644 --- a/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore.Scaffolding/ScaffolderTemplateConfigurePage.cs +++ b/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore.Scaffolding/ScaffolderTemplateConfigurePage.cs @@ -62,16 +62,21 @@ namespace MonoDevelop.AspNetCore.Scaffolding table.Add (input, 1, rowIndex); input.Changed += (sender, args) => s.SelectedValue = input.Text; input.MinWidth = 300; + input.Accessible.LabelWidget = label; input.SetFocus (); break; case ComboField comboField: ComboBox comboBox; if (comboField.IsEditable) { - var comboBoxEntry = new ComboBoxEntry (); + var comboBoxEntry = new ComboBoxEntry { + Completes = true + }; + comboBoxEntry.TextEntry.Changed += (sender, args) => { if(!string.IsNullOrWhiteSpace(comboBoxEntry.TextEntry.Text)) comboField.SelectedValue = comboBoxEntry.TextEntry.Text; }; + if(comboField.PlaceholderText != null) comboBoxEntry.TextEntry.PlaceholderText = comboField.PlaceholderText; comboBox = comboBoxEntry; @@ -100,9 +105,8 @@ namespace MonoDevelop.AspNetCore.Scaffolding table.Add (label, 0, rowIndex, hpos: WidgetPlacement.End); table.Add (comboBox, 1, rowIndex); comboBox.TextInput += (sender, args) => comboField.SelectedValue = comboBox.SelectedText; - comboBox.SelectionChanged += (sender, args) => comboField.SelectedValue = comboBox.SelectedText; - + comboBox.Accessible.LabelWidget = label; break; case BoolFieldList boolFieldList: label.Text = boolFieldList.DisplayName; @@ -132,6 +136,7 @@ namespace MonoDevelop.AspNetCore.Scaffolding rowAdditionCount++; fileSelector.HeightRequest = 20; fileSelector.FileChanged += (sender, args) => fileField.SelectedValue = fileSelector.FileName; + fileSelector.Accessible.LabelWidget = label; break; } diff --git a/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore/AspNetCoreProjectExtension.cs b/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore/AspNetCoreProjectExtension.cs index e50b937d18..c2733f26c2 100644 --- a/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore/AspNetCoreProjectExtension.cs +++ b/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore/AspNetCoreProjectExtension.cs @@ -92,7 +92,7 @@ namespace MonoDevelop.AspNetCore protected override bool SupportsObject (WorkspaceObject item) { - return DotNetCoreSupportsObject (item) && IsWebProject ((DotNetProject)item); + return DotNetCoreSupportsObject (item) && SupportsLaunchSettings ((DotNetProject)item); } protected override bool IsSupportedFramework (TargetFrameworkMoniker framework) @@ -178,26 +178,30 @@ namespace MonoDevelop.AspNetCore protected override IEnumerable<ExecutionTarget> OnGetExecutionTargets (OperationContext ctx, ConfigurationSelector configuration, SolutionItemRunConfiguration runConfig) { - var result = new ExecutionTargetGroup (GettextCatalog.GetString ("Browser"), "MonoDevelop.AspNetCore.BrowserExecutionTargets"); - foreach (var browser in IdeServices.DesktopService.GetApplications ("https://localhost", Ide.Desktop.DesktopApplicationRole.Viewer)) { - if (browser.IsDefault) { - if (Project.HasMultipleTargetFrameworks) { - result.InsertRange (0, GetMultipleTargetFrameworkExecutionTargets (browser)); + if (IsWeb) { + var result = new ExecutionTargetGroup (GettextCatalog.GetString ("Browser"), "MonoDevelop.AspNetCore.BrowserExecutionTargets"); + foreach (var browser in IdeServices.DesktopService.GetApplications ("https://localhost", Ide.Desktop.DesktopApplicationRole.Viewer)) { + if (browser.IsDefault) { + if (Project.HasMultipleTargetFrameworks) { + result.InsertRange (0, GetMultipleTargetFrameworkExecutionTargets (browser)); + } else { + result.Insert (0, new AspNetCoreExecutionTarget (browser)); + } } else { - result.Insert (0, new AspNetCoreExecutionTarget (browser)); - } - } else { - if (Project.HasMultipleTargetFrameworks) { - result.AddRange (GetMultipleTargetFrameworkExecutionTargets (browser)); - } else { - result.Add (new AspNetCoreExecutionTarget (browser)); + if (Project.HasMultipleTargetFrameworks) { + result.AddRange (GetMultipleTargetFrameworkExecutionTargets (browser)); + } else { + result.Add (new AspNetCoreExecutionTarget (browser)); + } } } - } - return result.Count > 0 - ? new ExecutionTarget [] { result } - : base.OnGetExecutionTargets (ctx, configuration, runConfig); + return result.Count > 0 + ? new ExecutionTarget [] { result } + : base.OnGetExecutionTargets (ctx, configuration, runConfig); + } else { + return base.OnGetExecutionTargets (ctx, configuration, runConfig); + } } IEnumerable<ExecutionTarget> GetMultipleTargetFrameworkExecutionTargets (DesktopApplication browser) diff --git a/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore/AspNetCoreRunConfiguration.cs b/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore/AspNetCoreRunConfiguration.cs index 247dc9db71..4298218c7b 100644 --- a/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore/AspNetCoreRunConfiguration.cs +++ b/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore/AspNetCoreRunConfiguration.cs @@ -102,7 +102,7 @@ namespace MonoDevelop.AspNetCore EnvironmentVariables.Add ("ASPNETCORE_ENVIRONMENT", "Development"); #pragma warning disable CS0618 //disables warnings threw by obsolete methods used in nameof() if (CurrentProfile.LaunchBrowser == null) - CurrentProfile.LaunchBrowser = pset.GetValue (nameof (LaunchBrowser), true); + CurrentProfile.LaunchBrowser = pset.GetValue (nameof (LaunchBrowser), false); if (string.IsNullOrEmpty (CurrentProfile.TryGetApplicationUrl ())) { if (CurrentProfile.OtherSettings == null) diff --git a/main/src/addins/MonoDevelop.AspNetCore/Properties/MonoDevelop.AspNetCore.addin.xml b/main/src/addins/MonoDevelop.AspNetCore/Properties/MonoDevelop.AspNetCore.addin.xml index 6f3303009b..65267a3685 100644 --- a/main/src/addins/MonoDevelop.AspNetCore/Properties/MonoDevelop.AspNetCore.addin.xml +++ b/main/src/addins/MonoDevelop.AspNetCore/Properties/MonoDevelop.AspNetCore.addin.xml @@ -136,7 +136,7 @@ <Template
id="Microsoft.Worker.Empty.CSharp"
templateId="Microsoft.Worker.Empty.CSharp.3.1"
- _overrideName="Worker"
+ _overrideName="Worker Service"
_overrideDescription="An empty project template for creating a worker service."
path="${DotNetCoreSdk.3.1.Templates.Web.ProjectTemplates.nupkg}"
icon="md-netcore-empty-project"
@@ -144,7 +144,7 @@ wizard="MonoDevelop.AspNetCore.ProjectTemplateWizard"
supportedParameters="AspNetCoreWorker"
condition="UseNetCore31=true"
- category="netcore/app/aspnet"
+ category="netcore/app/general"
defaultParameters="IncludeLaunchSettings=true" />
<Template
id="Microsoft.Web.RazorPages.CSharp"
@@ -305,7 +305,7 @@ <Template
id="Microsoft.Worker.Empty.CSharp"
templateId="Microsoft.Worker.Empty.CSharp.3.0"
- _overrideName="Worker"
+ _overrideName="Worker Service"
_overrideDescription="An empty project template for creating a worker service."
path="${DotNetCoreSdk.3.0.Templates.Web.ProjectTemplates.nupkg}"
icon="md-netcore-empty-project"
@@ -313,7 +313,7 @@ wizard="MonoDevelop.AspNetCore.ProjectTemplateWizard"
supportedParameters="AspNetCoreWorker"
condition="UseNetCore30=true"
- category="netcore/app/aspnet"
+ category="netcore/app/general"
defaultParameters="IncludeLaunchSettings=true" />
<Template
id="Microsoft.Web.RazorPages.CSharp"
diff --git a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewImportsPage.xft.xml b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewImportsPage.xft.xml index 56710d91a3..baa9d9ce36 100644 --- a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewImportsPage.xft.xml +++ b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewImportsPage.xft.xml @@ -5,7 +5,7 @@ lastModified="2017/06/01"> <TemplateConfiguration> - <_Name>MVC View Imports Page</_Name> + <_Name>Razor View Imports</_Name> <Icon>md-html-file-icon</Icon> <_Category>ASP.NET Core</_Category> <LanguageName>C#</LanguageName> diff --git a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewLayoutPage.xft.xml b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewLayoutPage.xft.xml index dd332cb77b..8b68b7d9f3 100644 --- a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewLayoutPage.xft.xml +++ b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewLayoutPage.xft.xml @@ -5,7 +5,7 @@ lastModified="2017/06/01"> <TemplateConfiguration> - <_Name>MVC View Layout Page</_Name> + <_Name>Razor Layout</_Name> <Icon>md-html-file-icon</Icon> <_Category>ASP.NET Core</_Category> <LanguageName>C#</LanguageName> diff --git a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewPage.xft.xml b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewPage.xft.xml index 53a8aed637..7691331deb 100644 --- a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewPage.xft.xml +++ b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewPage.xft.xml @@ -5,7 +5,7 @@ lastModified="2017/06/01"> <TemplateConfiguration> - <_Name>MVC View Page</_Name> + <_Name>Razor View</_Name> <Icon>md-html-file-icon</Icon> <_Category>ASP.NET Core</_Category> <LanguageName>C#</LanguageName> diff --git a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewStartPage.xft.xml b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewStartPage.xft.xml index ee6429812a..3c4dfc9929 100644 --- a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewStartPage.xft.xml +++ b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewStartPage.xft.xml @@ -5,7 +5,7 @@ lastModified="2017/06/01"> <TemplateConfiguration> - <_Name>MVC View Start Page</_Name> + <_Name>Razor View Start</_Name> <Icon>md-html-file-icon</Icon> <_Category>ASP.NET Core</_Category> <LanguageName>C#</LanguageName> diff --git a/main/src/addins/MonoDevelop.AspNetCore/Templates/MvcController.xft.xml b/main/src/addins/MonoDevelop.AspNetCore/Templates/MvcController.xft.xml index 80890c85aa..cf6eea7130 100644 --- a/main/src/addins/MonoDevelop.AspNetCore/Templates/MvcController.xft.xml +++ b/main/src/addins/MonoDevelop.AspNetCore/Templates/MvcController.xft.xml @@ -5,7 +5,7 @@ lastModified="2017/05/01"> <TemplateConfiguration> - <_Name>MVC Controller Class</_Name> + <_Name>Controller Class</_Name> <Icon>md-html-file-icon</Icon> <_Category>ASP.NET Core</_Category> <LanguageName>C#</LanguageName> diff --git a/main/src/addins/MonoDevelop.Autotools/CustomMakefile.cs b/main/src/addins/MonoDevelop.Autotools/CustomMakefile.cs index 8fa40ae4cb..4965f364d5 100644 --- a/main/src/addins/MonoDevelop.Autotools/CustomMakefile.cs +++ b/main/src/addins/MonoDevelop.Autotools/CustomMakefile.cs @@ -262,7 +262,7 @@ namespace MonoDevelop.Autotools using (StreamWriter sw = new StreamWriter (fileName)) sw.Write (content); - UpdatedMakefiles++; + UpdatedMakefiles.Inc (1); } void ThrowMakefileVarNotFound (string var) diff --git a/main/src/addins/MonoDevelop.ConnectedServices/MonoDevelop.ConnectedServices.csproj b/main/src/addins/MonoDevelop.ConnectedServices/MonoDevelop.ConnectedServices.csproj index fc08ed6b63..408fc35ff6 100644 --- a/main/src/addins/MonoDevelop.ConnectedServices/MonoDevelop.ConnectedServices.csproj +++ b/main/src/addins/MonoDevelop.ConnectedServices/MonoDevelop.ConnectedServices.csproj @@ -13,10 +13,6 @@ <ItemGroup> <Reference Include="System" /> <Reference Include="System.Xml" /> - <Reference Include="ICSharpCode.NRefactory"> - <HintPath>..\..\..\build\bin\ICSharpCode.NRefactory.dll</HintPath> - <Private>False</Private> - </Reference> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj"> diff --git a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol.csproj b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol.csproj index abfc017abb..cffd4ddd46 100644 --- a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol.csproj +++ b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol.csproj @@ -48,6 +48,8 @@ <Compile Include="VsCodeStackFrame.cs" /> <Compile Include="VsCodeObjectSource.cs" /> <Compile Include="VsCodeBacktrace.cs" /> + <Compile Include="VSCodeVariableSource.cs" /> + <Compile Include="VSCodeEvaluationSource.cs" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> </Project> diff --git a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeDebuggerSession.cs b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeDebuggerSession.cs index 5da7eda093..ff06cef278 100644 --- a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeDebuggerSession.cs +++ b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeDebuggerSession.cs @@ -23,20 +23,23 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + using System; -using Mono.Debugging.Client; -using System.Diagnostics; -using Mono.Debugging.Backend; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using System.IO; +using System.Linq; using System.Text; -using Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages; +using System.Diagnostics; +using System.Threading.Tasks; +using System.Collections.Generic; + +using Mono.Debugging.Client; + using Microsoft.VisualStudio.Shared.VSCodeDebugProtocol; -using System.Threading; +using Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages; + using MonoDevelop.Core; using MonoDevelop.Core.Execution; + using MonoFunctionBreakpoint = Mono.Debugging.Client.FunctionBreakpoint; using VsCodeFunctionBreakpoint = Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages.FunctionBreakpoint; @@ -44,8 +47,23 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol { public abstract class VSCodeDebuggerSession : DebuggerSession { + readonly Dictionary<string, bool> enumTypes = new Dictionary<string, bool> (); int currentThreadId; + internal bool IsEnum (string type, int frameId) + { + if (enumTypes.TryGetValue (type, out var isEnum)) + return isEnum; + + var request = new EvaluateRequest ($"typeof ({type}).IsEnum") { FrameId = frameId }; + var response = protocolClient.SendRequestSync (request); + + isEnum = response.Result.Equals ("true", StringComparison.OrdinalIgnoreCase); + enumTypes.Add (type, isEnum); + + return isEnum; + } + protected override void OnContinue () { protocolClient.SendRequestSync (new ContinueRequest (currentThreadId)); @@ -156,6 +174,7 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol } bool currentExceptionState = false; + bool unhandleExceptionRegistered = false; void UpdateExceptions () { //Disposed @@ -163,11 +182,13 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol return; var hasCustomExceptions = breakpoints.Select (b => b.Key).OfType<Catchpoint> ().Any (e => e.Enabled); - if (currentExceptionState != hasCustomExceptions) { + if (currentExceptionState != hasCustomExceptions || !unhandleExceptionRegistered) { currentExceptionState = hasCustomExceptions; - protocolClient.SendRequest (new SetExceptionBreakpointsRequest ( - Capabilities.ExceptionBreakpointFilters.Where (f => hasCustomExceptions || (f.Default ?? false)).Select (f => f.Filter).ToList () - ), null); + var exceptionRequest = new SetExceptionBreakpointsRequest ( + Capabilities.ExceptionBreakpointFilters.Where (f => hasCustomExceptions || (f.Default ?? false)).Select (f => f.Filter).ToList ()); + exceptionRequest.ExceptionOptions = new List<ExceptionOptions> () {new ExceptionOptions(ExceptionBreakMode.UserUnhandled)}; + protocolClient.SendRequest (exceptionRequest, null); + unhandleExceptionRegistered = true; } } @@ -227,7 +248,7 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol startInfo.StandardOutputEncoding = Encoding.UTF8; startInfo.StandardOutputEncoding = Encoding.UTF8; startInfo.UseShellExecute = false; - if (!MonoDevelop.Core.Platform.IsWindows) + if (!Platform.IsWindows) startInfo.EnvironmentVariables ["PATH"] = Environment.GetEnvironmentVariable ("PATH") + ":/usr/local/share/dotnet/"; debugAgentProcess = Process.Start (startInfo); debugAgentProcess.EnableRaisingEvents = true; @@ -236,7 +257,7 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol protocolClient.RequestReceived += OnDebugAdaptorRequestReceived; protocolClient.Run (); protocolClient.EventReceived += HandleEvent; - InitializeRequest initRequest = CreateInitRequest (); + var initRequest = CreateInitRequest (); Capabilities = protocolClient.SendRequestSync (initRequest); } @@ -265,9 +286,10 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol { pauseWhenFinished = !startInfo.CloseExternalConsoleOnExit; StartDebugAgent (); - LaunchRequest launchRequest = CreateLaunchRequest (startInfo); + var launchRequest = CreateLaunchRequest (startInfo); protocolClient.SendRequestSync (launchRequest); protocolClient.SendRequestSync (new ConfigurationDoneRequest ()); + UpdateExceptions (); } protected void Attach (long processId) @@ -277,6 +299,7 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol protocolClient.SendRequestSync (attachRequest); OnStarted (); protocolClient.SendRequestSync (new ConfigurationDoneRequest ()); + UpdateExceptions (); } protected internal DebugProtocolHost protocolClient; @@ -316,7 +339,7 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol bool? EvaluateCondition (int frameId, string exp) { - var response = protocolClient.SendRequestSync (new EvaluateRequest (exp, frameId)).Result; + var response = protocolClient.SendRequestSync (new EvaluateRequest (exp) { FrameId = frameId }).Result; if (bool.TryParse (response, out var result)) return result; @@ -347,6 +370,7 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol return string.IsNullOrWhiteSpace (catchpoint.ConditionExpression) || EvaluateCondition (frameId, catchpoint.ConditionExpression) != false; } + protected void HandleEvent (object sender, EventReceivedEventArgs obj) { Task.Run (() => { @@ -403,12 +427,16 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol // It's OK to evaluate expressions in external code stackFrame = (VsCodeStackFrame)backtrace.GetFrame (0); } - - if (!breakpoints.Select (b => b.Key).OfType<Catchpoint> ().Any (c => ShouldStopOnExceptionCatchpoint (c, stackFrame.frameId))) { - OnContinue (); - return; + var response = protocolClient.SendRequestSync (new ExceptionInfoRequest (body.ThreadId ?? -1)); + if (response.BreakMode.Equals (ExceptionBreakMode.UserUnhandled)) { + args = new TargetEventArgs (TargetEventType.UnhandledException); + } else { + if (!breakpoints.Select (b => b.Key).OfType<Catchpoint> ().Any (c => ShouldStopOnExceptionCatchpoint (c, stackFrame.frameId))) { + OnContinue (); + return; + } + args = new TargetEventArgs (TargetEventType.ExceptionThrown); } - args = new TargetEventArgs (TargetEventType.ExceptionThrown); break; default: throw new NotImplementedException (body.Reason.ToString ()); @@ -455,7 +483,7 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol } break; } - }); + }).Ignore (); } List<string> pathsWithBreakpoints = new List<string> (); @@ -502,13 +530,13 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol return; protocolClient.SendRequest ( - new SetBreakpointsRequest (source) {
+ new SetBreakpointsRequest (source) { Breakpoints = sourceFile.Select (b => new SourceBreakpoint { Line = b.OriginalLine, Column = b.OriginalColumn, - Condition = b.ConditionExpression,
- HitCondition = GetHitCondition(b)
- }).ToList ()
+ Condition = b.ConditionExpression, + HitCondition = GetHitCondition(b) + }).ToList () }, (obj) => { Task.Run (() => { for (int i = 0; i < obj.Breakpoints.Count; i++) { @@ -516,7 +544,7 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol if (obj.Breakpoints [i].Line != sourceFile.ElementAt (i).OriginalLine) breakpoints [sourceFile.ElementAt (i)].AdjustBreakpointLocation (obj.Breakpoints [i].Line, obj.Breakpoints [i].Column ?? 1); } - }); + }).Ignore (); }); } diff --git a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeEvaluationSource.cs b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeEvaluationSource.cs new file mode 100644 index 0000000000..235b7adaa2 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeEvaluationSource.cs @@ -0,0 +1,117 @@ +using System; +using System.Globalization; + +using Mono.Debugging.Client; +using Mono.Debugging.Evaluation; + +using Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages; + +namespace MonoDevelop.Debugger.VsCodeDebugProtocol +{ + class VSCodeEvaluationSource : VSCodeObjectSource + { + readonly EvaluateResponse response; + readonly string expression; + readonly string display; + readonly string value; + readonly string name; + readonly string type; + + public VSCodeEvaluationSource (VSCodeDebuggerSession session, string expression, EvaluateResponse response, int frameId) : base (session, 0, frameId) + { + this.expression = expression; + this.response = response; + + // FIXME: can we use PresentationHint.Attributes == VariablePresentationHint.AttributesValue.FailedEvaluation instead? + if (response.Type == null) { + if (IsCSError (118, "is a namespace but is used like a variable", response.Result, out string ns)) { + Flags = ObjectValueFlags.Namespace; + display = name = value = ns; + type = "<namespace>"; + return; + } + + if (IsCSError (119, "is a type, which is not valid in the given context", response.Result, out string vtype)) { + if (expression.StartsWith ("global::", StringComparison.Ordinal)) + vtype = expression.Substring ("global::".Length); + + display = name = value = ObjectValueAdaptor.GetCSharpTypeName (vtype); + Flags = ObjectValueFlags.Type; + type = "<type>"; + return; + } + } + + var actualType = GetActualTypeName (response.Type); + + Flags = GetFlags (response.PresentationHint); + type = actualType.Replace (", ", ","); + name = expression; + + if (actualType != "void") + value = GetFixedValue (response.Result, type, actualType); + else + value = "No return value."; + display = response.Result; + + if (name[0] == '[') + Flags |= ObjectValueFlags.ArrayElement; + + if (type == null || value == $"'{name}' threw an exception of type '{type}'") + Flags = ObjectValueFlags.Error; + } + + protected override string Display { + get { return display; } + } + + protected override string Expression { + get { return expression; } + } + + protected override string Name { + get { return name; } + } + + protected override string Type { + get { return type; } + } + + protected override string Value { + get { return value; } + } + + protected override int VariablesReference { + get { return response.VariablesReference; } + } + + static bool IsCSError (int code, string message, string value, out string newValue) + { + var prefix = string.Format (CultureInfo.InvariantCulture, "error CS{0:D4}: '", code); + + newValue = null; + + if (value == null || !value.StartsWith (prefix, StringComparison.Ordinal)) + return false; + + int startIndex = prefix.Length; + int index = startIndex; + + while (index < value.Length && value [index] != '\'') + index++; + + newValue = value.Substring (startIndex, index - startIndex); + index++; + + if (index >= value.Length || value [index] != ' ') + return false; + + index++; + + if (index + message.Length != value.Length) + return false; + + return string.CompareOrdinal (value, index, message, 0, message.Length) == 0; + } + } +} diff --git a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeVariableSource.cs b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeVariableSource.cs new file mode 100644 index 0000000000..789e4ef0c4 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeVariableSource.cs @@ -0,0 +1,76 @@ +using System; + +using Mono.Debugging.Client; + +using Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages; + +namespace MonoDevelop.Debugger.VsCodeDebugProtocol +{ + class VSCodeVariableSource : VSCodeObjectSource + { + readonly Variable variable; + readonly string display; + readonly string value; + readonly string name; + readonly string type; + + public VSCodeVariableSource (VSCodeDebuggerSession session, Variable variable, int parentVariablesReference, int frameId) : base (session, parentVariablesReference, frameId) + { + this.variable = variable; + + var actualType = GetActualTypeName (variable.Type); + + Flags = parentVariablesReference > 0 ? ObjectValueFlags.None : ObjectValueFlags.ReadOnly; + Flags |= GetFlags (variable.PresentationHint); + name = GetFixedVariableName (variable.Name); + type = actualType.Replace (", ", ","); + + if (actualType != "void") + value = GetFixedValue (variable.Value, type, actualType); + else + value = "No return value."; + display = variable.Value; + + if (name[0] == '[') + Flags |= ObjectValueFlags.ArrayElement; + + if (type == null || value == $"'{name}' threw an exception of type '{type}'") + Flags = ObjectValueFlags.Error; + } + + protected override string Display { + get { return display; } + } + + protected override string Expression { + get { return variable.EvaluateName; } + } + + protected override string Name { + get { return name; } + } + + protected override string Type { + get { return type; } + } + + protected override string Value { + get { return value; } + } + + protected override int VariablesReference { + get { return variable.VariablesReference; } + } + + static string GetFixedVariableName (string name) + { + // Check for a type attribute and strip it off. + var index = name.LastIndexOf (" [", StringComparison.Ordinal); + + if (index != -1) + return name.Remove (index); + + return name; + } + } +} diff --git a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeBacktrace.cs b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeBacktrace.cs index 9a7c611876..7fe678a1fe 100644 --- a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeBacktrace.cs +++ b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeBacktrace.cs @@ -2,39 +2,45 @@ using System; using System.Linq; using System.Collections.Generic; +using Mono.Debugging.Client; +using Mono.Debugging.Backend; + using Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages; -using Mono.Debugging.Backend; -using Mono.Debugging.Client; +using MonoDevelop.Core; -using VsFormat = Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages.StackFrameFormat; +using StackFrame = Mono.Debugging.Client.StackFrame; +using VsStackFrame = Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages.StackFrame; +using VsFrameFormat = Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages.StackFrameFormat; namespace MonoDevelop.Debugger.VsCodeDebugProtocol { class VSCodeDebuggerBacktrace : IBacktrace { + readonly VSCodeDebuggerSession session; + readonly VsStackFrame[] frames; + readonly List<Scope>[] scopes; + readonly VsFrameFormat format; readonly int threadId; - VSCodeDebuggerSession vsCodeDebuggerSession; - int totalFramesCount; - Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages.StackFrame [] frames; - VsFormat frame0Format; - public VSCodeDebuggerBacktrace (VSCodeDebuggerSession vsCodeDebuggerSession, int threadId) + public VSCodeDebuggerBacktrace (VSCodeDebuggerSession session, int threadId) { + this.session = session; this.threadId = threadId; - this.vsCodeDebuggerSession = vsCodeDebuggerSession; - frame0Format = VsCodeStackFrame.GetStackFrameFormat (vsCodeDebuggerSession.EvaluationOptions); - var body = vsCodeDebuggerSession.protocolClient.SendRequestSync (new StackTraceRequest (threadId) { StartFrame = 0, Levels = 1, Format = frame0Format }); - totalFramesCount = body.TotalFrames ?? 0; - frames = new Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages.StackFrame [totalFramesCount]; - if (totalFramesCount > 0 && body.StackFrames.Count > 0) - frames [0] = body.StackFrames [0]; + + format = VsCodeStackFrame.GetStackFrameFormat (session.EvaluationOptions); + + var response = session.protocolClient.SendRequestSync (new StackTraceRequest (threadId) { StartFrame = 0, Levels = 1, Format = format }); + + FrameCount = response.TotalFrames ?? 0; + frames = new VsStackFrame[FrameCount]; + scopes = new List<Scope>[FrameCount]; + if (FrameCount > 0 && response.StackFrames.Count > 0) + frames[0] = response.StackFrames[0]; } public int FrameCount { - get { - return totalFramesCount; - } + get; private set; } public AssemblyLine [] Disassemble (int frameIndex, int firstLine, int count) @@ -42,19 +48,42 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol throw new NotImplementedException (); } + List<Scope> GetScopes (int frameIndex) + { + if (scopes[frameIndex] == null) { + var response = session.protocolClient.SendRequestSync (new ScopesRequest (frames[frameIndex].Id)); + scopes[frameIndex] = response.Scopes; + } + + return scopes[frameIndex]; + } + public ObjectValue [] GetAllLocals (int frameIndex, EvaluationOptions options) { - List<ObjectValue> results = new List<ObjectValue> (); - var scopeBody = vsCodeDebuggerSession.protocolClient.SendRequestSync (new ScopesRequest (frames [frameIndex].Id)); - foreach (var variablesGroup in scopeBody.Scopes) { - using (var timer = vsCodeDebuggerSession.EvaluationStats.StartTimer ()) { - var varibles = vsCodeDebuggerSession.protocolClient.SendRequestSync (new VariablesRequest (variablesGroup.VariablesReference)); - foreach (var variable in varibles.Variables) { - results.Add (VsCodeVariableToObjectValue (vsCodeDebuggerSession, variable.Name, variable.EvaluateName, variable.Type, variable.Value, variable.VariablesReference, variablesGroup.VariablesReference, frames [frameIndex].Id)); + var results = new List<ObjectValue> (); + var frame = frames[frameIndex]; + + foreach (var scope in GetScopes (frameIndex)) { + using (var timer = session.EvaluationStats.StartTimer ()) { + VariablesResponse response; + + try { + response = session.protocolClient.SendRequestSync (new VariablesRequest (scope.VariablesReference)); + } catch (Exception ex) { + LoggingService.LogError ($"[VsCodeDebugger] Failed to get local variables for the scope: {scope.Name}", ex); + timer.Success = false; + continue; + } + + foreach (var variable in response.Variables) { + var source = new VSCodeVariableSource (session, variable, scope.VariablesReference, frame.Id); + results.Add (source.GetValue (default (ObjectPath), null)); } + timer.Success = true; } } + return results.ToArray (); } @@ -71,54 +100,75 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol public ObjectValue [] GetExpressionValues (int frameIndex, string [] expressions, EvaluationOptions options) { var results = new List<ObjectValue> (); + var frame = frames[frameIndex]; + foreach (var expr in expressions) { - using (var timer = vsCodeDebuggerSession.EvaluationStats.StartTimer ()) { - var responseBody = vsCodeDebuggerSession.protocolClient.SendRequestSync (new EvaluateRequest (expr) { FrameId = frames[frameIndex].Id }); - results.Add (VsCodeVariableToObjectValue (vsCodeDebuggerSession, expr, expr, responseBody.Type, responseBody.Result, responseBody.VariablesReference, 0, frames [frameIndex].Id)); + using (var timer = session.EvaluationStats.StartTimer ()) { + var response = session.protocolClient.SendRequestSync (new EvaluateRequest (expr) { FrameId = frame.Id }); + var source = new VSCodeEvaluationSource (session, expr, response, frame.Id); + + results.Add (source.GetValue (default (ObjectPath), null)); timer.Success = true; } } + return results.ToArray (); } - internal static ObjectValue VsCodeVariableToObjectValue (VSCodeDebuggerSession vsCodeDebuggerSession, string name, string evalName, string type, string value, int variablesReference, int parentVariablesReference, int frameId) + ObjectValue[] GetVariables (int frameIndex, string scopeName) { - return new VSCodeObjectSource (vsCodeDebuggerSession, variablesReference, parentVariablesReference, name, type, evalName, frameId, value).GetValue (default (ObjectPath), null); - } + var results = new List<ObjectValue> (); + var frame = frames[frameIndex]; - public ObjectValue [] GetLocalVariables (int frameIndex, EvaluationOptions options) - { - List<ObjectValue> results = new List<ObjectValue> (); - var scopeBody = vsCodeDebuggerSession.protocolClient.SendRequestSync (new ScopesRequest (frames [frameIndex].Id)); - foreach (var variablesGroup in scopeBody.Scopes) { - using (var timer = vsCodeDebuggerSession.EvaluationStats.StartTimer ()) { - var varibles = vsCodeDebuggerSession.protocolClient.SendRequestSync (new VariablesRequest (variablesGroup.VariablesReference)); - foreach (var variable in varibles.Variables) { - results.Add (ObjectValue.CreatePrimitive (null, new ObjectPath (variable.Name), variable.Type ?? "<unknown>", new EvaluationResult (variable.Value), ObjectValueFlags.None)); + foreach (var scope in GetScopes (frameIndex)) { + if (!scope.Name.Equals (scopeName, StringComparison.Ordinal)) + continue; + + using (var timer = session.EvaluationStats.StartTimer ()) { + VariablesResponse response; + + try { + response = session.protocolClient.SendRequestSync (new VariablesRequest (scope.VariablesReference)); + } catch (Exception ex) { + LoggingService.LogError ($"[VsCodeDebugger] Failed to get local variables for the scope: {scope.Name}", ex); + timer.Success = false; + continue; + } + + foreach (var variable in response.Variables) { + var source = new VSCodeVariableSource (session, variable, scope.VariablesReference, frame.Id); + results.Add (source.GetValue (default (ObjectPath), null)); } + timer.Success = true; } } + return results.ToArray (); } + public ObjectValue [] GetLocalVariables (int frameIndex, EvaluationOptions options) + { + return GetVariables (frameIndex, "Locals"); + } + public ObjectValue [] GetParameters (int frameIndex, EvaluationOptions options) { - return new ObjectValue [0];//TODO: Find out how to seperate Params from other Locals + return GetVariables (frameIndex, "Arguments"); } - public Mono.Debugging.Client.StackFrame [] GetStackFrames (int firstIndex, int lastIndex) + public StackFrame [] GetStackFrames (int firstIndex, int lastIndex) { //Optimisation for getting 1st frame of thread(used for ThreadPad) - if (firstIndex == 0 && lastIndex == 1 && totalFramesCount > 0) { - return new Mono.Debugging.Client.StackFrame [] { new VsCodeStackFrame (frame0Format, threadId, 0, frames [0]) }; - } - var stackFrames = new Mono.Debugging.Client.StackFrame [Math.Min (lastIndex - firstIndex, totalFramesCount - firstIndex)]; - var format = VsCodeStackFrame.GetStackFrameFormat (vsCodeDebuggerSession.EvaluationOptions); - var body = vsCodeDebuggerSession.protocolClient.SendRequestSync (new StackTraceRequest (threadId) { StartFrame = firstIndex, Levels = stackFrames.Length, Format = format }); + if (firstIndex == 0 && lastIndex == 1 && FrameCount > 0) + return new StackFrame[] { new VsCodeStackFrame (this.format, threadId, 0, frames[0]) }; + + var stackFrames = new StackFrame [Math.Min (lastIndex - firstIndex, FrameCount - firstIndex)]; + var format = VsCodeStackFrame.GetStackFrameFormat (session.EvaluationOptions); + var body = session.protocolClient.SendRequestSync (new StackTraceRequest (threadId) { StartFrame = firstIndex, Levels = stackFrames.Length, Format = format }); for (int i = 0; i < stackFrames.Length; i++) { - frames [i + firstIndex] = body.StackFrames [i]; - stackFrames [i] = new VsCodeStackFrame (format, threadId, i, body.StackFrames [i]); + frames[i + firstIndex] = body.StackFrames [i]; + stackFrames[i] = new VsCodeStackFrame (format, threadId, i, body.StackFrames [i]); } return stackFrames; } diff --git a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeObjectSource.cs b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeObjectSource.cs index 19c8c4fa77..bae1cf7637 100644 --- a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeObjectSource.cs +++ b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeObjectSource.cs @@ -1,37 +1,129 @@ using System; -using System.Linq; using System.Text; using System.Globalization; +using System.Collections.Generic; -using Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages; - -using Mono.Debugging.Backend; using Mono.Debugging.Client; -using Mono.Debugging.Evaluation; +using Mono.Debugging.Backend; + +using Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages; namespace MonoDevelop.Debugger.VsCodeDebugProtocol { - class VSCodeObjectSource : IObjectValueSource + abstract class VSCodeObjectSource : IObjectValueSource { - const VariablePresentationHint.AttributesValue ConstantReadOnlyStatic = VariablePresentationHint.AttributesValue.Constant | VariablePresentationHint.AttributesValue.ReadOnly | VariablePresentationHint.AttributesValue.Static; static readonly char[] CommaDotOrSquareEndBracket = { ',', '.', ']' }; static readonly char[] CommaOrSquareEndBracket = { ',', ']' }; static readonly char[] LessThanOrSquareBracket = { '<', '[' }; ObjectValue[] objValChildren; - readonly VSCodeDebuggerSession vsCodeDebuggerSession; - readonly int parentVariablesReference; - readonly ObjectValueFlags flags; - readonly int variablesReference; - readonly int frameId; - readonly string evalName; - readonly string display; - readonly string name; - readonly string type; - readonly string val; - - static string GetActualTypeName (string type) + protected VSCodeObjectSource (VSCodeDebuggerSession session, int parentVariablesReference, int frameId) + { + ParentVariablesReference = parentVariablesReference; + Session = session; + FrameId = frameId; + } + + protected abstract string Display { + get; + } + + protected abstract string Expression { + get; + } + + protected ObjectValueFlags Flags { + get; set; + } + + protected int FrameId { + get; private set; + } + + protected abstract string Name { + get; + } + + protected int ParentVariablesReference { + get; + } + + protected VSCodeDebuggerSession Session { + get; private set; + } + + protected abstract string Type { + get; + } + + protected abstract string Value { + get; + } + + protected abstract int VariablesReference { + get; + } + + protected ObjectValueFlags GetFlags (VariablePresentationHint hint) + { + var flags = ObjectValueFlags.None; + + if (hint != null) { + if (hint.Attributes.HasValue) { + var attributes = hint.Attributes.Value; + + if ((attributes & VariablePresentationHint.AttributesValue.FailedEvaluation) != 0) + return ObjectValueFlags.Error; + if ((attributes & VariablePresentationHint.AttributesValue.Constant) != 0) + flags |= ObjectValueFlags.Literal; + if ((attributes & VariablePresentationHint.AttributesValue.ReadOnly) != 0) + flags |= ObjectValueFlags.ReadOnly; + if ((attributes & VariablePresentationHint.AttributesValue.Static) != 0) + flags |= ObjectValueFlags.ReadOnly; + if ((attributes & VariablePresentationHint.AttributesValue.CanHaveObjectId) != 0) + flags |= ObjectValueFlags.Primitive; + if ((attributes & VariablePresentationHint.AttributesValue.HasObjectId) != 0) + flags |= ObjectValueFlags.Object; + } + + if (hint.Kind.HasValue) { + var kind = hint.Kind.Value; + + if ((kind & VariablePresentationHint.KindValue.Property) != 0) + flags |= ObjectValueFlags.Property; + if ((kind & VariablePresentationHint.KindValue.BaseClass) != 0) + flags |= ObjectValueFlags.Type; + if ((kind & VariablePresentationHint.KindValue.Class) != 0) + flags |= ObjectValueFlags.Type; + if ((kind & VariablePresentationHint.KindValue.InnerClass) != 0) + flags |= ObjectValueFlags.Type; + if ((kind & VariablePresentationHint.KindValue.Interface) != 0) + flags |= ObjectValueFlags.Type; + if ((kind & VariablePresentationHint.KindValue.MostDerivedClass) != 0) + flags |= ObjectValueFlags.Type; + if ((kind & VariablePresentationHint.KindValue.Data) != 0) + flags |= ObjectValueFlags.Variable; + } + + if (hint.Visibility.HasValue) { + var visibility = hint.Visibility.Value; + + if ((visibility & VariablePresentationHint.VisibilityValue.Protected) != 0) + flags |= ObjectValueFlags.Protected; + if ((visibility & VariablePresentationHint.VisibilityValue.Internal) != 0) + flags |= ObjectValueFlags.Internal; + if ((visibility & VariablePresentationHint.VisibilityValue.Private) != 0) + flags |= ObjectValueFlags.Private; + if ((visibility & VariablePresentationHint.VisibilityValue.Public) != 0) + flags |= ObjectValueFlags.Public; + } + } + + return flags; + } + + protected static string GetActualTypeName (string type) { int startIndex; @@ -51,17 +143,6 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol return type; } - static string GetFixedVariableName (string name) - { - // Check for a type attribute and strip it off. - var index = name.LastIndexOf (" [", StringComparison.Ordinal); - - if (index != -1) - return name.Remove (index); - - return name; - } - static bool IsMultiDimensionalArray (string type, out int arrayIndexer) { int index = type.IndexOfAny (LessThanOrSquareBracket); @@ -91,11 +172,56 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol return index < type.Length && type[index] == ','; } + bool IsPotentialEnumValue (string value) + { + if (string.IsNullOrEmpty (value)) + return false; + + // Note: An enum value must begin with a letter + if (!char.IsLetter (value[0])) + return false; + + // Note: if the value has a '|', it's probably an enum (can it be anything else?) + if (value.IndexOf ('|') != -1) + return true; + + for (int i = 1; i < value.Length; i++) { + if (char.IsLetterOrDigit (value[i]) || value[i] == '_') + continue; + + return false; + } + + return true; + } + + bool IsEnum (string displayType, string value) + { + if (string.IsNullOrEmpty (displayType)) + return false; + + // Note: generic types cannot be enums + if (displayType[displayType.Length - 1] == '>') + return false; + + // Note: true and false look like enum values but aren't + if (displayType.Equals ("bool", StringComparison.Ordinal)) + return false; + + if (!IsPotentialEnumValue (value)) + return false; + + return Session.IsEnum (displayType, FrameId); + } + // Note: displayType will often have spaces after commas - string GetFixedValue (string value, string canonType, string displayType) + protected string GetFixedValue (string value, string canonType, string displayType) { int arrayIndex; + if (value.Equals ("null", StringComparison.Ordinal)) + return value; + if (IsMultiDimensionalArray (displayType, out arrayIndex)) { var arrayType = displayType.Substring (0, arrayIndex); var prefix = $"{{{arrayType}["; @@ -148,212 +274,220 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol return compacted.ToString (); } - } else if (canonType == "char") { + } else if (canonType.Equals ("char", StringComparison.Ordinal)) { int startIndex = value.IndexOf ('\''); if (startIndex != -1) return value.Substring (startIndex); - } else { - var request = new EvaluateRequest ($"typeof ({displayType}).IsEnum") { FrameId = frameId }; - var result = vsCodeDebuggerSession.protocolClient.SendRequestSync (request); - - if (result.Result.Equals ("true", StringComparison.OrdinalIgnoreCase)) { - int endIndex = value.IndexOf (" | ", StringComparison.Ordinal); + } else if (IsEnum (displayType, value)) { + int endIndex = value.IndexOf (" | ", StringComparison.Ordinal); - if (endIndex != -1) { - // The value a bitwise-or'd set of enum values - var expanded = new StringBuilder (); - int index = 0; + if (endIndex != -1) { + // The value is a bitwise-or'd set of enum values + var expanded = new StringBuilder (); + int index = 0; - while (index < value.Length) { - endIndex = value.IndexOf (" | ", index, StringComparison.Ordinal); - string enumValue; - - if (endIndex != -1) - enumValue = value.Substring (index, endIndex - index); - else if (index > 0) - enumValue = value.Substring (index); - else - enumValue = value; + while (index < value.Length) { + endIndex = value.IndexOf (" | ", index, StringComparison.Ordinal); + string enumValue; - expanded.Append (canonType).Append ('.').Append (enumValue); + if (endIndex != -1) + enumValue = value.Substring (index, endIndex - index); + else if (index > 0) + enumValue = value.Substring (index); + else + enumValue = value; - if (endIndex == -1) - break; + expanded.Append (canonType).Append ('.').Append (enumValue); - expanded.Append (" | "); - index = endIndex + 3; - } + if (endIndex == -1) + break; - return expanded.ToString (); + expanded.Append (" | "); + index = endIndex + 3; } - return canonType + "." + value; + return expanded.ToString (); } + + return canonType + "." + value; } return value; } - static bool IsCSError (int code, string message, string value, out string newValue) + public ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options) { - var prefix = string.Format (CultureInfo.InvariantCulture, "error CS{0:D4}: '", code); - - newValue = null; - - if (value == null || !value.StartsWith (prefix, StringComparison.Ordinal)) - return false; - - int startIndex = prefix.Length; - int index = startIndex; - - while (index < value.Length && value[index] != '\'') - index++; - - newValue = value.Substring (startIndex, index - startIndex); - index++; - - if (index >= value.Length || value[index] != ' ') - return false; - - index++; + if (objValChildren == null) { + if (VariablesReference > 0) { + using (var timer = Session.EvaluationStats.StartTimer ()) { + var response = Session.protocolClient.SendRequestSync (new VariablesRequest (VariablesReference)); + var children = new List<ObjectValue> (); + + foreach (var variable in response.Variables) { + var source = new VSCodeVariableSource (Session, variable, VariablesReference, FrameId); + children.Add (source.GetValue (default (ObjectPath), null)); + } - if (index + message.Length != value.Length) - return false; + objValChildren = children.ToArray (); + timer.Success = true; + } + } else { + objValChildren = new ObjectValue[0]; + } + } - return string.CompareOrdinal (value, index, message, 0, message.Length) == 0; + return objValChildren; } - public VSCodeObjectSource (VSCodeDebuggerSession vsCodeDebuggerSession, int variablesReference, int parentVariablesReference, string name, string type, string evalName, int frameId, string val) + static string Quote (string text) { - this.vsCodeDebuggerSession = vsCodeDebuggerSession; - this.parentVariablesReference = parentVariablesReference; - this.variablesReference = variablesReference; - this.evalName = evalName; - this.frameId = frameId; - - if (type == null) { - if (IsCSError (118, "is a namespace but is used like a variable", val, out string ns)) { - this.display = this.name = this.val = ns; - this.flags = ObjectValueFlags.Namespace; - this.type = "<namespace>"; - return; - } - - if (IsCSError (119, "is a type, which is not valid in the given context", val, out string vtype)) { - if (name.StartsWith ("global::", StringComparison.Ordinal)) - vtype = name.Substring ("global::".Length); - - this.display = this.name = this.val = ObjectValueAdaptor.GetCSharpTypeName (vtype); - this.flags = ObjectValueFlags.Type; - this.type = "<type>"; - return; + var quoted = new StringBuilder (text.Length + 2); + + quoted.Append ('"'); + for (int i = 0; i < text.Length; i++) { + char c = text [i]; + + switch (c) { + case '\0': quoted.Append ("\\0"); break; + case '\a': quoted.Append ("\\a"); break; + case '\b': quoted.Append ("\\b"); break; + case '\n': quoted.Append ("\\n"); break; + case '\r': quoted.Append ("\\r"); break; + case '\t': quoted.Append ("\\t"); break; + case '\v': quoted.Append ("\\v"); break; + case '"': quoted.Append ("\\\""); break; + case '\\': quoted.Append ("\\\\"); break; + default: + if (c < ' ') { + quoted.AppendFormat (CultureInfo.InvariantCulture, "\\x{0:2}", c); + } else { + quoted.Append (c); + } + break; } } + quoted.Append ('"'); - var actualType = GetActualTypeName (type); - - this.flags = parentVariablesReference > 0 ? ObjectValueFlags.None : ObjectValueFlags.ReadOnly; - this.type = actualType.Replace (", ", ","); - this.name = GetFixedVariableName (name); - - if (actualType != "void") - this.val = GetFixedValue (val, this.type, actualType); - else - this.val = "No return value."; - this.display = val; - - if (this.name[0] == '[') - flags |= ObjectValueFlags.ArrayElement; - - if (type == null || val == $"'{this.name}' threw an exception of type '{this.type}'") - flags |= ObjectValueFlags.Error; + return quoted.ToString (); } - public ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options) + static string Unquote (string text) { - if (objValChildren == null) { - if (variablesReference <= 0) { - objValChildren = new ObjectValue[0]; - } else { - using (var timer = vsCodeDebuggerSession.EvaluationStats.StartTimer ()) { - var children = vsCodeDebuggerSession.protocolClient.SendRequestSync (new VariablesRequest ( - variablesReference - )).Variables; - objValChildren = children.Select (c => VSCodeDebuggerBacktrace.VsCodeVariableToObjectValue (vsCodeDebuggerSession, c.Name, c.EvaluateName, c.Type, c.Value, c.VariablesReference, variablesReference, frameId)).ToArray (); - timer.Success = true; - } + var unquoted = new char [text.Length - 2]; + bool escaped = false; + int count = 0; + + for (int i = 1; i < text.Length - 1; i++) { + char c = text [i]; + + switch (c) { + case '\\': + if (escaped) + unquoted [count++] = '\\'; + escaped = !escaped; + break; + case '0': + unquoted [count++] = escaped ? '\0' : c; + escaped = false; + break; + case 'a': + unquoted [count++] = escaped ? '\a' : c; + escaped = false; + break; + case 'b': + unquoted [count++] = escaped ? '\b' : c; + escaped = false; + break; + case 'n': + unquoted [count++] = escaped ? '\n' : c; + escaped = false; + break; + case 'r': + unquoted [count++] = escaped ? '\r' : c; + escaped = false; + break; + case 't': + unquoted [count++] = escaped ? '\t' : c; + escaped = false; + break; + case 'v': + unquoted [count++] = escaped ? '\v' : c; + escaped = false; + break; + default: + unquoted [count++] = c; + escaped = false; + break; } } - return objValChildren; + + return new string (unquoted, 0, count); } class RawString : IRawValueString { - string val; - - public RawString (string val) + public RawString (string value) { - this.val = val.Remove (val.Length - 1).Remove (0, 1); + Value = value; } public int Length { - get { - return val.Length; - } + get { return Value.Length; } } public string Value { - get { - return val; - } + get; private set; } public string Substring (int index, int length) { - return val.Substring (index, length); + return Value.Substring (index, length); } } public object GetRawValue (ObjectPath path, EvaluationOptions options) { - string rawValue = null; + // Note: If the type is a string, then we already have the full value + if (Type.Equals ("string", StringComparison.Ordinal)) { + var rawValue = Unquote (Value); - using (var timer = vsCodeDebuggerSession.EvaluationStats.StartTimer ()) { - rawValue = vsCodeDebuggerSession.protocolClient.SendRequestSync (new EvaluateRequest (evalName) { FrameId = frameId }).Result; - timer.Success = true; + return new RawValueString (new RawString (rawValue)); } - if (rawValue.StartsWith ("\"", StringComparison.Ordinal)) { - if (options.ChunkRawStrings) - return new RawValueString (new RawString (rawValue)); - - return rawValue.Substring (1, rawValue.Length - 2); - } + //using (var timer = Session.EvaluationStats.StartTimer ()) { + // var response = Session.protocolClient.SendRequestSync (new EvaluateRequest (Expression) { FrameId = FrameId }); + // var rawValue = response.Result; + // timer.Success = true; + //} throw new NotImplementedException (); } public ObjectValue GetValue (ObjectPath path, EvaluationOptions options) { - if (val == "null") - return ObjectValue.CreateNullObject (this, name, type, flags); - if (variablesReference == 0)//This is some kind of primitive... - return ObjectValue.CreatePrimitive (this, new ObjectPath (name), type, new EvaluationResult (val, display), flags); - return ObjectValue.CreateObject (this, new ObjectPath (name), type, new EvaluationResult (val, display), flags, null); + if (Value == "null") + return ObjectValue.CreateNullObject (this, Name, Type, Flags); + + if (VariablesReference == 0) // This is some kind of primitive... + return ObjectValue.CreatePrimitive (this, new ObjectPath (Name), Type, new EvaluationResult (Value, Display), Flags); + + return ObjectValue.CreateObject (this, new ObjectPath (Name), Type, new EvaluationResult (Value, Display), Flags, null); } public void SetRawValue (ObjectPath path, object value, EvaluationOptions options) { var v = value.ToString (); - if (type == "string") - v = $"\"{v}\""; - vsCodeDebuggerSession.protocolClient.SendRequestSync (new SetVariableRequest (parentVariablesReference, name, v)); + + if (Type == "string") + v = Quote (v); + + Session.protocolClient.SendRequestSync (new SetVariableRequest (ParentVariablesReference, Name, v)); } public EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options) { - return new EvaluationResult (vsCodeDebuggerSession.protocolClient.SendRequestSync (new SetVariableRequest (parentVariablesReference, name, value)).Value); + return new EvaluationResult (Session.protocolClient.SendRequestSync (new SetVariableRequest (ParentVariablesReference, Name, value)).Value); } } } diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.PerfTests/MonoDevelop.Debugger.PerfTests.csproj b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.PerfTests/MonoDevelop.Debugger.PerfTests.csproj index 0b2e7f18fa..b2110f98d2 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.PerfTests/MonoDevelop.Debugger.PerfTests.csproj +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.PerfTests/MonoDevelop.Debugger.PerfTests.csproj @@ -42,11 +42,6 @@ <PackageReference Include="NUnit" Version="$(NuGetVersionNUnit2)" /> </ItemGroup> <ItemGroup> - <ProjectReference Include="..\..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\..\..\..\external\mono-addins\Mono.Addins\Mono.Addins.csproj"> <Project>{91DD5A2D-9FE3-4C3C-9253-876141874DAD}</Project> <Name>Mono.Addins</Name> diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/MonoDevelop.Debugger.Tests.csproj b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/MonoDevelop.Debugger.Tests.csproj index 44807cad5e..342f0f39b5 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/MonoDevelop.Debugger.Tests.csproj +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/MonoDevelop.Debugger.Tests.csproj @@ -41,11 +41,6 @@ <Name>MonoDevelop.Ide</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\..\..\..\external\mono-addins\Mono.Addins\Mono.Addins.csproj"> <Project>{91DD5A2D-9FE3-4C3C-9253-876141874DAD}</Project> <Name>Mono.Addins</Name> diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/ExceptionCaught/ExceptionCaughtAdornmentManager.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/ExceptionCaught/ExceptionCaughtAdornmentManager.cs index 6a633f99d0..490fbc6754 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/ExceptionCaught/ExceptionCaughtAdornmentManager.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/ExceptionCaught/ExceptionCaughtAdornmentManager.cs @@ -43,6 +43,7 @@ namespace MonoDevelop.Debugger.VSTextView.ExceptionCaught private readonly string filePath; readonly IXPlatAdornmentLayer _exceptionCaughtLayer; FileLineExtension extension; + NSPanel exceptionCaughtButtonWindow; public ExceptionCaughtAdornmentManager (ICocoaViewFactory cocoaViewFactory, ICocoaTextView textView) { @@ -68,6 +69,10 @@ namespace MonoDevelop.Debugger.VSTextView.ExceptionCaught if (e.Extension == extension) { extension = null; _exceptionCaughtLayer.RemoveAllAdornments (); + if (exceptionCaughtButtonWindow != null) { + exceptionCaughtButtonWindow.Close (); + exceptionCaughtButtonWindow = null; + } } } @@ -81,11 +86,14 @@ namespace MonoDevelop.Debugger.VSTextView.ExceptionCaught private void RenderAdornment (FileLineExtension fileLineExtension) { NSView view; - if (fileLineExtension is ExceptionCaughtButton button) + bool mini; + if (fileLineExtension is ExceptionCaughtButton button) { + mini = false; view = CreateButton (cocoaViewFactory, button); - else if (fileLineExtension is ExceptionCaughtMiniButton miniButton) + } else if (fileLineExtension is ExceptionCaughtMiniButton miniButton) { + mini = true; view = CreateMiniButton (cocoaViewFactory, miniButton); - else + } else return; if (extension != fileLineExtension) { extension = fileLineExtension; @@ -97,17 +105,38 @@ namespace MonoDevelop.Debugger.VSTextView.ExceptionCaught return; if (!textView.TextViewLines.FormattedSpan.Contains (span.End)) return; - try { - var charBound = textView.TextViewLines.GetCharacterBounds (span.End); - view.SetFrameOrigin (new CGPoint ( + _exceptionCaughtLayer.RemoveAllAdornments (); + if (exceptionCaughtButtonWindow != null) { + exceptionCaughtButtonWindow.Close (); + exceptionCaughtButtonWindow = null; + } + var charBound = textView.TextViewLines.GetCharacterBounds (span.End); + if (mini) { + try { + view.SetFrameOrigin (new CGPoint ( Math.Round (charBound.Left), - Math.Round (charBound.TextTop + charBound.TextHeight / 2 - view.Frame.Height / 2))); - } catch (Exception e) { - view.SetFrameOrigin (default); - LoggingService.LogInternalError ("https://vsmac.dev/923058", e); + Math.Round (charBound.TextTop - charBound.TextHeight / 2 - view.Frame.Height / 2))); + } catch (Exception e) { + view.SetFrameOrigin (default); + LoggingService.LogInternalError ("https://vsmac.dev/923058", e); + } + _exceptionCaughtLayer.AddAdornment (XPlatAdornmentPositioningBehavior.TextRelative, span, null, view, null); + } else { + var editorWindow = textView.VisualElement.Window; + var pointOnScreen = editorWindow.ConvertPointToScreen (textView.VisualElement.ConvertPointToView (new CGPoint (charBound.Left, charBound.TextTop), null)); + exceptionCaughtButtonWindow = new NSPanel (CGRect.Empty, NSWindowStyle.Borderless, NSBackingStore.Buffered, false); + exceptionCaughtButtonWindow.AccessibilityRole = NSAccessibilityRoles.PopoverRole; + editorWindow.AddChildWindow (exceptionCaughtButtonWindow, NSWindowOrderingMode.Above); + exceptionCaughtButtonWindow.IsOpaque = false; + exceptionCaughtButtonWindow.BackgroundColor = NSColor.Clear; + exceptionCaughtButtonWindow.HasShadow = true; + exceptionCaughtButtonWindow.ContentView = view; + var fittingSize = view.FittingSize; + var x = Math.Min (editorWindow.Screen.VisibleFrame.Width - fittingSize.Width, pointOnScreen.X); + var y = Math.Max (0, pointOnScreen.Y - fittingSize.Height / 2); + exceptionCaughtButtonWindow.SetFrame (new CGRect (x, y, fittingSize.Width, fittingSize.Height), true); + exceptionCaughtButtonWindow.MakeKeyAndOrderFront (null); } - _exceptionCaughtLayer.RemoveAllAdornments (); - _exceptionCaughtLayer.AddAdornment (XPlatAdornmentPositioningBehavior.TextRelative, span, null, view, null); } private void TextView_LayoutChanged (object sender, TextViewLayoutChangedEventArgs e) diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/PinnedWatches/PinnedWatchView.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/PinnedWatches/PinnedWatchView.cs index 3736f36d95..5c937d32c7 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/PinnedWatches/PinnedWatchView.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/PinnedWatches/PinnedWatchView.cs @@ -57,7 +57,7 @@ namespace MonoDevelop.Debugger.VSTextView.PinnedWatches controller.AllowExpanding = false; treeView = controller.GetMacControl (ObjectValueTreeViewFlags.PinnedWatchFlags); - + treeView.UIElementName = "PinnedWatch"; controller.PinnedWatch = watch; if (watch.Value != null) diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/DebuggerQuickInfoSource.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/DebuggerQuickInfoSource.cs index 8835fe7e30..05ba944d75 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/DebuggerQuickInfoSource.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/DebuggerQuickInfoSource.cs @@ -7,7 +7,7 @@ using Gtk; using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; - +using Mono.Debugging.Client; using MonoDevelop.Core; using MonoDevelop.Ide.Gui.Documents; @@ -119,22 +119,27 @@ namespace MonoDevelop.Debugger.VSTextView.QuickInfo return null; } - private async Task EvaluateAndShowTooltipAsync (IAsyncQuickInfoSession session, ITextView view, SnapshotPoint point, DataTipInfo debugInfo, CancellationToken cancellationToken) + async Task EvaluateAndShowTooltipAsync (IAsyncQuickInfoSession session, ITextView view, SnapshotPoint point, DataTipInfo debugInfo, CancellationToken cancellationToken) { var options = DebuggingService.DebuggerSession.EvaluationOptions.Clone (); options.AllowMethodEvaluation = true; options.AllowTargetInvoke = true; + ObjectValue val; - var val = DebuggingService.CurrentFrame.GetExpressionValue (debugInfo.Text, options); + using (var timer = DebuggingService.CurrentFrame.DebuggerSession.TooltipStats.StartTimer ()) { + val = DebuggingService.CurrentFrame.GetExpressionValue (debugInfo.Text, options); - if (val.IsEvaluating) - await WaitOneAsync (val.WaitHandle, cancellationToken); + if (val.IsEvaluating) + await WaitOneAsync (val.WaitHandle, cancellationToken); - if (cancellationToken.IsCancellationRequested) - return; + if (cancellationToken.IsCancellationRequested) + return; - if (val == null || val.IsUnknown || val.IsNotSupported) - return; + if (val == null || val.IsUnknown || val.IsNotSupported) + return; + + timer.Success = true; + } if (!view.Properties.TryGetProperty (typeof (Widget), out Widget gtkParent)) return; diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/MacDebuggerTooltipWindow.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/MacDebuggerTooltipWindow.cs index de0d95a703..c0d228350e 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/MacDebuggerTooltipWindow.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/MacDebuggerTooltipWindow.cs @@ -53,6 +53,7 @@ namespace MonoDevelop.Debugger controller.PinnedWatchLocation = location; treeView = controller.GetMacControl (ObjectValueTreeViewFlags.TooltipFlags); + treeView.UIElementName = "Tooltip"; treeView.NodePinned += OnPinStatusChanged; treeView.StartEditing += OnStartEditing; treeView.EndEditing += OnEndEditing; diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj index 67e4afd42e..716287531c 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj @@ -46,11 +46,6 @@ <Name>MonoDevelop.Ide</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\..\..\external\mono-addins\Mono.Addins\Mono.Addins.csproj"> <Project>{91DD5A2D-9FE3-4C3C-9253-876141874DAD}</Project> <Name>Mono.Addins</Name> diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Counters.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Counters.cs index c8fd7030f7..c72f154692 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Counters.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Counters.cs @@ -24,18 +24,36 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using MonoDevelop.Core.Instrumentation; using System; +using MonoDevelop.Core.Instrumentation; + namespace MonoDevelop.Debugger { static class Counters { public static Counter DebugSession = InstrumentationService.CreateCounter ("Debug Session", "Debugger", id: "Debugger.DebugSession"); public static Counter EvaluationStats = InstrumentationService.CreateCounter ("Evaluation Statistics", "Debugger", id: "Debugger.EvaluationStatistics"); + public static Counter StepInStats = InstrumentationService.CreateCounter ("Step In Statistics", "Debugger", id: "Debugger.StepInStatistics"); + public static Counter StepOutStats = InstrumentationService.CreateCounter ("Step Out Statistics", "Debugger", id: "Debugger.StepOutStatistics"); + public static Counter StepOverStats = InstrumentationService.CreateCounter ("Step Over Statistics", "Debugger", id: "Debugger.StepOverStatistics"); + public static Counter StepInstructionStats = InstrumentationService.CreateCounter ("Step Instruction Statistics", "Debugger", id: "Debugger.StepInstructionStatistics"); + public static Counter NextInstructionStats = InstrumentationService.CreateCounter ("Next Instruction Statistics", "Debugger", id: "Debugger.NextInstructionStatistics"); public static TimerCounter<DebuggerStartMetadata> DebuggerStart = InstrumentationService.CreateTimerCounter<DebuggerStartMetadata> ("Debugger Start", "Debugger", id: "Debugger.Start"); public static TimerCounter<DebuggerActionMetadata> DebuggerAction = InstrumentationService.CreateTimerCounter<DebuggerActionMetadata> ("Debugger Action", "Debugger", id: "Debugger.Action"); + public static Counter LocalVariableStats = InstrumentationService.CreateCounter ("Local Variable Statistics", "Debugger", id: "Debugger.LocalVariableStatistics"); + public static Counter WatchExpressionStats = InstrumentationService.CreateCounter ("Watch Expression Statistics", "Debugger", id: "Debugger.WatchExpressionStatistics"); + public static Counter StackTraceStats = InstrumentationService.CreateCounter ("Stack Trace Statistics", "Debugger", id: "Debugger.StackTraceStatistics"); + public static Counter TooltipStats = InstrumentationService.CreateCounter ("Tooltip Statistics", "Debugger", id: "Debugger.TooltipStatistics"); public static Counter DebuggerBusy = InstrumentationService.CreateCounter ("Debugger Busy", "Debugger", id: "Debugger.Busy"); + public static Counter LocalsPadFrameChanged = InstrumentationService.CreateCounter ("The StackFrame changed in the Locals Pad", "Debugger", id: "Debugger.LocalsPadFrameChanged"); + public static Counter AddedWatchFromLocals = InstrumentationService.CreateCounter ("Added a Watch Expression from the Locals Pad", "Debugger", id: "Debugger.AddedWatchFromLocals"); + public static Counter ManuallyAddedWatch = InstrumentationService.CreateCounter ("User Manually Added Watch Expression", "Debugger", id: "Debugger.ManuallyAddedWatch"); + public static Counter PinnedWatch = InstrumentationService.CreateCounter ("Pinned Watch Expression", "Debugger", id: "Debugger.PinnedWatch"); + public static Counter EditedValue = InstrumentationService.CreateCounter ("User Edited Variable Value", "Debugger", id: "Debugger.EditedValue"); + public static Counter ExpandedNode = InstrumentationService.CreateCounter ("User Expanded ObjectValue Node", "Debugger", id: "Debugger.ExpandedObjectValueNode"); + public static Counter OpenedPreviewer = InstrumentationService.CreateCounter ("User opened the value in the previewer", "Debugger", id: "Debugger.OpenedPreviewer"); + public static Counter OpenedVisualizer = InstrumentationService.CreateCounter ("User opened the value in a Visualizer", "Debugger", id: "Debugger.OpenedVisualizer"); } class DebuggerStartMetadata : CounterMetadata diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs index 18b9c9a50a..8fb53e652f 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs @@ -27,31 +27,31 @@ // using System; -using System.Collections.Generic; using System.Xml; +using System.Linq; +using System.Threading; +using System.Globalization; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Collections.Concurrent; + using Mono.Addins; + using Mono.Debugging.Client; -using MonoDevelop.Core; -using MonoDevelop.Core.Execution; + +using Microsoft.VisualStudio.Text; +using Microsoft.CodeAnalysis.Text; + using MonoDevelop.Ide; +using MonoDevelop.Core; using MonoDevelop.Ide.Gui; -using MonoDevelop.Ide.Gui.Content; using MonoDevelop.Projects; -using MonoDevelop.Debugger.Viewers; - -/* - * Some places we should be doing some error handling we used to toss - * exceptions, now we error out silently, this needs a real solution. - */ +using MonoDevelop.Components; +using MonoDevelop.Core.Execution; using MonoDevelop.Ide.TextEditing; -using System.Linq; -using System.Threading.Tasks; -using System.Collections.Concurrent; -using System.Threading; +using MonoDevelop.Ide.Gui.Content; +using MonoDevelop.Debugger.Viewers; using MonoDevelop.Core.Instrumentation; -using MonoDevelop.Components; -using Microsoft.VisualStudio.Text; -using Microsoft.CodeAnalysis.Text; namespace MonoDevelop.Debugger { @@ -135,7 +135,6 @@ namespace MonoDevelop.Debugger args.Cancel = true; } - public static IExecutionHandler GetExecutionHandler () { return executionHandlerFactory; @@ -145,7 +144,6 @@ namespace MonoDevelop.Debugger get { return currentSession?.Session ?? sessions.Values.FirstOrDefault ()?.Session; } } - public static DebuggerSession [] GetSessions () { return sessions.Keys.ToArray (); @@ -815,7 +813,19 @@ namespace MonoDevelop.Debugger public void Dispose () { UpdateDebugSessionCounter (); - UpdateEvaluationStatsCounter (); + + UpdateStatsCounter (Counters.EvaluationStats, Session.EvaluationStats); + + UpdateStatsCounter (Counters.StepInStats, Session.StepInStats); + UpdateStatsCounter (Counters.StepOutStats, Session.StepOutStats); + UpdateStatsCounter (Counters.StepOverStats, Session.StepOverStats); + UpdateStatsCounter (Counters.StepInstructionStats, Session.StepInstructionStats); + UpdateStatsCounter (Counters.NextInstructionStats, Session.NextInstructionStats); + + UpdateStatsCounter (Counters.LocalVariableStats, Session.LocalVariableStats); + UpdateStatsCounter (Counters.WatchExpressionStats, Session.WatchExpressionStats); + UpdateStatsCounter (Counters.StackTraceStats, Session.StackTraceStats); + UpdateStatsCounter (Counters.TooltipStats, Session.TooltipStats); console?.Dispose (); console = null; @@ -844,7 +854,7 @@ namespace MonoDevelop.Debugger void UpdateDebugSessionCounter () { var metadata = new Dictionary<string, object> (); - metadata ["Success"] = (!SessionError).ToString (); + metadata ["Success"] = (!SessionError).ToString (CultureInfo.InvariantCulture); metadata ["DebuggerType"] = Engine.Id; if (firstAssemblyLoadTimer != null) { @@ -852,29 +862,25 @@ namespace MonoDevelop.Debugger // No first assembly load event. firstAssemblyLoadTimer.Stop (); } else { - metadata ["AssemblyFirstLoadDuration"] = firstAssemblyLoadTimer.ElapsedMilliseconds.ToString (); + metadata ["AssemblyFirstLoadDuration"] = firstAssemblyLoadTimer.ElapsedMilliseconds.ToString (CultureInfo.InvariantCulture); } } Counters.DebugSession.Inc (1, null, metadata); } - void UpdateEvaluationStatsCounter () + void UpdateStatsCounter (Counter counter, DebuggerStatistics stats) { - if (Session.EvaluationStats.TimingsCount == 0 && Session.EvaluationStats.FailureCount == 0) { + if (stats.TimingsCount == 0 && stats.FailureCount == 0) { // No timings or failures recorded. return; } var metadata = new Dictionary<string, object> (); - metadata ["DebuggerType"] = Engine.Id; - metadata ["AverageDuration"] = Session.EvaluationStats.AverageTime.ToString (); - metadata ["MaximumDuration"] = Session.EvaluationStats.MaxTime.ToString (); - metadata ["MinimumDuration"] = Session.EvaluationStats.MinTime.ToString (); - metadata ["FailureCount"] = Session.EvaluationStats.FailureCount.ToString (); - metadata ["SuccessCount"] = Session.EvaluationStats.TimingsCount.ToString (); + metadata["DebuggerType"] = Engine.Id; + stats.Serialize (metadata); - Counters.EvaluationStats.Inc (1, null, metadata); + counter.Inc (1, null, metadata); } bool ExceptionHandler (Exception ex) @@ -1391,7 +1397,7 @@ namespace MonoDevelop.Debugger pinnedWatches.SetAllLiveUpdateBreakpoints (breakpoints); - return Task.FromResult (true); + return Task.CompletedTask; } static void OnSolutionClosed (object s, EventArgs args) diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ExceptionCaughtDialog.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ExceptionCaughtDialog.cs index 619354ebb9..0a8c41c860 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ExceptionCaughtDialog.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ExceptionCaughtDialog.cs @@ -194,6 +194,7 @@ widget ""*.exception_help_link_label"" style ""exception-help-link-label"" if (Platform.IsMac) { macExceptionValueTreeView = controller.GetMacControl (ObjectValueTreeViewFlags.ObjectValuePadFlags); + macExceptionValueTreeView.UIElementName = "ExceptionCaughtDialog"; } else { exceptionValueTreeView = controller.GetGtkControl (ObjectValueTreeViewFlags.ExceptionCaughtFlags); } @@ -423,7 +424,12 @@ widget ""*.exception_help_link_label"" style ""exception-help-link-label"" actionArea.PackStart (new VBox (), false, true, 3); // dummy just to take extra 6px at end to make it 20pixels actionArea.ShowAll (); - vbox.PackStart (actionArea, false, true, 0); + var bottomButtonPanelBackground = new EventBox (); + bottomButtonPanelBackground.Show (); + bottomButtonPanelBackground.ModifyBg (StateType.Normal, Styles.ExceptionCaughtDialog.BottomPaddingBackgroundColor.ToGdkColor ()); + bottomButtonPanelBackground.Add (actionArea); + + vbox.PackStart (bottomButtonPanelBackground, false, true, 0); } Widget CreateInnerExceptionMessage () diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Initializer.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Initializer.cs index 93749e9961..f33ea3148d 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Initializer.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Initializer.cs @@ -46,6 +46,7 @@ namespace MonoDevelop.Debugger Document noSourceDoc; NoSourceView noSourceView; string symbolCachePath; + bool changingFrame; protected override void Run () { @@ -67,108 +68,120 @@ namespace MonoDevelop.Debugger async void OnFrameChanged (object s, EventArgs a) { - if (disassemblyDoc != null && DebuggingService.IsFeatureSupported (DebuggerFeatures.Disassembly)) - disassemblyView.Update (); - - var frame = DebuggingService.CurrentFrame; - if (frame == null) + if (changingFrame) { return; - - FilePath file = frame.SourceLocation.FileName; + } + try { + changingFrame = true; + if (disassemblyDoc != null && DebuggingService.IsFeatureSupported (DebuggerFeatures.Disassembly)) + disassemblyView.Update (); - int line = frame.SourceLocation.Line; - if (line != -1) { - if (!file.IsNullOrEmpty && File.Exists (file)) { - var doc = await IdeApp.Workbench.OpenDocument (file, null, line, 1, OpenDocumentOptions.Debugger); - if (doc != null) - return; + var frame = DebuggingService.CurrentFrame; + if (frame == null) { + return; } - bool alternateLocationExists = false; - if (frame.SourceLocation.FileHash != null) { - var newFilePath = SourceCodeLookup.FindSourceFile (file, frame.SourceLocation.FileHash); - if (newFilePath != null && File.Exists (newFilePath)) { - frame.UpdateSourceFile (newFilePath); - var doc = await IdeApp.Workbench.OpenDocument (newFilePath, null, line, 1, OpenDocumentOptions.Debugger); - if (doc != null) + + FilePath file = frame.SourceLocation.FileName; + + int line = frame.SourceLocation.Line; + if (line != -1) { + if (!file.IsNullOrEmpty && File.Exists (file)) { + var doc = await IdeApp.Workbench.OpenDocument (file, null, line, 1, OpenDocumentOptions.Debugger); + if (doc != null) { return; + } } - } - var debuggerOptions = DebuggingService.GetUserOptions (); - var automaticSourceDownload = debuggerOptions.AutomaticSourceLinkDownload; + bool alternateLocationExists = false; + if (frame.SourceLocation.FileHash != null) { + var newFilePath = SourceCodeLookup.FindSourceFile (file, frame.SourceLocation.FileHash); + if (newFilePath != null && File.Exists (newFilePath)) { + frame.UpdateSourceFile (newFilePath); + var doc = await IdeApp.Workbench.OpenDocument (newFilePath, null, line, 1, OpenDocumentOptions.Debugger); + if (doc != null) { + return; + } + } + } + var debuggerOptions = DebuggingService.GetUserOptions (); + var automaticSourceDownload = debuggerOptions.AutomaticSourceLinkDownload; - var sourceLink = frame.SourceLocation.SourceLink; - if (sourceLink != null && automaticSourceDownload != AutomaticSourceDownload.Never) { - var downloadLocation = sourceLink.GetDownloadLocation (symbolCachePath); - Document doc = null; - // ~/Library/Caches/VisualStudio/8.0/Symbols/org/projectname/git-sha/path/to/file.cs - if (!File.Exists (downloadLocation)) { - if (automaticSourceDownload == AutomaticSourceDownload.Always) { - doc = await DownloadAndOpenFileAsync (frame, line, sourceLink); - } else { - var hyperlink = $"<a href='{ sourceLink.Uri }'>{ Path.GetFileName (sourceLink.RelativeFilePath) }</a>"; - var stackframeText = $"<b>{frame.FullStackframeText}</b>"; + var sourceLink = frame.SourceLocation.SourceLink; + if (sourceLink != null && automaticSourceDownload != AutomaticSourceDownload.Never) { + var downloadLocation = sourceLink.GetDownloadLocation (symbolCachePath); + Document doc = null; + // ~/Library/Caches/VisualStudio/8.0/Symbols/org/projectname/git-sha/path/to/file.cs + if (!File.Exists (downloadLocation)) { + if (automaticSourceDownload == AutomaticSourceDownload.Always) { + doc = await DownloadAndOpenFileAsync (frame, line, sourceLink); + } else { + var hyperlink = $"<a href='{ sourceLink.Uri }'>{ Path.GetFileName (sourceLink.RelativeFilePath) }</a>"; + var stackframeText = $"<b>{frame.FullStackframeText}</b>"; - var text = GettextCatalog.GetString - ("{0} is a call to external source code. Would you like to get '{1}' and view it?", stackframeText, hyperlink); - var message = new Ide.GenericMessage { - Text = GettextCatalog.GetString ("External source code available"), - SecondaryText = text - }; - message.AddOption (nameof (automaticSourceDownload), GettextCatalog.GetString ("Always get source code automatically"), false); - message.Buttons.Add (AlertButton.Cancel); - message.Buttons.Add (new AlertButton (GettextCatalog.GetString ("Get and Open"))); - message.DefaultButton = 1; + var text = GettextCatalog.GetString + ("{0} is a call to external source code. Would you like to get '{1}' and view it?", stackframeText, hyperlink); + var message = new Ide.GenericMessage { + Text = GettextCatalog.GetString ("External source code available"), + SecondaryText = text + }; + message.AddOption (nameof (automaticSourceDownload), GettextCatalog.GetString ("Always get source code automatically"), false); + message.Buttons.Add (AlertButton.Cancel); + message.Buttons.Add (new AlertButton (GettextCatalog.GetString ("Get and Open"))); + message.DefaultButton = 1; - var didNotCancel = MessageService.GenericAlert (message) != AlertButton.Cancel; - if (didNotCancel) { - if (message.GetOptionValue (nameof (automaticSourceDownload))) { - debuggerOptions.AutomaticSourceLinkDownload = AutomaticSourceDownload.Always; - DebuggingService.SetUserOptions (debuggerOptions); + var didNotCancel = MessageService.GenericAlert (message) != AlertButton.Cancel; + if (didNotCancel) { + if (message.GetOptionValue (nameof (automaticSourceDownload))) { + debuggerOptions.AutomaticSourceLinkDownload = AutomaticSourceDownload.Always; + DebuggingService.SetUserOptions (debuggerOptions); + } + doc = await DownloadAndOpenFileAsync (frame, line, sourceLink); } - doc = await DownloadAndOpenFileAsync (frame, line, sourceLink); } + } else { + // The file has previously been downloaded for a different solution. + // We need to map the cached location + frame.UpdateSourceFile (downloadLocation); + doc = await IdeApp.Workbench.OpenDocument (downloadLocation, null, line, 1, OpenDocumentOptions.Debugger); + } + if (doc != null) { + return; } - } else { - // The file has previously been downloaded for a different solution. - // We need to map the cached location - frame.UpdateSourceFile (downloadLocation); - doc = await IdeApp.Workbench.OpenDocument (downloadLocation, null, line, 1, OpenDocumentOptions.Debugger); } - if (doc != null) - return; } - } - bool disassemblyNotSupported = false; - // If we don't have an address space, we can't disassemble - if (string.IsNullOrEmpty (frame.AddressSpace)) - disassemblyNotSupported = true; + bool disassemblyNotSupported = false; + // If we don't have an address space, we can't disassemble + if (string.IsNullOrEmpty (frame.AddressSpace)) + disassemblyNotSupported = true; - if (!DebuggingService.CurrentSessionSupportsFeature (DebuggerFeatures.Disassembly)) - disassemblyNotSupported = true; + if (!DebuggingService.CurrentSessionSupportsFeature (DebuggerFeatures.Disassembly)) + disassemblyNotSupported = true; - if (disassemblyNotSupported && disassemblyDoc != null) { - disassemblyDoc.Close ().Ignore (); - disassemblyDoc = null; - disassemblyView = null; - } + if (disassemblyNotSupported && disassemblyDoc != null) { + disassemblyDoc.Close ().Ignore (); + disassemblyDoc = null; + disassemblyView = null; + } - // If disassembly is open don't show NoSourceView - if (disassemblyDoc == null) { - if (noSourceDoc == null) { - noSourceView = new NoSourceView (); - noSourceView.Update (disassemblyNotSupported); - noSourceDoc = await IdeApp.Workbench.OpenDocument (noSourceView, true); - noSourceDoc.Closed += delegate { - noSourceDoc = null; - noSourceView = null; - }; + // If disassembly is open don't show NoSourceView + if (disassemblyDoc == null) { + if (noSourceDoc == null) { + noSourceView = new NoSourceView (); + noSourceView.Update (disassemblyNotSupported); + noSourceDoc = await IdeApp.Workbench.OpenDocument (noSourceView, true); + noSourceDoc.Closed += delegate { + noSourceDoc = null; + noSourceView = null; + }; + } else { + noSourceView.Update (disassemblyNotSupported); + noSourceDoc.Select (); + } } else { - noSourceView.Update (disassemblyNotSupported); - noSourceDoc.Select (); + disassemblyDoc.Select (); } - } else { - disassemblyDoc.Select (); + } finally { + changingFrame = false; } } diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/LocalsPad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/LocalsPad.cs index 97cf84202a..e64938f183 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/LocalsPad.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/LocalsPad.cs @@ -26,6 +26,7 @@ // using System; +using System.Collections.Generic; using Mono.Debugging.Client; @@ -67,7 +68,7 @@ namespace MonoDevelop.Debugger void AddFakeNodes () { - var xx = new System.Collections.Generic.List<ObjectValueNode> (); + var xx = new List<ObjectValueNode> (); xx.Add (new FakeObjectValueNode ("f1")); xx.Add (new FakeIsImplicitNotSupportedObjectValueNode ()); @@ -84,14 +85,35 @@ namespace MonoDevelop.Debugger controller.AddValues (xx); } - void ReloadValues () + void ReloadValues (bool frameChanged) { var frame = DebuggingService.CurrentFrame; if (frame == null) return; - var locals = frame.GetAllLocals (); + ObjectValue[] locals; + TimeSpan elapsed; + + using (var timer = frame.DebuggerSession.LocalVariableStats.StartTimer ()) { + try { + locals = frame.GetAllLocals (); + timer.Stop (true); + } catch { + locals = new ObjectValue[0]; + timer.Stop (false); + } + + elapsed = timer.Elapsed; + } + + if (frameChanged) { + var metadata = new Dictionary<string, object> (); + metadata["LocalsCount"] = locals.Length; + metadata["Elapsed"] = elapsed.TotalMilliseconds; + + Counters.LocalsPadFrameChanged.Inc (1, null, metadata); + } DebuggerLoggingService.LogMessage ("Begin Local Variables:"); foreach (var local in locals) @@ -107,7 +129,6 @@ namespace MonoDevelop.Debugger _treeview.EndUpdates (); } - if (EnableFakeNodes) AddFakeNodes (); } else { @@ -119,13 +140,13 @@ namespace MonoDevelop.Debugger public override void OnUpdateFrame () { base.OnUpdateFrame (); - ReloadValues (); + ReloadValues (true); } public override void OnUpdateValues () { base.OnUpdateValues (); - ReloadValues (); + ReloadValues (false); } } } diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacDebuggerObjectNameView.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacDebuggerObjectNameView.cs index 63b1c60e32..a48fbd8a48 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacDebuggerObjectNameView.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacDebuggerObjectNameView.cs @@ -182,8 +182,10 @@ namespace MonoDevelop.Debugger UpdateContents (); if (Node is AddNewExpressionObjectValueNode) { - if (newValue.Length > 0) + if (newValue.Length > 0) { TreeView.OnExpressionAdded (newValue); + Counters.ManuallyAddedWatch.Inc (1); + } } else if (newValue != oldValue) { TreeView.OnExpressionEdited (Node, newValue); } @@ -429,6 +431,12 @@ namespace MonoDevelop.Debugger SetPreviewButtonIcon (PreviewButtonIcon.Active); DebuggingService.ShowPreviewVisualizer (val, IdeApp.Workbench.RootWindow, buttonArea); + + var metadata = new Dictionary<string, object> (); + metadata["UIElementName"] = TreeView.UIElementName; + metadata["ObjectValue.Type"] = val.TypeName; + + Counters.OpenedPreviewer.Inc (1, null, metadata); } void OnEditorLostFocus (object sender, EventArgs e) diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacDebuggerTextField.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacDebuggerTextField.cs index 704469aac8..fd95fd209d 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacDebuggerTextField.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacDebuggerTextField.cs @@ -24,6 +24,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +using System.Collections.Generic; + using AppKit; using Foundation; @@ -103,8 +105,14 @@ namespace MonoDevelop.Debugger cellView.TreeView.OnExpressionEdited (cellView.Node, newValue); } } else if (cellView is MacDebuggerObjectValueView) { - if (newValue != oldValue && cellView.TreeView.GetEditValue (cellView.Node, newValue)) + if (newValue != oldValue && cellView.TreeView.GetEditValue (cellView.Node, newValue)) { + var metadata = new Dictionary<string, object> (); + metadata["UIElementName"] = cellView.TreeView.UIElementName; + metadata["ObjectValue.Type"] = cellView.Node.TypeName; + + Counters.EditedValue.Inc (1, null, metadata); cellView.Refresh (); + } } oldValue = newValue = null; diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacObjectValueTreeView.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacObjectValueTreeView.cs index 0f2909acc9..fa11d2a3f4 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacObjectValueTreeView.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacObjectValueTreeView.cs @@ -143,6 +143,10 @@ namespace MonoDevelop.Debugger "bounds", NSNull.Null); } + public string UIElementName { + get; set; + } + public ObjectValueTreeViewController Controller { get; private set; } @@ -451,6 +455,8 @@ namespace MonoDevelop.Debugger } NodePinned?.Invoke (this, new ObjectValueNodeEventArgs (node)); + + Counters.PinnedWatch.Inc (1); } public void Pin (ObjectValueNode node) @@ -475,6 +481,12 @@ namespace MonoDevelop.Debugger internal bool ShowVisualizer (ObjectValueNode node) { + var metadata = new Dictionary<string, object> (); + metadata["UIElementName"] = UIElementName; + metadata["ObjectValue.Type"] = node.TypeName; + + Counters.OpenedVisualizer.Inc (1, null, metadata); + var args = new ObjectValueNodeEventArgs (node); NodeShowVisualiser?.Invoke (this, args); return args.Response is bool b && b; @@ -563,6 +575,19 @@ namespace MonoDevelop.Debugger // TODO: all this scrolling kind of seems awkward //if (path != null) // ScrollToCell (path, expCol, true, 0f, 0f); + + var parent = node.Parent; + int level = 0; + while (parent != null) { + parent = parent.Parent; + level++; + } + + var metadata = new Dictionary<string, object> (); + metadata["UIElementName"] = UIElementName; + metadata["NodeLevel"] = level; + + Counters.ExpandedNode.Inc (1, null, metadata); } } @@ -883,6 +908,11 @@ namespace MonoDevelop.Debugger foreach (var expression in expressions) DebuggingService.AddWatch (expression); + + var metadata = new Dictionary<string, object> (); + metadata["ExpressionCount"] = expressions.Count; + + Counters.AddedWatchFromLocals.Inc (1, null, metadata); } void OnAddWatch (object sender, EventArgs args) diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/ObjectValueStackFrame.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/ObjectValueStackFrame.cs index 7e8880ab22..938cb925ae 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/ObjectValueStackFrame.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/ObjectValueStackFrame.cs @@ -80,7 +80,10 @@ namespace MonoDevelop.Debugger ObjectValue[] qvalues; if (StackFrame != null) { - qvalues = StackFrame.GetExpressionValues (unknown.ToArray (), true); + using (var timer = StackFrame.DebuggerSession.WatchExpressionStats.StartTimer ()) { + qvalues = StackFrame.GetExpressionValues (unknown.ToArray (), true); + timer.Success = true; + } } else { qvalues = new ObjectValue[unknown.Count]; for (int i = 0; i < qvalues.Length; i++) diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValuePad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValuePad.cs index bb964bd8bb..7751d5e230 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValuePad.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValuePad.cs @@ -71,6 +71,7 @@ namespace MonoDevelop.Debugger if (Platform.IsMac) { LoggingService.LogInfo ("Using MacObjectValueTreeView for {0}", allowWatchExpressions ? "Watch Pad" : "Locals Pad"); var treeView = controller.GetMacControl (ObjectValueTreeViewFlags.ObjectValuePadFlags); + treeView.UIElementName = allowWatchExpressions ? "WatchPad" : "LocalsPad"; _treeview = treeView; fontChanger = new PadFontChanger (treeView, treeView.SetCustomFont, treeView.QueueResize); diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/StackTracePad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/StackTracePad.cs index f2f694f3db..1923ca3b5f 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/StackTracePad.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/StackTracePad.cs @@ -222,10 +222,17 @@ namespace MonoDevelop.Debugger { var backtrace = DebuggingService.CurrentCallStack; var result = new List<(StackFrame frame, string text)> (); - for (int i = 0; i < backtrace.FrameCount; i++) { - var frame = backtrace.GetFrame (i); - result.Add ((frame, frame.FullStackframeText)); + + if (backtrace.FrameCount > 0) { + using (var timer = backtrace.DebuggerSession.StackTraceStats.StartTimer ()) { + for (int i = 0; i < backtrace.FrameCount; i++) { + var frame = backtrace.GetFrame (i); + result.Add ((frame, frame.FullStackframeText)); + } + timer.Success = true; + } } + return result; } diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Styles.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Styles.cs index d8a608a98a..7f6141b0e2 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Styles.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Styles.cs @@ -57,6 +57,7 @@ namespace MonoDevelop.Debugger public Color TreeSelectedBackgroundColor { get; internal set; } public Color TreeSelectedTextColor { get; internal set; } public Color ValueTreeBackgroundColor { get; internal set; } + public Color BottomPaddingBackgroundColor { get; internal set; } } static Styles () @@ -86,6 +87,7 @@ namespace MonoDevelop.Debugger ExceptionCaughtDialog.LineNumberTextColor = Color.FromName ("#707070"); ExceptionCaughtDialog.ExternalCodeTextColor = Color.FromName ("#707070"); ExceptionCaughtDialog.ValueTreeBackgroundColor = Color.FromName ("#ffffff"); + ExceptionCaughtDialog.BottomPaddingBackgroundColor = Color.FromName ("#ececec"); BreakpointPropertiesSecondaryTextColor = Color.FromName ("#707070"); } else { @@ -99,6 +101,7 @@ namespace MonoDevelop.Debugger ExceptionCaughtDialog.LineNumberTextColor = Color.FromName ("#b4b4b4"); ExceptionCaughtDialog.ExternalCodeTextColor = Color.FromName ("#b4b4b4"); ExceptionCaughtDialog.ValueTreeBackgroundColor = Color.FromName ("#525252"); + ExceptionCaughtDialog.BottomPaddingBackgroundColor = ObjectValueTreeActiveBackgroundColor; BreakpointPropertiesSecondaryTextColor = Color.FromName ("#b4b4b4"); } diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/ComponentModelEditorProvider.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/ComponentModelEditorProvider.cs index 5a95a0b4bb..06b595bd09 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/ComponentModelEditorProvider.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/ComponentModelEditorProvider.cs @@ -96,11 +96,8 @@ namespace MonoDevelop.DesignerSupport var collection = new List<DescriptorPropertyInfo> (); foreach (object propertyProvider in providers) { - //get the current properties for this provider - var currentType = propertyProvider.GetType (); - - //we want all property descriptors for this propertyProvider type - var propertyDescriptors = System.ComponentModel.TypeDescriptor.GetProperties (currentType); + //we want all property descriptors for this propertyProvider + var propertyDescriptors = System.ComponentModel.TypeDescriptor.GetProperties (propertyProvider); foreach (System.ComponentModel.PropertyDescriptor propertyDescriptor in propertyDescriptors) { if (propertyDescriptor.IsBrowsable) { diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Templating/DotNetCoreProjectTemplateWizard.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Templating/DotNetCoreProjectTemplateWizard.cs index cfe5ee2ad7..41e3ce3b1e 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Templating/DotNetCoreProjectTemplateWizard.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Templating/DotNetCoreProjectTemplateWizard.cs @@ -87,6 +87,8 @@ namespace MonoDevelop.DotNetCore.Templating } else { targetFrameworks = DotNetCoreProjectSupportedTargetFrameworks.GetNetCoreAppTargetFrameworksWithSdkSupport ().ToList (); + RemoveUnsupportedNetCoreAppTargetFrameworks (targetFrameworks); + if (!SupportsNetCore2x ()) { RemoveUnsupportedNetCoreApp2xTargetFrameworks (targetFrameworks); } @@ -105,6 +107,11 @@ namespace MonoDevelop.DotNetCore.Templating targetFrameworks.RemoveAll (framework => framework.IsLowerThanNetStandard16 ()); } + static void RemoveUnsupportedNetCoreAppTargetFrameworks (List<TargetFramework> targetFrameworks) + { + targetFrameworks.RemoveAll (framework => framework.IsNetCoreAppOrHigher (DotNetCoreSdk.DotNetCoreUnsupportedTargetFrameworkVersion)); + } + /// <summary> /// FSharp class library project template and the Razor Pages project template do not support /// targeting 1.x versions so remove these frameworks. diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests.csproj b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests.csproj index f1e8486702..e762a7fdd9 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests.csproj +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests.csproj @@ -43,6 +43,7 @@ <Compile Include="MonoDevelop.DotNetCore.Tests\PackProjectTests.cs" /> <Compile Include="MonoDevelop.DotNetCore.Tests\FrameworkReferenceTests.cs" /> <Compile Include="MonoDevelop.DotNetCore.Tests\GlobalToolTests.cs" /> + <Compile Include="MonoDevelop.DotNetCore.Tests\TargetFrameworkTests.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\..\..\external\guiunit\src\framework\GuiUnit_NET_4_5.csproj"> diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateWizardTests.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateWizardTests.cs index 6dec6e10c7..323e7ef068 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateWizardTests.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateWizardTests.cs @@ -24,6 +24,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +using System.Linq; using System.Reflection; using MonoDevelop.Core.StringParsing; using MonoDevelop.DotNetCore.Templating;
@@ -322,6 +323,20 @@ namespace MonoDevelop.DotNetCore.Tests } [Test] + public void NetCoreApp_UnsupportedSDKInstalled_TemplateDoesNotShowUnsupported () + { + CreateWizard (); + DotNetCoreRuntimesInstalled ("2.1.14", "2.2.8", "3.0.1", "3.1.0", $"{DotNetCoreSdk.DotNetCoreUnsupportedTargetFrameworkVersion.Major}.{DotNetCoreSdk.DotNetCoreUnsupportedTargetFrameworkVersion.Minor}.0"); + DotNetCoreSdksInstalled ("2.1.702", "2.2.402", "3.0.101", "3.1.100", $"{DotNetCoreSdk.DotNetCoreUnsupportedTargetFrameworkVersion.Major}.{DotNetCoreSdk.DotNetCoreUnsupportedTargetFrameworkVersion.Minor}.0"); + + int pages = wizard.TotalPages; + + Assert.AreEqual (1, pages); + Assert.AreEqual (4, wizard.TargetFrameworks.Count); + Assert.False (wizard.TargetFrameworks.Any (x => x.Id.IsNetCoreAppOrHigher (DotNetCoreSdk.DotNetCoreUnsupportedTargetFrameworkVersion))); + } + + [Test] public void NetCoreLibrary_NetCore20Installed () { CreateWizard (); diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/TargetFrameworkTests.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/TargetFrameworkTests.cs new file mode 100644 index 0000000000..25eec27758 --- /dev/null +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/TargetFrameworkTests.cs @@ -0,0 +1,76 @@ +// +// TargetFrameworkTests.cs +// +// Author: +// Rodrigo Moya <rodrigo.moya@xamarin.com> +// +// Copyright (c) 2019 Microsoft, Corp. (http://www.microsoft.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using MonoDevelop.Core; +using MonoDevelop.Core.Assemblies; +using NUnit.Framework; + +namespace MonoDevelop.DotNetCore.Tests +{ + [TestFixture] + class TargetFrameworkTests : DotNetCoreTestBase + { + [TestCase ("1.0", "1.0", "1.1", "2.0", "2.1", "2.2", "3.0", "3.1")] + [TestCase ("1.1", "1.1", "2.0", "2.1", "2.2", "3.0", "3.1")] + [TestCase ("2.0", "2.0", "2.1", "2.2", "3.0", "3.1")] + [TestCase ("2.1", "2.1", "2.2", "3.0", "3.1")] + [TestCase ("2.2", "2.2", "3.0", "3.1")] + [TestCase ("3.0", "3.0", "3.1")] + public void NetCoreApp_IsVersionOrHigher (string version, params string[] versionsToCheck) + { + var frameworkVersion = DotNetCoreVersion.Parse (version); + foreach (var v in versionsToCheck) { + var framework = CreateTargetFramework (".NETCoreApp", v); + Assert.True (framework.IsNetCoreAppOrHigher (frameworkVersion)); + } + } + + [TestCase ("1.0", "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "2.0", "2.1")] + [TestCase ("1.1", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "2.0", "2.1")] + [TestCase ("1.2", "1.2", "1.3", "1.4", "1.5", "1.6", "2.0", "2.1")] + [TestCase ("1.3", "1.3", "1.4", "1.5", "1.6", "2.0", "2.1")] + [TestCase ("1.4", "1.4", "1.5", "1.6", "2.0", "2.1")] + [TestCase ("1.5", "1.5", "1.6", "2.0", "2.1")] + [TestCase ("1.6", "1.6", "2.0", "2.1")] + [TestCase ("2.0", "2.0", "2.1")] + [TestCase ("2.1", "2.1")] + public void NetStandard_IsVersionOrHigher (string version, params string [] versionsToCheck) + { + var frameworkVersion = DotNetCoreVersion.Parse (version); + foreach (var v in versionsToCheck) { + var framework = CreateTargetFramework (".NETStandard", v); + Assert.True (framework.IsNetStandardOrHigher (frameworkVersion)); + } + } + + static TargetFramework CreateTargetFramework (string identifier, string version) + { + var moniker = new TargetFrameworkMoniker (identifier, version); + return Runtime.SystemAssemblyService.GetTargetFramework (moniker); + } + } +} diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs index ced8a441c4..e62b73f956 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs @@ -75,7 +75,7 @@ namespace MonoDevelop.DotNetCore protected override bool SupportsObject (WorkspaceObject item) { - return DotNetCoreSupportsObject (item) && !IsWebProject ((DotNetProject)item); + return DotNetCoreSupportsObject (item) && !SupportsLaunchSettings ((DotNetProject)item); } protected bool DotNetCoreSupportsObject (WorkspaceObject item) @@ -404,7 +404,13 @@ namespace MonoDevelop.DotNetCore public bool HasSdk => Project.MSBuildProject.GetReferencedSDKs ().Length > 0; - protected bool IsWebProject (DotNetProject project) + protected static bool SupportsLaunchSettings (DotNetProject project) + { + return IsWebProject (project) || + project.MSBuildProject.GetReferencedSDKs ().FirstOrDefault (x => x.IndexOf ("Microsoft.NET.Sdk.Worker", StringComparison.OrdinalIgnoreCase) != -1) != null; + } + + protected static bool IsWebProject (DotNetProject project) { return (project.MSBuildProject.GetReferencedSDKs ().FirstOrDefault (x => x.IndexOf ("Microsoft.NET.Sdk.Web", StringComparison.OrdinalIgnoreCase) != -1) != null); } diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdk.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdk.cs index 50992bf057..63dc50df57 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdk.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdk.cs @@ -36,6 +36,7 @@ namespace MonoDevelop.DotNetCore public static class DotNetCoreSdk { static readonly Version DotNetCoreVersion2_1 = new Version (2, 1, 0); + internal static readonly DotNetCoreVersion DotNetCoreUnsupportedTargetFrameworkVersion = new DotNetCoreVersion (3, 2, 0); static DotNetCoreSdk () { diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkMonikerExtensions.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkMonikerExtensions.cs index 0e52b80399..71c92e557c 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkMonikerExtensions.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkMonikerExtensions.cs @@ -50,22 +50,32 @@ namespace MonoDevelop.DotNetCore return framework.IsNetStandard () || framework.IsNetCoreApp (); } - public static bool IsNetCoreAppOrHigher (this TargetFrameworkMoniker framework, DotNetCoreVersion version) + static bool IsVersionOrHigher (this TargetFrameworkMoniker framework, DotNetCoreVersion version) { DotNetCoreVersion.TryParse (framework.Version, out var dotNetCoreVersion); if (dotNetCoreVersion == null) return false; - return framework.IsNetCoreApp () && dotNetCoreVersion >= version; + // Only compare $major.$minor, as Version parsing sets some fields to -1 + // (Build), which gives false positives/negatives when comparing, for instance, + // 3.1.100-preview1-014459 with an unsupported 3.1, and we're really only + // interested in the target framework version, which only uses $major.$minor. + if (dotNetCoreVersion.Major > version.Major) + return true; + if (dotNetCoreVersion.Major < version.Major) + return false; + + return dotNetCoreVersion.Minor >= version.Minor; } - public static bool IsNetStandardOrHigher (this TargetFrameworkMoniker framework, DotNetCoreVersion version) + public static bool IsNetCoreAppOrHigher (this TargetFrameworkMoniker framework, DotNetCoreVersion version) { - DotNetCoreVersion.TryParse (framework.Version, out var dotNetCoreVersion); - if (dotNetCoreVersion == null) - return false; + return framework.IsNetCoreApp () && framework.IsVersionOrHigher (version); + } - return framework.IsNetStandard () && dotNetCoreVersion >= version; + public static bool IsNetStandardOrHigher (this TargetFrameworkMoniker framework, DotNetCoreVersion version) + { + return framework.IsNetStandard () && framework.IsVersionOrHigher (version); } } } diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationNodeBuilder.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationNodeBuilder.cs index 74a5a2c965..5c09463382 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationNodeBuilder.cs @@ -126,7 +126,7 @@ namespace MonoDevelop.Gettext.NodeBuilders UpdateTranslations (project, translation); } - static Task currentUpdateTranslationOperation = Task.FromResult (0); + static Task currentUpdateTranslationOperation = Task.CompletedTask; void UpdateTranslationsAsync (ProgressMonitor monitor, TranslationProject project, Translation translation) { diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationProjectNodeBuilder.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationProjectNodeBuilder.cs index 01e255d42a..0cadc4bcf3 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationProjectNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationProjectNodeBuilder.cs @@ -157,7 +157,7 @@ namespace MonoDevelop.Gettext.NodeBuilders chooser.Dispose (); } } - static Task currentUpdateTranslationOperation = Task.FromResult (0); + static Task currentUpdateTranslationOperation = Task.CompletedTask; void UpdateTranslationsAsync (ProgressMonitor monitor, TranslationProject project) { diff --git a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs index 3bdfd4a8b1..fa9dba2031 100644 --- a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs +++ b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs @@ -71,7 +71,7 @@ namespace MonoDevelop.GtkCore.GuiBuilder { this.fileName = fileName; this.project = project; - Counters.GuiProjectsLoaded++; + Counters.GuiProjectsLoaded.Inc (1); GuiBuilderService.NotifyGuiProjectLoaded (); } @@ -96,7 +96,7 @@ namespace MonoDevelop.GtkCore.GuiBuilder hasError = true; } - Counters.SteticProjectsLoaded++; + Counters.SteticProjectsLoaded.Inc (1); gproject.ResourceProvider = GtkDesignInfo.FromProject (project).ResourceProvider; gproject.WidgetAdded += OnAddWidget; gproject.WidgetRemoved += OnRemoveWidget; @@ -125,8 +125,8 @@ namespace MonoDevelop.GtkCore.GuiBuilder if (gproject == null) return; - Counters.SteticProjectsLoaded--; - + Counters.SteticProjectsLoaded.Dec (1); + if (Unloaded != null) Unloaded (this, EventArgs.Empty); if (formInfos != null) { @@ -252,7 +252,7 @@ namespace MonoDevelop.GtkCore.GuiBuilder if (disposed) return; GuiBuilderService.NotifyGuiProjectUnloaded (); - Counters.GuiProjectsLoaded--; + Counters.GuiProjectsLoaded.Dec (1); disposed = true; if (watcher != null) watcher.Dispose (); diff --git a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.csproj b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.csproj index 2e73602ef8..ed4cf412c1 100644 --- a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.csproj +++ b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.csproj @@ -72,11 +72,6 @@ <Name>CSharpBinding</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\..\external\nrefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj"> - <Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project> - <Name>ICSharpCode.NRefactory.CSharp</Name> - <Private>False</Private> - </ProjectReference> </ItemGroup> <ItemGroup> <None Include="icons\window.png" /> diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.UI.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.UI.cs index f8e2435b85..5a23a14c4d 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.UI.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.UI.cs @@ -65,10 +65,10 @@ namespace MonoDevelop.PackageManagement ComboBox packageVersionComboBox; HBox packageVersionsHBox; Label packageVersionsLabel; - Label browseLabel; - Label installedLabel; - Label updatesLabel; - Label consolidateLabel; + CustomButtonLabel browseLabel; + CustomButtonLabel installedLabel; + CustomButtonLabel updatesLabel; + CustomButtonLabel consolidateLabel; HBox tabGroup; VBox projectsListViewVBox; Label projectsListViewLabel; @@ -114,33 +114,29 @@ namespace MonoDevelop.PackageManagement tabGroup = new HBox (); int tabLabelMinWidth = 60; - browseLabel = new Label (); + browseLabel = new CustomButtonLabel (); browseLabel.Text = GettextCatalog.GetString ("Browse"); browseLabel.Tag = browseLabel.Text; browseLabel.MinWidth = tabLabelMinWidth; browseLabel.MarginLeft = 10; - browseLabel.CanGetFocus = true; tabGroup.PackStart (browseLabel); - installedLabel = new Label (); + installedLabel = new CustomButtonLabel (); installedLabel.Text = GettextCatalog.GetString ("Installed"); installedLabel.Tag = installedLabel.Text; installedLabel.MinWidth = tabLabelMinWidth; - installedLabel.CanGetFocus = true; tabGroup.PackStart (installedLabel); - updatesLabel = new Label (); + updatesLabel = new CustomButtonLabel (); updatesLabel.Text = GettextCatalog.GetString ("Updates"); updatesLabel.Tag = updatesLabel.Text; updatesLabel.MinWidth = tabLabelMinWidth; - updatesLabel.CanGetFocus = true; tabGroup.PackStart (updatesLabel); - consolidateLabel = new Label (); + consolidateLabel = new CustomButtonLabel (); consolidateLabel.Text = GettextCatalog.GetString ("Consolidate"); consolidateLabel.Tag = consolidateLabel.Text; consolidateLabel.MinWidth = tabLabelMinWidth; - consolidateLabel.CanGetFocus = true; tabGroup.PackStart (consolidateLabel); topHBox.PackStart (tabGroup); @@ -506,5 +502,63 @@ namespace MonoDevelop.PackageManagement } } } + + sealed class CustomButtonLabel : Canvas + { + readonly TextLayout layout = new TextLayout (); + Size preferredSize; + + public string Text { + get { return layout.Text; } + set { + layout.Markup = null; + layout.Text = value; + Accessible.Title = layout.Text; + preferredSize = layout.GetSize (); + OnPreferredSizeChanged (); + } + } + + public string Markup { + get { return layout.Markup; } + set { + layout.Markup = value; + Accessible.Title = layout.Text; + preferredSize = layout.GetSize (); + OnPreferredSizeChanged (); + } + } + + public CustomButtonLabel () + { + CanGetFocus = true; + Accessible.Role = Xwt.Accessibility.Role.Button; + } + + protected override Size OnGetPreferredSize (SizeConstraint widthConstraint, SizeConstraint heightConstraint) + { + return preferredSize; + } + + protected override void OnDraw (Context ctx, Rectangle dirtyRect) + { + if (HasFocus) { + ctx.SetColor (Ide.Gui.Styles.BaseSelectionBackgroundColor); + } + var actualSize = Size; + var x = Math.Max (0, (actualSize.Width - preferredSize.Width) / 2); + var y = Math.Max (0, (actualSize.Height - preferredSize.Height) / 2); + x += x % 2; // align pixels + ctx.DrawTextLayout (layout, x, y); + } + + protected override void Dispose (bool disposing) + { + if (disposing) { + layout.Dispose (); + } + base.Dispose (disposing); + } + } } diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.cs index f4266e4ee3..b5b1fac718 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.cs @@ -1156,7 +1156,7 @@ namespace MonoDevelop.PackageManagement UpdatePackageResultsLabel (ManagePackagesPage.Consolidate, consolidateLabel); } - void UpdatePackageResultsLabel (ManagePackagesPage page, Label label) + void UpdatePackageResultsLabel (ManagePackagesPage page, CustomButtonLabel label) { string text = (string)label.Tag; if (page == viewModel.PageSelected) { @@ -1168,7 +1168,7 @@ namespace MonoDevelop.PackageManagement } } - static void UpdatePackageResultsLabelA11y (Label label, bool active) + static void UpdatePackageResultsLabelA11y (Widget label, bool active) { if (label.Surface.ToolkitEngine.Type == ToolkitType.Gtk) { var widget = label.Surface.NativeWidget as Gtk.Widget; diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialogRunner.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialogRunner.cs index e766df17e2..67d3035ae0 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialogRunner.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialogRunner.cs @@ -38,6 +38,7 @@ namespace MonoDevelop.PackageManagement public void Run (IDotNetProject project = null, string initialSearch = null) { try { + PackageManagementCredentialService.Reset (); bool configurePackageSources = false; do { using (ManagePackagesDialog dialog = CreateDialog (initialSearch, project)) { diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj index ff695562c1..b96a78138b 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj @@ -159,6 +159,7 @@ <Compile Include="MonoDevelop.PackageManagement.Tests\UpdateStrictPackageDependenciesTests.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests\UpdateMultipleNuGetPackagesActionTests.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableUpdateMultipleNuGetPackagesAction.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests\MonoDevelopNuGetResourceProviderFactoryTests.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj"> diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/MonoDevelopNuGetResourceProviderFactoryTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/MonoDevelopNuGetResourceProviderFactoryTests.cs new file mode 100644 index 0000000000..522b851f30 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/MonoDevelopNuGetResourceProviderFactoryTests.cs @@ -0,0 +1,70 @@ +// +// MonoDevelopNuGetResourceProviderFactoryTests.cs +// +// Author: +// Matt Ward <matt.ward@microsoft.com> +// +// Copyright (c) 2019 Microsoft Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using NuGet.Protocol; +using NuGet.Protocol.Core.Types; +using NUnit.Framework; + +namespace MonoDevelop.PackageManagement.Tests +{ + [TestFixture] + public class MonoDevelopNuGetResourceProviderFactoryTests + { + [Test] + public void CustomProviderFactory_HasSameProvidersAsDefault_ExceptHttpHandlerResourceProvider () + { + bool customHttpHandlerResourceV3Provider = false; + var customProviderItems = new List<string> (); + var defaultProviderItems = new List<string> (); + + // Touch the MonoDevelopNuGetResourceProviderFactory so it initializes the NuGet Respository.Provider. + // The NuGet addin uses MonoDevelopNuGetResourceProviderFactory directly some parts of NuGet create + // new SourceRepository instances using Repository.Provider directory. + var _ = MonoDevelopNuGetResourceProviderFactory.GetProviders (); + + foreach (Lazy<INuGetResourceProvider> item in Repository.Provider.GetCoreV3 ()) { + Type type = item.Value.GetType (); + if (type == typeof (MonoDevelopHttpHandlerResourceV3Provider)) { + type = typeof (HttpHandlerResourceV3Provider); + customHttpHandlerResourceV3Provider = true; + } + customProviderItems.Add (type.Name); + } + + var defaultProviderFactory = new Repository.ProviderFactory (); + + foreach (Lazy<INuGetResourceProvider> item in defaultProviderFactory.GetCoreV3 ()) { + Type type = item.Value.GetType (); + defaultProviderItems.Add (type.Name); + } + + Assert.AreEqual (defaultProviderItems, customProviderItems); + Assert.IsTrue (customHttpHandlerResourceV3Provider, "Custom MonoDevelopHttpHandlerResourceV3Provider not used"); + } + } +} diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj index 1065766e15..ba2765a202 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj @@ -314,7 +314,6 @@ <Compile Include="MonoDevelop.PackageManagement\ItemTemplateNuGetPackageInstaller.cs" /> <Compile Include="Gui\MonoDevelop.PackageManagement.PackageManagementOptionsWidget.cs" /> <Compile Include="Gui\MonoDevelop.PackageManagement.PackageSourcesWidget.cs" /> - <Compile Include="MonoDevelop.PackageManagement\RepositoryProviderFactoryExtensions.cs" /> <Compile Include="MonoDevelop.PackageManagement\MonoDevelopHttpHandlerResourceV3Provider.cs" /> <Compile Include="MonoDevelop.PackageManagement\MonoDevelopServerWarningLogHandler.cs" /> <Compile Include="MonoDevelop.PackageManagement\NuGetHttpSourceAuthenticationHandler.cs" /> @@ -368,6 +367,8 @@ <Compile Include="MonoDevelop.PackageManagement\PackageManagementCanReferenceProjectExtension.cs" /> <Compile Include="MonoDevelop.PackageManagement\UpdateMultipleNuGetPackagesAction.cs" /> <Compile Include="MonoDevelop.PackageManagement\ProjectReferenceMaintainerCollection.cs" /> + <Compile Include="MonoDevelop.PackageManagement\MonoDevelopPluginFactory.cs" /> + <Compile Include="MonoDevelop.PackageManagement\MonoDevelopNuGetResourceProviderFactory.cs" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="MonoDevelop.PackageManagement.addin.xml" /> @@ -449,11 +450,6 @@ <Name>MonoDevelop.DesignerSupport</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\..\core\MonoDevelop.Ide\MonoDevelop.Ide.csproj"> <Project>{27096E7F-C91C-4AC6-B289-6897A701DF21}</Project> <Name>MonoDevelop.Ide</Name> diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/LicenseAcceptanceService.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/LicenseAcceptanceService.cs index bd66949c15..57d8994914 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/LicenseAcceptanceService.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/LicenseAcceptanceService.cs @@ -29,6 +29,7 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using MonoDevelop.Core;
+using MonoDevelop.Core.FeatureConfiguration; using MonoDevelop.Ide;
namespace MonoDevelop.PackageManagement
@@ -37,6 +38,9 @@ namespace MonoDevelop.PackageManagement {
public Task<bool> AcceptLicenses (IEnumerable<NuGetPackageLicense> licenses)
{
+ if (FeatureSwitchService.IsFeatureEnabled ("NuGetLicenseAcceptanceDialog") == false)
+ return Task.FromResult (true);
+
if (Runtime.IsMainThread)
return ShowLicenseAcceptanceDialog (licenses);
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopCommonOperations.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopCommonOperations.cs index 995fc8ac3c..f5b704b1e0 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopCommonOperations.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopCommonOperations.cs @@ -36,7 +36,7 @@ namespace MonoDevelop.PackageManagement {
public Task CollapseAllNodes (ISolutionManager solutionManager)
{
- return Task.FromResult (0);
+ return Task.CompletedTask;
}
public Task OpenFile (string fullPath)
@@ -48,7 +48,7 @@ namespace MonoDevelop.PackageManagement public Task SaveSolutionExplorerNodeStates (ISolutionManager solutionManager)
{
- return Task.FromResult (0);
+ return Task.CompletedTask;
}
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopMSBuildNuGetProjectSystem.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopMSBuildNuGetProjectSystem.cs index 9d5dcee75a..3261ea8631 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopMSBuildNuGetProjectSystem.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopMSBuildNuGetProjectSystem.cs @@ -283,7 +283,7 @@ namespace MonoDevelop.PackageManagement public Task BeginProcessingAsync ()
{
- return Task.FromResult (true);
+ return Task.CompletedTask;
}
// TODO: Support recursive.
@@ -304,7 +304,7 @@ namespace MonoDevelop.PackageManagement public Task EndProcessingAsync ()
{
- return Task.FromResult (true);
+ return Task.CompletedTask;
}
public bool FileExistsInProject (string path)
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RepositoryProviderFactoryExtensions.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopNuGetResourceProviderFactory.cs index c106bcf839..43d08989e1 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RepositoryProviderFactoryExtensions.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopNuGetResourceProviderFactory.cs @@ -1,8 +1,28 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // -// Based on FactoryExtensionsV3 and FactoryExtensionsVS -// From: https://github.com/NuGet/NuGet.Client/ +// MonoDevelopNuGetResourceProviderFactory.cs +// +// Author: +// Matt Ward <matt.ward@microsoft.com> +// +// Copyright (c) 2019 Microsoft Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. using System; using System.Collections.Generic; @@ -12,19 +32,25 @@ using NuGet.Protocol.LocalRepositories; namespace MonoDevelop.PackageManagement { - static class RepositoryProviderFactoryExtensions + class MonoDevelopNuGetResourceProviderFactory : Repository.ProviderFactory { - public static IEnumerable<Lazy<INuGetResourceProvider>> GetMonoDevelop (this Repository.ProviderFactory factory) + static MonoDevelopNuGetResourceProviderFactory () + { + // Some parts of NuGet create new SourceRepository instances which bypasses the custom + // MonoDevelopHttpHandlerResourceV3Provider used when SourceRepository instances are created by the NuGet + // addin itself. To prevent this the default provider factory is replaced with a custom provider factory. + Repository.Provider = new MonoDevelopNuGetResourceProviderFactory (); + } + + public static IEnumerable<Lazy<INuGetResourceProvider>> GetProviders () { - foreach (Lazy<INuGetResourceProvider> item in Repository.Provider.GetMonoDevelopCoreV3 ()) { - yield return item; - } + return Repository.Provider.GetCoreV3 (); } /// <summary> /// Includes a custom HttpHandlerResourceV3Provider which can use native HttpMessageHandlers defined by MonoDevelop. /// </summary> - public static IEnumerable<Lazy<INuGetResourceProvider>> GetMonoDevelopCoreV3 (this Repository.ProviderFactory factory) + public override IEnumerable<Lazy<INuGetResourceProvider>> GetCoreV3 () { yield return new Lazy<INuGetResourceProvider> (() => new FeedTypeResourceProvider ()); yield return new Lazy<INuGetResourceProvider> (() => new DependencyInfoResourceV3Provider ()); @@ -33,7 +59,9 @@ namespace MonoDevelop.PackageManagement yield return new Lazy<INuGetResourceProvider> (() => new MetadataResourceV3Provider ()); yield return new Lazy<INuGetResourceProvider> (() => new RawSearchResourceV3Provider ()); yield return new Lazy<INuGetResourceProvider> (() => new RegistrationResourceV3Provider ()); + yield return new Lazy<INuGetResourceProvider> (() => new SymbolPackageUpdateResourceV3Provider ()); yield return new Lazy<INuGetResourceProvider> (() => new ReportAbuseResourceV3Provider ()); + yield return new Lazy<INuGetResourceProvider> (() => new PackageDetailsUriResourceV3Provider ()); yield return new Lazy<INuGetResourceProvider> (() => new ServiceIndexResourceV3Provider ()); yield return new Lazy<INuGetResourceProvider> (() => new ODataServiceDocumentResourceV2Provider ()); yield return new Lazy<INuGetResourceProvider> (() => new MonoDevelopHttpHandlerResourceV3Provider ()); @@ -58,7 +86,8 @@ namespace MonoDevelop.PackageManagement yield return new Lazy<INuGetResourceProvider> (() => new PackageMetadataResourceV3Provider ()); yield return new Lazy<INuGetResourceProvider> (() => new AutoCompleteResourceV2FeedProvider ()); yield return new Lazy<INuGetResourceProvider> (() => new AutoCompleteResourceV3Provider ()); - yield return new Lazy<INuGetResourceProvider> (() => new PluginResourceProvider ()); + yield return new Lazy<INuGetResourceProvider> (() => new PluginResourceProvider (PackageManagementServices.PluginManager)); + yield return new Lazy<INuGetResourceProvider> (() => new RepositorySignatureResourceProvider ()); yield return new Lazy<INuGetResourceProvider> (() => new FindLocalPackagesResourceUnzippedProvider ()); yield return new Lazy<INuGetResourceProvider> (() => new FindLocalPackagesResourceV2Provider ()); yield return new Lazy<INuGetResourceProvider> (() => new FindLocalPackagesResourceV3Provider ()); diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopPluginFactory.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopPluginFactory.cs new file mode 100644 index 0000000000..9d8ce28c58 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/MonoDevelopPluginFactory.cs @@ -0,0 +1,100 @@ +// +// MonoDevelopPluginFactory.cs +// +// Author: +// Matt Ward <matt.ward@microsoft.com> +// +// Copyright (c) 2020 Microsoft Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MonoDevelop.Core; +using MonoDevelop.Core.Assemblies; +using NuGet.Protocol.Plugins; + +namespace MonoDevelop.PackageManagement +{ + sealed class MonoDevelopPluginFactory : IPluginFactory + { + readonly PluginFactory pluginFactory; + + public MonoDevelopPluginFactory (TimeSpan idleTimeout) + { + pluginFactory = new PluginFactory (idleTimeout); + } + + public void Dispose () + { + pluginFactory.Dispose (); + } + + public Task<IPlugin> GetOrCreateAsync ( + string filePath, + IEnumerable<string> arguments, + IRequestHandlers requestHandlers, + ConnectionOptions options, + CancellationToken sessionCancellationToken) + { + if (!Platform.IsWindows) { + var modifiedCommandLine = GetModifiedCommandLine (filePath, arguments); + if (modifiedCommandLine != null) { + filePath = modifiedCommandLine.FilePath; + arguments = modifiedCommandLine.Arguments; + } + } + + return pluginFactory.GetOrCreateAsync (filePath, arguments, requestHandlers, options, sessionCancellationToken); + } + + ModifiedCommandLineArguments GetModifiedCommandLine (string filePath, IEnumerable<string> arguments) + { + string extension = Path.GetExtension (filePath); + if (!StringComparer.OrdinalIgnoreCase.Equals (".exe", extension)) { + return null; + } + + var runtime = MonoRuntimeInfo.FromCurrentRuntime (); + if (runtime == null) { + return null; + } + + string monoPath = Path.Combine (runtime.Prefix, "bin", "mono"); + + List<string> updatedArguments = arguments.ToList (); + updatedArguments.Insert (0, "\"" + filePath + "\""); + + return new ModifiedCommandLineArguments { + FilePath = monoPath, + Arguments = updatedArguments + }; + } + + sealed class ModifiedCommandLineArguments + { + public string FilePath { get; set; } + public List<string> Arguments { get; set; } + } + } +} diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/NuGetProjectExtensions.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/NuGetProjectExtensions.cs index 9e405faacf..45bbbc864c 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/NuGetProjectExtensions.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/NuGetProjectExtensions.cs @@ -60,7 +60,7 @@ namespace MonoDevelop.PackageManagement return buildIntegratedProject.PostProcessAsync (context, token);
}
- return Task.FromResult (0);
+ return Task.CompletedTask;
}
public static void OnAfterExecuteActions (this NuGetProject project, IEnumerable<NuGetProjectAction> actions)
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/NuGetProjectServices.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/NuGetProjectServices.cs index 2f8a148ec3..d28b5fd3a3 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/NuGetProjectServices.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/NuGetProjectServices.cs @@ -67,7 +67,7 @@ namespace MonoDevelop.PackageManagement public Task SaveProjectAsync (CancellationToken token) { - return Task.FromResult (0); + return Task.CompletedTask; } public Task<bool> ExecutePackageInitScriptAsync ( @@ -88,7 +88,7 @@ namespace MonoDevelop.PackageManagement bool throwOnFailure, CancellationToken token) { - return Task.FromResult (0); + return Task.CompletedTask; } } } diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementCredentialService.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementCredentialService.cs index 44a38d885b..18b4936515 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementCredentialService.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementCredentialService.cs @@ -32,6 +32,7 @@ using MonoDevelop.Core; using NuGet.CommandLine; using NuGet.Credentials; using NuGet.Protocol; +using NuGet.Protocol.Plugins; namespace MonoDevelop.PackageManagement { @@ -60,6 +61,7 @@ namespace MonoDevelop.PackageManagement var credentialProviders = new List<ICredentialProvider>(); credentialProviders.Add (CreateSettingsCredentialProvider ()); + credentialProviders.AddRange (GetPluginsCredentialProviders ()); credentialProviders.Add (new MonoDevelopCredentialProvider ()); return credentialProviders; @@ -72,6 +74,17 @@ namespace MonoDevelop.PackageManagement return new SettingsCredentialProvider (packageSourceProvider); } + static IEnumerable<ICredentialProvider> GetPluginsCredentialProviders () + { + var builder = new SecurePluginCredentialProviderBuilder ( + PackageManagementServices.PluginManager, + canShowDialog: false, + logger: NuGet.Common.NullLogger.Instance + ); + var providers = builder.BuildAllAsync ().Result; + return providers; + } + /// <summary> /// The credential service puts itself in a retry mode if a credential provider /// is checked. This results in credentials stored in the key chain being ignored diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementLogger.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementLogger.cs index e050f320aa..8b0e887581 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementLogger.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementLogger.cs @@ -98,13 +98,13 @@ namespace MonoDevelop.PackageManagement public Task LogAsync (LogLevel level, string data)
{
Log (level, data);
- return Task.FromResult (true);
+ return Task.CompletedTask;
}
public Task LogAsync (ILogMessage message)
{
Log (message);
- return Task.FromResult (true);
+ return Task.CompletedTask;
}
public void Log (LogLevel level, string data)
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementServices.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementServices.cs index d095f7f9ae..72cfb0e590 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementServices.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementServices.cs @@ -28,7 +28,10 @@ using System;
using System.IO;
-
+using NuGet.Common; +using NuGet.Configuration; +using NuGet.Protocol.Plugins; + namespace MonoDevelop.PackageManagement
{
public static class PackageManagementServices
@@ -47,6 +50,7 @@ namespace MonoDevelop.PackageManagement //static readonly AnalyzerPackageMonitor analyzerPackageMonitor;
static readonly MonoDevelopHttpUserAgent userAgent = new MonoDevelopHttpUserAgent ();
static readonly NuGetConfigFileChangedMonitor nuGetConfigFileChangedMonitor = new NuGetConfigFileChangedMonitor ();
+ static readonly PluginManager pluginManager;
static PackageManagementServices()
{
@@ -65,6 +69,8 @@ namespace MonoDevelop.PackageManagement workspace = new PackageManagementWorkspace ();
+ pluginManager = CreatePluginManager ();
+
credentialService = new PackageManagementCredentialService ();
credentialService.Initialize ();
@@ -76,6 +82,23 @@ namespace MonoDevelop.PackageManagement MonoDevelop.Refactoring.PackageInstaller.PackageInstallerServiceFactory.PackageServices = new MonoDevelop.PackageManagement.Refactoring.NuGetPackageServicesProxy (); }
+ static PluginManager CreatePluginManager ()
+ {
+ return new PluginManager (
+ EnvironmentVariableWrapper.Instance,
+ new Lazy<IPluginDiscoverer> (InitializeDiscoverer),
+ (TimeSpan idleTimeout) => new MonoDevelopPluginFactory (idleTimeout),
+ new Lazy<string> (() => SettingsUtility.GetPluginsCacheFolder ()));
+ }
+
+ static PluginDiscoverer InitializeDiscoverer ()
+ {
+ var verifier = EmbeddedSignatureVerifier.Create ();
+
+ string pluginPaths = EnvironmentVariableWrapper.Instance.GetEnvironmentVariable ("NUGET_PLUGIN_PATHS");
+ return new PluginDiscoverer (pluginPaths, verifier);
+ }
+
internal static void InitializeCredentialService ()
{
credentialService.Initialize ();
@@ -116,5 +139,9 @@ namespace MonoDevelop.PackageManagement internal static ProjectTargetFrameworkMonitor ProjectTargetFrameworkMonitor { get { return projectTargetFrameworkMonitor; } }
+
+ internal static IPluginManager PluginManager {
+ get { return pluginManager; }
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SourceRepositoryProvider.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SourceRepositoryProvider.cs index 3bc25eef1a..887f7286ac 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SourceRepositoryProvider.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SourceRepositoryProvider.cs @@ -40,7 +40,7 @@ namespace MonoDevelop.PackageManagement public static ISourceRepositoryProvider CreateSourceRepositoryProvider (ISettings settings)
{
var packageSourceProvider = new MonoDevelopPackageSourceProvider (settings);
- return new SourceRepositoryProvider (packageSourceProvider, Repository.Provider.GetMonoDevelop ());
+ return new SourceRepositoryProvider (packageSourceProvider, MonoDevelopNuGetResourceProviderFactory.GetProviders ());
}
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.Credentials/CredentialService.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.Credentials/CredentialService.cs index f189f62439..f4c412ff14 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/NuGet.Credentials/CredentialService.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.Credentials/CredentialService.cs @@ -103,13 +103,18 @@ namespace NuGet.Credentials CredentialResponse response; if (!TryFromCredentialCache (uri, type, isRetry, provider, out response)) { + /* Temporarily disable interactive-ness with secure plugin provider + * to avoid them blocking on requesting user-input for device flow auth + */ + var nonInteractive = _nonInteractive || provider is SecurePluginCredentialProvider; + response = await provider.GetAsync ( uri, proxy, type, message, isRetry, - _nonInteractive, + nonInteractive, cancellationToken); // Check that the provider gave us a valid response. diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs index 365927bafe..e1971f465f 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs @@ -195,7 +195,7 @@ namespace MonoDevelop.SourceEditor private SourceEditorView (DocumentAndLoaded doc)
{
- Counters.LoadedEditors++; + Counters.LoadedEditors.Inc (1); breakpoints = DebuggingService.Breakpoints; widget = new SourceEditorWidget (this, doc.Document);
@@ -906,7 +906,7 @@ namespace MonoDevelop.SourceEditor {
var document = Document;
if (document == null)
- return TaskUtil.Default<object> ();
+ return Task.CompletedTask;
document.TextChanged -= OnTextReplaced; if (warnOverwrite) { @@ -970,7 +970,7 @@ namespace MonoDevelop.SourceEditor //document.AddMarker (7, new MyExtendingLineMarker ()); //document.AddMarker (10, new MyExtendingLineMarker ()); - return TaskUtil.Default<object> ();
+ return Task.CompletedTask;
}
void HandleTextEditorVAdjustmentChanged (object sender, EventArgs e) @@ -1056,7 +1056,7 @@ namespace MonoDevelop.SourceEditor StoreSettings (); - Counters.LoadedEditors--; + Counters.LoadedEditors.Dec (1); /* if (messageBubbleHighlightPopupWindow != null) messageBubbleHighlightPopupWindow.Destroy ();*/ diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/MonoDevelop.TextEditor.Cocoa.csproj b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/MonoDevelop.TextEditor.Cocoa.csproj index 43dfde632b..065924b5e5 100644 --- a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/MonoDevelop.TextEditor.Cocoa.csproj +++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/MonoDevelop.TextEditor.Cocoa.csproj @@ -133,6 +133,14 @@ <None Remove="icons\go-down-16%402x.png" /> <None Remove="icons\go-down-16~contrast.png" /> <None Remove="icons\go-down-16~contrast%402x.png" /> + <None Remove="icons\vs-go-to-line-16.png" /> + <None Remove="icons\vs-go-to-line-16~contrast%402x.png" /> + <None Remove="icons\vs-go-to-line-16~contrast~dark.png" /> + <None Remove="icons\vs-go-to-line-16~contrast~dark%402x.png" /> + <None Remove="icons\vs-go-to-line-16~contrast.png" /> + <None Remove="icons\vs-go-to-line-16%402x.png" /> + <None Remove="icons\vs-go-to-line-16~dark%402x.png" /> + <None Remove="icons\vs-go-to-line-16~dark.png" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="icons\vs-find-replace-close-16.png" /> @@ -159,6 +167,14 @@ <EmbeddedResource Include="icons\go-down-16%402x.png" /> <EmbeddedResource Include="icons\go-down-16~contrast.png" /> <EmbeddedResource Include="icons\go-down-16~contrast%402x.png" /> + <EmbeddedResource Include="icons\vs-go-to-line-16.png"/> + <EmbeddedResource Include="icons\vs-go-to-line-16~contrast%402x.png"/> + <EmbeddedResource Include="icons\vs-go-to-line-16~contrast~dark.png"/> + <EmbeddedResource Include="icons\vs-go-to-line-16~contrast~dark%402x.png"/> + <EmbeddedResource Include="icons\vs-go-to-line-16~contrast.png"/> + <EmbeddedResource Include="icons\vs-go-to-line-16%402x.png"/> + <EmbeddedResource Include="icons\vs-go-to-line-16~dark%402x.png"/> + <EmbeddedResource Include="icons\vs-go-to-line-16~dark.png"/> </ItemGroup> <Target Name="BuildTextMate" BeforeTargets="Compile"> <MSBuild Projects="$(VSEditorCoreDirectory)src\Editor\TextMate\TMRegEx\TMRegEx.proj" Targets="Build" Properties="Configuration=$(Configuration)" /> diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/Properties/MonoDevelop.TextEditor.Cocoa.addin.xml b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/Properties/MonoDevelop.TextEditor.Cocoa.addin.xml index 62a9596240..4738e17729 100644 --- a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/Properties/MonoDevelop.TextEditor.Cocoa.addin.xml +++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/Properties/MonoDevelop.TextEditor.Cocoa.addin.xml @@ -89,6 +89,7 @@ <StockIcon stockid="vs-find-replace-option-case-sensitive" resource="vs-find-replace-option-case-sensitive-16.png" size="Menu" imageid="{6114fe54-2a4a-4354-aabb-d2b8fad160a5}#3" /> <StockIcon stockid="vs-find-replace-option-regex" resource="vs-find-replace-option-regex-16.png" size="Menu" imageid="{6114fe54-2a4a-4354-aabb-d2b8fad160a5}#4" /> <StockIcon stockid="vs-find-replace-option-whole-words-only" resource="vs-find-replace-option-whole-words-only-16.png" size="Menu" imageid="{6114fe54-2a4a-4354-aabb-d2b8fad160a5}#5" /> + <StockIcon stockid="vs-go-to-line" resource="vs-go-to-line-16.png" size="Menu" imageid="1705" /> <StockIcon stockid="vs-signature-help-prev" resource="go-up-16.png" size="Menu" imageid="{95fdedcb-dc13-48a8-8165-ed1fff877d9a}#1" /> <StockIcon stockid="vs-signature-help-next" resource="go-down-16.png" size="Menu" imageid="{95fdedcb-dc13-48a8-8165-ed1fff877d9a}#2" /> </Extension> diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16.png b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16.png Binary files differnew file mode 100644 index 0000000000..855b4bd4e2 --- /dev/null +++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16.png diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16@2x.png b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16@2x.png Binary files differnew file mode 100644 index 0000000000..a9fd1127e8 --- /dev/null +++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16@2x.png diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~contrast.png b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~contrast.png Binary files differnew file mode 100644 index 0000000000..dcdf495008 --- /dev/null +++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~contrast.png diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~contrast@2x.png b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~contrast@2x.png Binary files differnew file mode 100644 index 0000000000..77fdb89da7 --- /dev/null +++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~contrast@2x.png diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~contrast~dark.png b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~contrast~dark.png Binary files differnew file mode 100644 index 0000000000..cd0d96576a --- /dev/null +++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~contrast~dark.png diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~contrast~dark@2x.png b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~contrast~dark@2x.png Binary files differnew file mode 100644 index 0000000000..86555543d8 --- /dev/null +++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~contrast~dark@2x.png diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~dark.png b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~dark.png Binary files differnew file mode 100644 index 0000000000..7caa0f88a4 --- /dev/null +++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~dark.png diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~dark@2x.png b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~dark@2x.png Binary files differnew file mode 100644 index 0000000000..ff411b5a51 --- /dev/null +++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/icons/vs-go-to-line-16~dark@2x.png diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/TextViewContent.cs b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/TextViewContent.cs index 0e2fb5832b..29c89bce8f 100644 --- a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/TextViewContent.cs +++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/TextViewContent.cs @@ -444,7 +444,7 @@ namespace MonoDevelop.TextEditor UpdateOptionsFromPolicy (); if (editorConfigContext == null) - return Task.FromResult (false); + return Task.CompletedTask; if (editorConfigContext.CurrentConventions.UniversalConventions.TryGetIndentStyle (out var indentStyle)) SetOptionValue (DefaultOptions.ConvertTabsToSpacesOptionName, indentStyle == IndentStyle.Spaces); @@ -486,7 +486,7 @@ namespace MonoDevelop.TextEditor EditorOptions.SetOptionValue (DefaultTextViewOptions.VerticalRulersName, verticalRulers ?? Array.Empty<int> ()); #endif - return Task.FromResult (true); + return Task.CompletedTask; } private void PolicyChanged (object sender, PolicyChangedEventArgs e) diff --git a/main/src/addins/MonoDevelop.UnitTesting/AddinInfo.cs b/main/src/addins/MonoDevelop.UnitTesting/AddinInfo.cs index f873a69fa0..4bba15a67a 100644 --- a/main/src/addins/MonoDevelop.UnitTesting/AddinInfo.cs +++ b/main/src/addins/MonoDevelop.UnitTesting/AddinInfo.cs @@ -6,6 +6,7 @@ using Mono.Addins.Description; [assembly:Addin ("UnitTesting", Namespace = "MonoDevelop", Version = MonoDevelop.BuildInfo.Version, + CompatVersion = "8.5", Category = "Testing")] [assembly:AddinName ("Unit Testing core support")] diff --git a/main/src/addins/MonoDevelop.UnitTesting/MonoDevelop.UnitTesting.csproj b/main/src/addins/MonoDevelop.UnitTesting/MonoDevelop.UnitTesting.csproj index 8d42275ca8..d768bb8c33 100644 --- a/main/src/addins/MonoDevelop.UnitTesting/MonoDevelop.UnitTesting.csproj +++ b/main/src/addins/MonoDevelop.UnitTesting/MonoDevelop.UnitTesting.csproj @@ -48,11 +48,6 @@ <Name>Xwt</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\MonoDevelop.DotNetCore\MonoDevelop.DotNetCore.csproj"> <Project>{6868153E-41EA-43A4-A81A-C1E7256373F7}</Project> <Name>MonoDevelop.DotNetCore</Name> diff --git a/main/src/addins/MonoDevelop.UnitTesting/Services/AbstractResultsStore.cs b/main/src/addins/MonoDevelop.UnitTesting/Services/AbstractResultsStore.cs index ba03343c15..43bba4ebe1 100644 --- a/main/src/addins/MonoDevelop.UnitTesting/Services/AbstractResultsStore.cs +++ b/main/src/addins/MonoDevelop.UnitTesting/Services/AbstractResultsStore.cs @@ -401,37 +401,21 @@ namespace MonoDevelop.UnitTesting } [Serializable] - public class TestRecordCollection: CollectionBase + public class TestRecordCollection: List<TestRecord> { - public TestRecord this [int n] { - get { return (TestRecord) ((IList)this) [n]; } - } - public TestRecord this [string name] { get { - for (int n=0; n<List.Count; n++) - if (((TestRecord)List [n]).Name == name) - return (TestRecord) List [n]; + foreach (var value in this) { + if (value.Name == name) + return value; + } return null; } } - - public void Add (TestRecord test) - { - ((IList)this).Add (test); - } } [Serializable] - public class UnitTestResultCollection: CollectionBase + public class UnitTestResultCollection: List<UnitTestResult> { - public UnitTestResult this [int n] { - get { return (UnitTestResult) ((IList)this) [n]; } - } - - public void Add (UnitTestResult test) - { - ((IList)this).Add (test); - } } } diff --git a/main/src/addins/MonoDevelop.UnitTesting/Services/BinaryResultsStore.cs b/main/src/addins/MonoDevelop.UnitTesting/Services/BinaryResultsStore.cs index 449ce82484..d57c51d0f7 100644 --- a/main/src/addins/MonoDevelop.UnitTesting/Services/BinaryResultsStore.cs +++ b/main/src/addins/MonoDevelop.UnitTesting/Services/BinaryResultsStore.cs @@ -26,7 +26,7 @@ using System; using System.Xml.Serialization; using System.IO; -using ICSharpCode.NRefactory.Utils; +using Newtonsoft.Json; namespace MonoDevelop.UnitTesting { @@ -54,7 +54,7 @@ namespace MonoDevelop.UnitTesting const string binaryExtension = ".test-result"; const string xmlExtension = ".xml"; - FastSerializer fastSerializer = new FastSerializer(); + JsonSerializer jsonSerializer = JsonSerializer.CreateDefault (); XmlSerializer xmlSerializer; XmlSerializer XmlSerializer { @@ -72,9 +72,10 @@ namespace MonoDevelop.UnitTesting // no need for xml serialization because next time it will be // deserialized from the binary format string binaryFilePath = GetBinaryFilePath (xmlFilePath); - using (var stream = File.OpenWrite(binaryFilePath)) { - fastSerializer.Serialize (stream, testRecord); - } + using var stream = File.OpenWrite (binaryFilePath); + using var writer = new StreamWriter (stream); + + jsonSerializer.Serialize (writer, testRecord); } public TestRecord Deserialize (string xmlFilePath) @@ -83,9 +84,9 @@ namespace MonoDevelop.UnitTesting // deserialize from the binary format if the file exists if (File.Exists(binaryFilePath)) { - using (var stream = File.OpenRead (binaryFilePath)) { - return (TestRecord) fastSerializer.Deserialize (stream); - } + using var stream = File.OpenRead (binaryFilePath); + using var reader = new JsonTextReader (new StreamReader (stream)); + return jsonSerializer.Deserialize<TestRecord> (reader); } // deserialize from xml if the file exists diff --git a/main/src/addins/MonoDevelop.UnitTesting/Services/UnitTest.cs b/main/src/addins/MonoDevelop.UnitTesting/Services/UnitTest.cs index da956f00ae..8a7bcce3bc 100644 --- a/main/src/addins/MonoDevelop.UnitTesting/Services/UnitTest.cs +++ b/main/src/addins/MonoDevelop.UnitTesting/Services/UnitTest.cs @@ -286,7 +286,7 @@ namespace MonoDevelop.UnitTesting // Forces the reloading of tests, if they have changed public virtual Task Refresh (CancellationToken ct) { - return Task.FromResult (0); + return Task.CompletedTask; } public UnitTestResult Run (TestContext testContext) @@ -336,7 +336,7 @@ namespace MonoDevelop.UnitTesting { if (parent != null) return parent.Build (); - return Task.FromResult (true); + return Task.CompletedTask; } public void RegisterResult (TestContext context, UnitTestResult result) diff --git a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Gui/T4EditorExtension.cs b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Gui/T4EditorExtension.cs index 520954efab..611db18a0d 100644 --- a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Gui/T4EditorExtension.cs +++ b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Gui/T4EditorExtension.cs @@ -31,7 +31,6 @@ using MonoDevelop.Ide.Gui.Content; using MonoDevelop.DesignerSupport; using MonoDevelop.TextTemplating.Parser; using MonoDevelop.Ide; -using ICSharpCode.NRefactory.TypeSystem; using MonoDevelop.Ide.Editor.Extension; using MonoDevelop.Ide.Editor; using System.Threading.Tasks; @@ -85,16 +84,6 @@ namespace MonoDevelop.TextTemplating.Gui } } - protected string GetBufferText (DomRegion region) - { - int start = Editor.LocationToOffset (region.BeginLine, region.BeginColumn); - int end = Editor.LocationToOffset (region.EndLine, region.EndColumn); - if (end > start && start >= 0) - return Editor.GetTextBetween (start, end); - else - return null; - } - #endregion #region Code completion diff --git a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/MonoDevelop.TextTemplating.csproj b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/MonoDevelop.TextTemplating.csproj index f4d393e913..93a403d0a0 100644 --- a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/MonoDevelop.TextTemplating.csproj +++ b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/MonoDevelop.TextTemplating.csproj @@ -55,11 +55,6 @@ <Name>MonoDevelop.Ide</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\..\..\..\external\mono-addins\Mono.Addins\Mono.Addins.csproj"> <Project>{91DD5A2D-9FE3-4C3C-9253-876141874DAD}</Project> <Name>Mono.Addins</Name> diff --git a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Parser/T4ParsedDocument.cs b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Parser/T4ParsedDocument.cs index 63d5f95b58..be9322ff9d 100644 --- a/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Parser/T4ParsedDocument.cs +++ b/main/src/addins/TextTemplating/MonoDevelop.TextTemplating/Parser/T4ParsedDocument.cs @@ -28,7 +28,6 @@ using System; using System.Collections.Generic; using Mono.TextTemplating; using MonoDevelop.Ide.TypeSystem; -using ICSharpCode.NRefactory.TypeSystem; using MonoDevelop.Ide.Editor; using System.Linq; diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs index 8737ccfe56..47a4f3b73f 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs @@ -54,7 +54,7 @@ namespace MonoDevelop.VersionControl.Git.Tests // Check out the repository. await CheckoutAsync (LocalPath, RemoteUrl); Repo = GetRepo (LocalPath, RemoteUrl); - await ((GitRepository)Repo).RunOperationAsync (() => ((GitRepository)Repo).RootRepository.Config.Set ("core.ignorecase", false)); + await ((GitRepository)Repo).RunOperationAsync ((token) => ((GitRepository)Repo).RootRepository.Config.Set ("core.ignorecase", false)); ModifyPath (Repo, ref LocalPath); DotDir = ".git"; diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.csproj b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.csproj index 5b156373db..90f82cd76e 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.csproj +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.csproj @@ -97,11 +97,6 @@ <Project>{EE6ED99F-CB12-4683-B055-D28FC7357A34}</Project> <Name>LibGit2Sharp</Name> </ProjectReference> - <ProjectReference Include="..\..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\..\MonoDevelop.SourceEditor2\MonoDevelop.SourceEditor.csproj"> <Project>{F8F92AA4-A376-4679-A9D4-60E7B7FBF477}</Project> <Name>MonoDevelop.SourceEditor</Name> diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Commands.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Commands.cs index 347f442eb8..ca740c6ae6 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Commands.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/Commands.cs @@ -184,11 +184,12 @@ namespace MonoDevelop.VersionControl.Git dlg.Dispose (); } } + protected override async Task UpdateAsync (CommandInfo info, CancellationToken cancelToken) { var repo = UpdateVisibility (info); if (repo != null) - info.Enabled = await repo.RunOperationAsync (repo.RootPath, repository => !repository.Info.IsHeadUnborn, cancelToken); + info.Enabled = await repo.RunOperationAsync (repo.RootPath, (repository, token) => !repository.Info.IsHeadUnborn, cancelToken); } } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitConfigurationDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitConfigurationDialog.cs index 82b833ac52..6cebdbc94d 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitConfigurationDialog.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitConfigurationDialog.cs @@ -421,7 +421,7 @@ namespace MonoDevelop.VersionControl.Git try { monitor.BeginTask (GettextCatalog.GetString ("Pushing Tag"), 1); monitor.Log.WriteLine (GettextCatalog.GetString ("Pushing Tag '{0}' to '{1}'", tagName, repo.Url)); - await repo.PushTagAsync (tagName); + await repo.PushTagAsync (tagName, destroyTokenSource.Token); monitor.Step (1); monitor.EndTask (); } catch (Exception ex) { @@ -449,7 +449,7 @@ namespace MonoDevelop.VersionControl.Git if (string.IsNullOrEmpty(remoteName)) return; - var monitor = VersionControlService.GetProgressMonitor (GettextCatalog.GetString ("Fetching remote...")); + var monitor = VersionControlService.GetProgressMonitor (GettextCatalog.GetString ("Fetching remote...")).WithCancellationSource (destroyTokenSource); try { await repo.FetchAsync (monitor, remoteName); } catch (Exception ex) { diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs index 05db51bee6..04b951cee7 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs @@ -35,6 +35,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using LibGit2Sharp; +using Microsoft.TemplateEngine.Core.Util; using MonoDevelop.Core; using MonoDevelop.Core.Text; using MonoDevelop.Ide; @@ -122,9 +123,9 @@ namespace MonoDevelop.VersionControl.Git Task<LibGit2Sharp.Repository> CreateSafeRepositoryAsync (string path) { - if (Thread.CurrentThread == GitScheduler.DedicatedThread) + //if (Thread.CurrentThread == GitScheduler.DedicatedThread) return Task.FromResult (new LibGit2Sharp.Repository (path)); - return RunOperationAsync (() => new LibGit2Sharp.Repository (path)); + //return RunOperationAsync ((token) => new LibGit2Sharp.Repository (path)); } void InitFileWatcher (bool throwIfIndexMissing = true) @@ -284,46 +285,47 @@ namespace MonoDevelop.VersionControl.Git { FileService.ThawEvents (); } - + object disposeLock = new object (); protected override void Dispose (bool disposing) { - if (IsDisposed) - return; - IsDisposed = true; - - if (disposing) { - ShutdownFileWatcher (); - gitLock?.Dispose (); - if (rootRepository != null) { - DedicatedOperationFactory.StartNew (() => { - try { - rootRepository?.Dispose (); - } catch (Exception e) { - LoggingService.LogInternalError ("Disposing LibGit2Sharp.Repository failed", e); - } - if (cachedSubmodules != null) { - foreach (var submodule in cachedSubmodules) { - if (submodule?.Item2 != null) { + lock (disposeLock) { + if (IsDisposed) + return; + IsDisposed = true; + if (disposing) { + ShutdownFileWatcher (); + gitLock?.Dispose (); + + if (rootRepository != null) { + // disposeTokenSource.Cancel is called so all operations on DedicatedOperationFactory should be canceled + DedicatedOperationFactory.StartNew (() => { + try { + rootRepository?.Dispose (); + } catch (Exception e) { + LoggingService.LogInternalError ("Disposing LibGit2Sharp.Repository failed", e); + } + if (cachedSubmodules != null) { + foreach (var submodule in cachedSubmodules) { try { - submodule?.Item2.Dispose (); + var submoduleRepository = submodule?.Item2; + submoduleRepository?.Dispose (); } catch (Exception e) { LoggingService.LogInternalError ("Disposing LibGit2Sharp.Repository failed", e); } } } - } - }).Wait (); - gitScheduler.Dispose (); + }).Ignore (); + gitScheduler.Dispose (); + } } - } - // now it's safe to dispose the base and release all information caches - // this will also wait for the scheduler to finish all operations and shutdown - base.Dispose (disposing); + // now it's safe to dispose the base and release all information caches + // this will also wait for the scheduler to finish all operations and shutdown + base.Dispose (disposing); - watcher = null; - rootRepository = null; - cachedSubmodules = null; + rootRepository = null; + cachedSubmodules = null; + } } public override string[] SupportedProtocols { @@ -379,7 +381,7 @@ namespace MonoDevelop.VersionControl.Git public override Task<string> GetBaseTextAsync (FilePath localFile, CancellationToken cancellationToken) { - return RunOperationAsync (localFile, repository => { + return RunOperationAsync (localFile, (repository, token) => { var c = GetHeadCommit (repository); return c == null ? string.Empty : GetCommitTextContent (c, localFile, repository); }, cancellationToken: cancellationToken); @@ -387,7 +389,7 @@ namespace MonoDevelop.VersionControl.Git Task<Commit> GetHeadCommitAsync (LibGit2Sharp.Repository repository) { - return RunOperationAsync (() => GetHeadCommit (repository)); + return RunOperationAsync ((token) => GetHeadCommit (repository)); } static Commit GetHeadCommit (LibGit2Sharp.Repository repository) @@ -402,7 +404,7 @@ namespace MonoDevelop.VersionControl.Git public Task<StashCollection> GetStashesAsync (CancellationToken cancellationToken = default) { - return RunOperationAsync (() => RootRepository.Stashes, cancellationToken: cancellationToken); + return RunOperationAsync ((token) => RootRepository.Stashes, cancellationToken: cancellationToken); } const CheckoutNotifyFlags refreshFlags = CheckoutNotifyFlags.Updated | CheckoutNotifyFlags.Conflict | CheckoutNotifyFlags.Untracked | CheckoutNotifyFlags.Dirty; @@ -472,7 +474,7 @@ namespace MonoDevelop.VersionControl.Git public StashApplyStatus ApplyStash (ProgressMonitor monitor, int stashIndex) { - return RunBlockingOperation (() => ApplyStash (RootRepository, monitor, stashIndex), true, monitor.CancellationToken); + return RunBlockingOperation ((token) => ApplyStash (RootRepository, monitor, stashIndex), true, monitor.CancellationToken); } StashApplyStatus ApplyStash (LibGit2Sharp.Repository repository, ProgressMonitor monitor, int stashIndex) @@ -508,7 +510,7 @@ namespace MonoDevelop.VersionControl.Git if (monitor != null) monitor.BeginTask (GettextCatalog.GetString ("Popping stash"), 1); - var res = RunBlockingOperation (() => { + var res = RunBlockingOperation ((token) => { var stash = RootRepository.Stashes [stashIndex]; int progress = 0; return RootRepository.Stashes.Pop (stashIndex, new StashApplyOptions { @@ -536,7 +538,7 @@ namespace MonoDevelop.VersionControl.Git if (monitor != null) monitor.BeginTask (GettextCatalog.GetString ("Stashing changes"), 1); - stash = RunBlockingOperation (() => RootRepository.Stashes.Add (sig, message, StashModifiers.Default | StashModifiers.IncludeUntracked), cancellationToken: monitor.CancellationToken); + stash = RunBlockingOperation ((token) => RootRepository.Stashes.Add (sig, message, StashModifiers.Default | StashModifiers.IncludeUntracked), cancellationToken: monitor.CancellationToken); if (monitor != null) monitor.EndTask (); @@ -602,14 +604,21 @@ namespace MonoDevelop.VersionControl.Git DedicatedOperationFactory.StartNew (action).RunWaitAndCapture (); } - internal Task RunOperationAsync (Action action, CancellationToken cancellationToken = default) + internal Task RunOperationAsync (Action<CancellationToken> action, CancellationToken cancellationToken = default) { EnsureInitialized (); if (IsGitThread) { - action (); + action (cancellationToken); return Task.CompletedTask; } - return DedicatedOperationFactory.StartNew (action, cancellationToken); + var src = LinkTokenToDispose (ref cancellationToken); + return DedicatedOperationFactory.StartNew (() => { + try { + action (cancellationToken); + } finally { + src.Dispose (); + } + }, cancellationToken); } internal T RunOperation<T> (Func<T> action, bool hasUICallbacks = false) @@ -622,133 +631,149 @@ namespace MonoDevelop.VersionControl.Git return DedicatedOperationFactory.StartNew (action).RunWaitAndCapture (); } - internal Task<T> RunOperationAsync<T> (Func<T> action, CancellationToken cancellationToken = default) + internal Task<T> RunOperationAsync<T> (Func<CancellationToken, T> action, CancellationToken cancellationToken = default) { EnsureInitialized (); if (IsGitThread) - return Task.FromResult (action ()); - return DedicatedOperationFactory.StartNew (action, cancellationToken); - } - - internal T RunOperation<T> (FilePath localPath, Func<LibGit2Sharp.Repository, T> action, bool hasUICallbacks = false) - { - EnsureInitialized (); - if (hasUICallbacks) - EnsureBackgroundThread (); - if (IsGitThread) - return action (GetRepository (localPath)); - return DedicatedOperationFactory.StartNew (() => action (GetRepository (localPath))).RunWaitAndCapture (); + return Task.FromResult (action (cancellationToken)); + var src = LinkTokenToDispose (ref cancellationToken); + return DedicatedOperationFactory.StartNew (() => { + try { + return action (cancellationToken); + } finally { + src.Dispose (); + } + }, cancellationToken); } - internal Task<T> RunOperationAsync<T> (FilePath localPath, Func<LibGit2Sharp.Repository, T> action, CancellationToken cancellationToken = default) + internal Task<T> RunOperationAsync<T> (FilePath localPath, Func<LibGit2Sharp.Repository, CancellationToken, T> action, CancellationToken cancellationToken = default) { EnsureInitialized (); if (IsGitThread) - return Task.FromResult (action (GetRepository (localPath))); - return DedicatedOperationFactory.StartNew (() => action (GetRepository (localPath)), cancellationToken); + return Task.FromResult (action (GetRepository (localPath), cancellationToken)); + var src = LinkTokenToDispose (ref cancellationToken); + return DedicatedOperationFactory.StartNew (() => { + try { + return action (GetRepository (localPath), cancellationToken); + } finally { + src.Dispose (); + } + }, cancellationToken); } - internal T RunBlockingOperation<T> (Func<T> action, bool hasUICallbacks = false, CancellationToken cancellationToken = default) + internal T RunBlockingOperation<T> (Func<CancellationToken, T> action, bool hasUICallbacks = false, CancellationToken cancellationToken = default) { EnsureInitialized (); if (hasUICallbacks) EnsureBackgroundThread (); - if (IsGitThread) { return RunBlockingOperationInternal (action, cancellationToken); } - return DedicatedOperationFactory.StartNew (() => RunBlockingOperationInternal (action, cancellationToken)) - .RunWaitAndCapture (); + using (LinkTokenToDispose (ref cancellationToken)) { + return DedicatedOperationFactory.StartNew (() => RunBlockingOperationInternal (action, cancellationToken)) + .RunWaitAndCapture (); + } - T RunBlockingOperationInternal (Func<T> action, CancellationToken cancellationToken) + T RunBlockingOperationInternal (Func<CancellationToken, T> action, CancellationToken cancellationToken) { if (!WaitAndFreezeEvents (cancellationToken)) return default; try { - return action (); + return action (cancellationToken); } finally { ThawEvents (); } } } - internal Task RunBlockingOperationAsync (Action action, CancellationToken cancellationToken = default) + internal Task RunBlockingOperationAsync (Action<CancellationToken> action, CancellationToken cancellationToken = default) { EnsureInitialized (); + if (IsGitThread) { + RunBlockingOperationInternal (action, cancellationToken); + return Task.CompletedTask; + } + + var src = LinkTokenToDispose (ref cancellationToken); + return DedicatedOperationFactory.StartNew (() => { try { RunBlockingOperationInternal (action, cancellationToken); - return Task.CompletedTask; - } catch (OperationCanceledException) { - return Task.FromCanceled (cancellationToken); + } finally { + src.Dispose (); } - } - - return DedicatedOperationFactory.StartNew (() => RunBlockingOperationInternal (action, cancellationToken)); + }); - void RunBlockingOperationInternal (Action action, CancellationToken cancellationToken) + void RunBlockingOperationInternal (Action<CancellationToken> action, CancellationToken cancellationToken) { if (!WaitAndFreezeEvents (cancellationToken)) cancellationToken.ThrowIfCancellationRequested (); try { - action (); + action (cancellationToken); } finally { ThawEvents (); } } } - internal Task RunBlockingOperationAsync (FilePath localPath, Action<LibGit2Sharp.Repository> action, CancellationToken cancellationToken = default) + internal Task RunBlockingOperationAsync (FilePath localPath, Action<LibGit2Sharp.Repository, CancellationToken> action, CancellationToken cancellationToken = default) { EnsureInitialized (); + if (IsGitThread) { + RunBlockingOperationInternal (localPath, action, cancellationToken); + return Task.CompletedTask; + } + + var src = LinkTokenToDispose (ref cancellationToken); + + return DedicatedOperationFactory.StartNew (() => { try { RunBlockingOperationInternal (localPath, action, cancellationToken); - return Task.CompletedTask; - } catch (OperationCanceledException) { - return Task.FromCanceled (cancellationToken); + } finally { + src.Dispose (); } - } - - return DedicatedOperationFactory.StartNew (() => RunBlockingOperationInternal (localPath, action, cancellationToken)); + }); - void RunBlockingOperationInternal (FilePath localPath, Action<LibGit2Sharp.Repository> action, CancellationToken cancellationToken) + void RunBlockingOperationInternal (FilePath localPath, Action<LibGit2Sharp.Repository, CancellationToken> action, CancellationToken cancellationToken) { if (!WaitAndFreezeEvents (cancellationToken)) cancellationToken.ThrowIfCancellationRequested (); try { - action (GetRepository (localPath)); + action (GetRepository (localPath), cancellationToken); } finally { ThawEvents (); } } } - internal Task<T> RunBlockingOperationAsync<T> (Func<T> action, CancellationToken cancellationToken = default) + internal Task<T> RunBlockingOperationAsync<T> (Func<CancellationToken, T> action, CancellationToken cancellationToken = default) { EnsureInitialized (); - if (IsGitThread) { - try { - return Task.FromResult (RunBlockingOperationInternal (action, cancellationToken)); - } catch (OperationCanceledException) { - return Task.FromCanceled<T> (cancellationToken); - } + return Task.FromResult (RunBlockingOperationInternal (action, cancellationToken)); } - return DedicatedOperationFactory.StartNew<T> (() => action (), cancellationToken); - - T RunBlockingOperationInternal (Func<T> action, CancellationToken cancellationToken) + var src = LinkTokenToDispose (ref cancellationToken); + return DedicatedOperationFactory.StartNew<T> (() => { + try { + return action (cancellationToken); + } finally { + src.Dispose (); + } + }, cancellationToken); + + T RunBlockingOperationInternal (Func<CancellationToken, T> action, CancellationToken cancellationToken) { if (!WaitAndFreezeEvents (cancellationToken)) cancellationToken.ThrowIfCancellationRequested (); try { - return action (); + return action (cancellationToken); } finally { ThawEvents (); } @@ -785,7 +810,7 @@ namespace MonoDevelop.VersionControl.Git protected override Task<Revision []> OnGetHistoryAsync (FilePath localFile, Revision since, CancellationToken cancellationToken) { - return RunOperationAsync (() => { + return RunOperationAsync ((token) => { var hc = GetHeadCommit (RootRepository); if (hc == null) return new GitRevision [0]; @@ -831,7 +856,7 @@ namespace MonoDevelop.VersionControl.Git protected override Task<RevisionPath []> OnGetRevisionChangesAsync (Revision revision, CancellationToken cancellationToken = default) { var rev = (GitRevision)revision; - return RunOperationAsync (() => { + return RunOperationAsync ((token) => { var commit = rev.GetCommit (RootRepository); if (commit == null) return new RevisionPath [0]; @@ -841,27 +866,27 @@ namespace MonoDevelop.VersionControl.Git var changes = RootRepository.Diff.Compare<TreeChanges> (parent?.Tree, commit.Tree); foreach (var entry in changes.Added) { - cancellationToken.ThrowIfCancellationRequested (); + token.ThrowIfCancellationRequested (); paths.Add (new RevisionPath (RootRepository.FromGitPath (entry.Path), RevisionAction.Add, null)); } foreach (var entry in changes.Copied) { - cancellationToken.ThrowIfCancellationRequested (); + token.ThrowIfCancellationRequested (); paths.Add (new RevisionPath (RootRepository.FromGitPath (entry.Path), RevisionAction.Add, null)); } foreach (var entry in changes.Deleted) { - cancellationToken.ThrowIfCancellationRequested (); + token.ThrowIfCancellationRequested (); paths.Add (new RevisionPath (RootRepository.FromGitPath (entry.OldPath), RevisionAction.Delete, null)); } foreach (var entry in changes.Renamed) { - cancellationToken.ThrowIfCancellationRequested (); + token.ThrowIfCancellationRequested (); paths.Add (new RevisionPath (RootRepository.FromGitPath (entry.Path), RootRepository.FromGitPath (entry.OldPath), RevisionAction.Replace, null)); } foreach (var entry in changes.Modified) { - cancellationToken.ThrowIfCancellationRequested (); + token.ThrowIfCancellationRequested (); paths.Add (new RevisionPath (RootRepository.FromGitPath (entry.Path), RevisionAction.Modify, null)); } foreach (var entry in changes.TypeChanged) { - cancellationToken.ThrowIfCancellationRequested (); + token.ThrowIfCancellationRequested (); paths.Add (new RevisionPath (RootRepository.FromGitPath (entry.Path), RevisionAction.Modify, null)); } return paths.ToArray (); @@ -960,13 +985,13 @@ namespace MonoDevelop.VersionControl.Git runAsync = true; } - if (runAsync && await RunOperationAsync (() => rev.GetCommit (repository)).ConfigureAwait (false) != headCommit) { + if (runAsync && await RunOperationAsync ((token) => rev.GetCommit (repository)).ConfigureAwait (false) != headCommit) { rev = new GitRevision (this, repositoryRoot, headCommit); versionInfoCacheRevision [repositoryRoot] = rev; } } - await RunOperationAsync (() => GetFilesVersionInfoCore (repository, rev, group.ToList (), versions)).ConfigureAwait (false); + await RunOperationAsync ((token) => GetFilesVersionInfoCore (repository, rev, group.ToList (), versions)).ConfigureAwait (false); } } } else { @@ -1001,7 +1026,7 @@ namespace MonoDevelop.VersionControl.Git } - if (runAsync && await RunOperationAsync (() => arev.GetCommit (rootRepository)).ConfigureAwait (false) != headCommit) { + if (runAsync && await RunOperationAsync ((token) => arev.GetCommit (rootRepository)).ConfigureAwait (false) != headCommit) { arev = new GitRevision (this, RootPath, headCommit); lock (versionInfoCacheRevision) { versionInfoCacheRevision [RootPath] = arev; @@ -1009,7 +1034,7 @@ namespace MonoDevelop.VersionControl.Git } } - await RunOperationAsync (() => GetDirectoryVersionInfoCore (rootRepository, arev, localDirectory.CanonicalPath, versions, recursive)).ConfigureAwait (false); + await RunOperationAsync ((token) => GetDirectoryVersionInfoCore (rootRepository, arev, localDirectory.CanonicalPath, versions, recursive)).ConfigureAwait (false); } return versions.ToArray (); @@ -1239,7 +1264,7 @@ namespace MonoDevelop.VersionControl.Git monitor.Log.WriteLine (GettextCatalog.GetString ("Fetching from '{0}'", remote)); int progress = 0; - var innerTask = await RunBlockingOperationAsync (() => { + var innerTask = await RunBlockingOperationAsync ((token) => { var refSpec = RootRepository.Network.Remotes [remote]?.FetchRefSpecs.Select (spec => spec.Specification); return RetryUntilSuccessAsync (monitor, credType => { LibGit2Sharp.Commands.Fetch (RootRepository, remote, refSpec, new FetchOptions { @@ -1349,7 +1374,7 @@ namespace MonoDevelop.VersionControl.Git if (RootRepository.Index.Conflicts.Any () && !ConflictResolver (RootRepository, monitor, oldHead, string.Empty)) PopStash (monitor, stashIndex); else - await RunBlockingOperationAsync (() => RootRepository.Stashes.Remove (stashIndex), cancellationToken: monitor.CancellationToken).ConfigureAwait (false); + await RunBlockingOperationAsync ((token) => RootRepository.Stashes.Remove (stashIndex), cancellationToken: monitor.CancellationToken).ConfigureAwait (false); monitor.Step (1); } } @@ -1377,7 +1402,7 @@ namespace MonoDevelop.VersionControl.Git stashIndex = newStashIndex; options = newOptions; - await RunBlockingOperationAsync (() => { + await RunBlockingOperationAsync ((token) => { // Do a rebase. var divergence = RootRepository.ObjectDatabase.CalculateHistoryDivergence (RootRepository.Head.Tip, RootRepository.Branches [branch].Tip); @@ -1431,7 +1456,7 @@ namespace MonoDevelop.VersionControl.Git options = newOptions; // Do a merge. - MergeResult mergeResult = await RunBlockingOperationAsync (() => + MergeResult mergeResult = await RunBlockingOperationAsync ((token) => RootRepository.Merge (branch, sig, new MergeOptions { CheckoutNotifyFlags = refreshFlags, OnCheckoutNotify = (string path, CheckoutNotifyFlags flags) => RefreshFile (path, flags), @@ -1485,7 +1510,7 @@ namespace MonoDevelop.VersionControl.Git var repo = (GitRepository)changeSet.Repository; var addedFiles = await GetAddedLocalPathItems (changeSet, monitor.CancellationToken).ConfigureAwait (false); - await RunBlockingOperationAsync (() => { + await RunBlockingOperationAsync ((token) => { try { // Unstage added files not included in the changeSet if (addedFiles.Any ()) @@ -1596,7 +1621,7 @@ namespace MonoDevelop.VersionControl.Git try { monitor.BeginTask (GettextCatalog.GetString ("Cloning…"), 2); bool skipSubmodules = false; - var innerTask = await RunOperationAsync (() => RetryUntilSuccessAsync (monitor, credType => { + var innerTask = await RunOperationAsync ((token) => RetryUntilSuccessAsync (monitor, credType => { var options = new CloneOptions { CredentialsProvider = (url, userFromUrl, types) => { transferProgress = checkoutProgress = 0; @@ -1728,7 +1753,7 @@ namespace MonoDevelop.VersionControl.Git monitor.BeginTask (GettextCatalog.GetString ("Reverting files"), 1); - await RunBlockingOperationAsync (group.Key, repository => { + await RunBlockingOperationAsync (group.Key, (repository, token) => { var repoFiles = repository.ToGitPath (toCheckout); int progress = 0; if (toCheckout.Any ()) { @@ -1767,7 +1792,7 @@ namespace MonoDevelop.VersionControl.Git foreach (var group in GroupByRepository (localPaths)) { var files = group.Where (f => !f.IsDirectory); if (files.Any ()) - await RunBlockingOperationAsync (() => LibGit2Sharp.Commands.Stage (group.Key, group.Key.ToGitPath (files)), monitor.CancellationToken).ConfigureAwait (false); + await RunBlockingOperationAsync ((token) => LibGit2Sharp.Commands.Stage (group.Key, group.Key.ToGitPath (files)), monitor.CancellationToken).ConfigureAwait (false); } } @@ -1793,7 +1818,7 @@ namespace MonoDevelop.VersionControl.Git protected override async Task OnDeleteDirectoriesAsync (FilePath[] localPaths, bool force, ProgressMonitor monitor, bool keepLocal) { - await DeleteCore (localPaths, keepLocal, monitor).ConfigureAwait (false); + await DeleteCore (localPaths, keepLocal, monitor).ConfigureAwait (false); foreach (var path in localPaths) { if (keepLocal) { @@ -1831,7 +1856,7 @@ namespace MonoDevelop.VersionControl.Git } } - await RunBlockingOperationAsync (() => { + await RunBlockingOperationAsync ((token) => { var files = group.Key.ToGitPath (group); LibGit2Sharp.Commands.Remove (group.Key, files, !keepLocal, null); }, monitor.CancellationToken).ConfigureAwait (false); @@ -1841,12 +1866,12 @@ namespace MonoDevelop.VersionControl.Git protected override Task<string> OnGetTextAtRevisionAsync (FilePath repositoryPath, Revision revision, CancellationToken cancellationToken) { var gitRev = (GitRevision)revision; - return RunOperationAsync (repositoryPath, repository => GetCommitTextContent (gitRev.GetCommit (repository), repositoryPath, repository)); + return RunOperationAsync (repositoryPath, (repository, token) => GetCommitTextContent (gitRev.GetCommit (repository), repositoryPath, repository)); } public override Task<DiffInfo> GenerateDiffAsync (FilePath baseLocalPath, VersionInfo versionInfo) { - return RunOperationAsync (versionInfo.LocalPath, repository => { + return RunOperationAsync (versionInfo.LocalPath, (repository, token) => { try { var patch = repository.Diff.Compare<Patch> (repository.Head?.Tip?.Tree, DiffTargets.WorkingDirectory | DiffTargets.Index, new [] { repository.ToGitPath (versionInfo.LocalPath) }); // Trim the header by taking out the first 2 lines. @@ -1889,7 +1914,7 @@ namespace MonoDevelop.VersionControl.Git public async Task<string> GetCurrentRemoteAsync (CancellationToken cancellationToken = default) { using (LinkTokenToDispose (ref cancellationToken)) { - var headRemote = await RunOperationAsync (() => RootRepository.Head?.RemoteName).ConfigureAwait (false); + var headRemote = await RunOperationAsync ((token) => RootRepository.Head?.RemoteName).ConfigureAwait (false); if (!string.IsNullOrEmpty (headRemote)) return headRemote; @@ -1905,14 +1930,14 @@ namespace MonoDevelop.VersionControl.Git { bool success = true; - await RunOperationAsync (() => { + await RunOperationAsync ((token) => { var branch = RootRepository.Head; if (branch.TrackedBranch == null) { RootRepository.Branches.Update (branch, b => b.TrackedBranch = "refs/remotes/" + remote + "/" + remoteBranch); } }, monitor.CancellationToken).ConfigureAwait (false); - var innerTask = await RunOperationAsync (() => { + var innerTask = await RunOperationAsync ((token) => { return RetryUntilSuccessAsync (monitor, credType => { RootRepository.Network.Push (RootRepository.Network.Remotes [remote], "refs/heads/" + remoteBranch, new PushOptions { OnPushStatusError = pushStatusErrors => success = false, @@ -1932,12 +1957,12 @@ namespace MonoDevelop.VersionControl.Git public Task CreateBranchFromCommitAsync (string name, Commit id) { - return RunBlockingOperationAsync (() => RootRepository.CreateBranch (name, id)); + return RunBlockingOperationAsync ((token) => RootRepository.CreateBranch (name, id)); } public Task CreateBranchAsync (string name, string trackSource, string targetRef) { - return RunBlockingOperationAsync (() => CreateBranch (name, trackSource, targetRef, RootRepository)); + return RunBlockingOperationAsync ((token) => CreateBranch (name, trackSource, targetRef, RootRepository)); } void CreateBranch (string name, string trackSource, string targetRef, LibGit2Sharp.Repository repo) @@ -1953,7 +1978,7 @@ namespace MonoDevelop.VersionControl.Git public Task SetBranchTrackRefAsync (string name, string trackSource, string trackRef) { - return RunBlockingOperationAsync (() => { + return RunBlockingOperationAsync ((token) => { var branch = RootRepository.Branches [name]; if (branch != null) { RootRepository.Branches.Update (branch, bu => bu.TrackedBranch = trackRef); @@ -1964,30 +1989,30 @@ namespace MonoDevelop.VersionControl.Git public Task RemoveBranchAsync (string name) { - return RunBlockingOperationAsync (() => RootRepository.Branches.Remove (name)); + return RunBlockingOperationAsync ((token) => RootRepository.Branches.Remove (name)); } public Task RenameBranchAsync (string name, string newName) { - return RunBlockingOperationAsync (() => RootRepository.Branches.Rename (name, newName, true)); + return RunBlockingOperationAsync ((token) => RootRepository.Branches.Rename (name, newName, true)); } public Task<List<string>> GetRemoteNamesAsync (CancellationToken cancellationToken = default) { // TODO: access to Remote props is not under our control - return RunOperationAsync (() => RootRepository.Network.Remotes.Select (r => r.Name).ToList (), cancellationToken: cancellationToken); + return RunOperationAsync ((token) => RootRepository.Network.Remotes.Select (r => r.Name).ToList (), cancellationToken: cancellationToken); } public Task<IEnumerable<Remote>> GetRemotesAsync (CancellationToken cancellationToken = default) { // TODO: access to Remote props is not under our control - return RunOperationAsync (() => RootRepository.Network.Remotes.Cast<Remote> (), cancellationToken:cancellationToken); + return RunOperationAsync ((token) => RootRepository.Network.Remotes.Cast<Remote> (), cancellationToken:cancellationToken); } public Task<bool> IsBranchMergedAsync (string branchName) { // check if a branch is merged into HEAD - return RunOperationAsync (() => { + return RunOperationAsync ((token) => { var tip = RootRepository.Branches [branchName].Tip.Sha; return RootRepository.Commits.Any (c => c.Sha == tip); }); @@ -1995,12 +2020,12 @@ namespace MonoDevelop.VersionControl.Git public Task RenameRemoteAsync (string name, string newName) { - return RunBlockingOperationAsync (() => RootRepository.Network.Remotes.Rename (name, newName)); + return RunBlockingOperationAsync ((token) => RootRepository.Network.Remotes.Rename (name, newName)); } public Task ChangeRemoteUrlAsync (string name, string url) { - return RunBlockingOperationAsync (() => + return RunBlockingOperationAsync ((token) => RootRepository.Network.Remotes.Update ( name, r => r.Url = url @@ -2009,7 +2034,7 @@ namespace MonoDevelop.VersionControl.Git public Task ChangeRemotePushUrlAsync (string name, string url) { - return RunBlockingOperationAsync (() => + return RunBlockingOperationAsync ((token) => RootRepository.Network.Remotes.Update ( name, r => r.PushUrl = url @@ -2021,31 +2046,31 @@ namespace MonoDevelop.VersionControl.Git if (string.IsNullOrEmpty (name)) throw new InvalidOperationException ("Name not set"); - return RunBlockingOperationAsync (() => + return RunBlockingOperationAsync ((token) => RootRepository.Network.Remotes.Update (RootRepository.Network.Remotes.Add (name, url).Name, r => r.TagFetchMode = importTags ? TagFetchMode.All : TagFetchMode.Auto)); } public Task RemoveRemoteAsync (string name) { - return RunBlockingOperationAsync (() => RootRepository.Network.Remotes.Remove (name)); + return RunBlockingOperationAsync ((token) => RootRepository.Network.Remotes.Remove (name)); } public Task<List<string>> GetLocalBranchNamesAsync (CancellationToken cancellationToken = default) { // TODO: access to Remote props is not under our control - return RunOperationAsync (() => RootRepository.Branches.Where (b => !b.IsRemote).Select (b => b.FriendlyName).ToList (), cancellationToken: cancellationToken); + return RunOperationAsync ((token) => RootRepository.Branches.Where (b => !b.IsRemote).Select (b => b.FriendlyName).ToList (), cancellationToken: cancellationToken); } public Task<List<Branch>> GetBranchesAsync (CancellationToken cancellationToken = default) { // TODO: access to Remote props is not under our control - return RunOperationAsync (() => RootRepository.Branches.Where (b => !b.IsRemote).ToList (), cancellationToken: cancellationToken); + return RunOperationAsync ((token) => RootRepository.Branches.Where (b => !b.IsRemote).ToList (), cancellationToken: cancellationToken); } public Task<List<string>> GetTagsAsync (CancellationToken cancellationToken = default) { - return RunOperationAsync (() => RootRepository.Tags.Select (t => t.FriendlyName).ToList (), cancellationToken: cancellationToken); + return RunOperationAsync ((token) => RootRepository.Tags.Select (t => t.FriendlyName).ToList (), cancellationToken: cancellationToken); } public Task AddTagAsync (string name, Revision rev, string message, CancellationToken cancellationToken = default) @@ -2055,17 +2080,17 @@ namespace MonoDevelop.VersionControl.Git return Task.CompletedTask; var gitRev = (GitRevision)rev; - return RunBlockingOperationAsync (() => RootRepository.Tags.Add (name, gitRev.GetCommit (RootRepository), sig, message), cancellationToken: cancellationToken); + return RunBlockingOperationAsync ((token) => RootRepository.Tags.Add (name, gitRev.GetCommit (RootRepository), sig, message), cancellationToken: cancellationToken); } public Task RemoveTagAsync (string name, CancellationToken cancellationToken = default) { - return RunBlockingOperationAsync (() => RootRepository.Tags.Remove (name), cancellationToken: cancellationToken); + return RunBlockingOperationAsync ((token) => RootRepository.Tags.Remove (name), cancellationToken: cancellationToken); } public Task PushTagAsync (string name, CancellationToken cancellationToken = default) { - return RunOperationAsync (() => { + return RunOperationAsync ((token) => { return RetryUntilSuccessAsync (null, async credType => RootRepository.Network.Push (RootRepository.Network.Remotes [await GetCurrentRemoteAsync ().ConfigureAwait (false)], "refs/tags/" + name + ":refs/tags/" + name, new PushOptions { CredentialsProvider = (url, userFromUrl, types) => GitCredentials.TryGet (url, userFromUrl, types, credType), })); @@ -2074,14 +2099,14 @@ namespace MonoDevelop.VersionControl.Git public Task<List<string>> GetRemoteBranchesAsync (string remoteName, CancellationToken cancellationToken = default) { - return RunOperationAsync (() => RootRepository.Branches + return RunOperationAsync ((token) => RootRepository.Branches .Where (b => b.IsRemote && b.RemoteName == remoteName) .Select (b => b.FriendlyName.Substring (b.FriendlyName.IndexOf ('/') + 1)).ToList (), cancellationToken: cancellationToken); } public Task<List<string>> GetRemoteBranchFullNamesAsync (CancellationToken cancellationToken = default) { - return RunOperationAsync (() => RootRepository.Branches + return RunOperationAsync ((token) => RootRepository.Branches .Where (b => b.IsRemote).Select (b => b.FriendlyName).OrderBy (n => n).ToList (), cancellationToken: cancellationToken); } @@ -2096,13 +2121,13 @@ namespace MonoDevelop.VersionControl.Git public Task<string> GetCurrentBranchAsync (CancellationToken cancellationToken = default) { - return RunOperationAsync (() => CachedCurrentBranch = RootRepository.Head.FriendlyName, cancellationToken: cancellationToken); + return RunOperationAsync ((token) => CachedCurrentBranch = RootRepository.Head.FriendlyName, cancellationToken: cancellationToken); } async Task SwitchBranchInternalAsync (ProgressMonitor monitor, string branch) { int progress = 0; - await RunOperationAsync (() => LibGit2Sharp.Commands.Checkout (RootRepository, branch, new CheckoutOptions { + await RunOperationAsync ((token) => LibGit2Sharp.Commands.Checkout (RootRepository, branch, new CheckoutOptions { OnCheckoutProgress = (path, completedSteps, totalSteps) => OnCheckoutProgress (completedSteps, totalSteps, monitor, ref progress), OnCheckoutNotify = (string path, CheckoutNotifyFlags flags) => RefreshFile (path, flags), CheckoutNotifyFlags = refreshFlags, @@ -2158,9 +2183,9 @@ namespace MonoDevelop.VersionControl.Git // Remove the stash for this branch, if exists // TODO: why do with do this? string currentBranch = RootRepository.Head.FriendlyName; - stashIndex = RunOperation (() => GetStashForBranch (RootRepository.Stashes, currentBranch)); + stashIndex = await RunBlockingOperationAsync ((token) => GetStashForBranch (RootRepository.Stashes, currentBranch), cancellationToken: monitor.CancellationToken); if (stashIndex != -1) - await RunBlockingOperationAsync (() => RootRepository.Stashes.Remove (stashIndex), cancellationToken: monitor.CancellationToken).ConfigureAwait (false); + await RunBlockingOperationAsync ((token) => RootRepository.Stashes.Remove (stashIndex), cancellationToken: monitor.CancellationToken).ConfigureAwait (false); if (!TryCreateStash (monitor, GetStashName (currentBranch), out stash)) return false; @@ -2275,7 +2300,7 @@ namespace MonoDevelop.VersionControl.Git var dstRepo = GetRepository (localDestPath); vi = await GetVersionInfoAsync (localDestPath, VersionInfoQueryFlags.IgnoreCache, monitor.CancellationToken).ConfigureAwait (false); - await RunBlockingOperationAsync (() => { + await RunBlockingOperationAsync ((token) => { if (vi != null && ((vi.Status & (VersionStatus.ScheduledDelete | VersionStatus.ScheduledReplace)) != VersionStatus.Unversioned)) LibGit2Sharp.Commands.Unstage (dstRepo, localDestPath); @@ -2309,7 +2334,7 @@ namespace MonoDevelop.VersionControl.Git public override Task<Annotation []> GetAnnotationsAsync (FilePath repositoryPath, Revision since, CancellationToken cancellationToken) { - return RunOperationAsync (repositoryPath, async repository => { + return RunOperationAsync (repositoryPath, async (repository, token) => { Commit hc = GetHeadCommit (repository); Commit sinceCommit = since != null ? ((GitRevision)since).GetCommit (repository) : null; if (hc == null) @@ -2332,7 +2357,7 @@ namespace MonoDevelop.VersionControl.Git } if (sinceCommit == null) { - var baseText = await GetBaseTextAsync (repositoryPath, cancellationToken).ConfigureAwait (false); + var baseText = await GetBaseTextAsync (repositoryPath, token).ConfigureAwait (false); await Runtime.RunInMainThread (delegate { var baseDocument = Mono.TextEditor.TextDocument.CreateImmutableDocument (baseText); var workingDocument = Mono.TextEditor.TextDocument.CreateImmutableDocument (TextFileUtility.GetText (repositoryPath)); @@ -2353,7 +2378,7 @@ namespace MonoDevelop.VersionControl.Git } return list.ToArray (); - }).Unwrap (); + }, cancellationToken).Unwrap (); } protected override async Task OnIgnoreAsync (FilePath[] localPath, CancellationToken cancellationToken) @@ -2370,7 +2395,7 @@ namespace MonoDevelop.VersionControl.Git } var sb = StringBuilderCache.Allocate (); - await RunBlockingOperationAsync (() => { + await RunBlockingOperationAsync ((token) => { foreach (var path in localPath.Except (ignored)) sb.AppendLine (RootRepository.ToGitPath (path)); @@ -2393,7 +2418,7 @@ namespace MonoDevelop.VersionControl.Git } var sb = new StringBuilder (); - await RunBlockingOperationAsync (() => { + await RunBlockingOperationAsync ((token) => { foreach (var path in ignored.Except (RootRepository.ToGitPath (localPath))) sb.AppendLine (path); @@ -2449,7 +2474,7 @@ namespace MonoDevelop.VersionControl.Git public override Task<Revision> GetPreviousAsync (CancellationToken cancellationToken) { var repo = (GitRepository)Repository; - return repo.RunOperationAsync (GitRepository, repository => GetPrevious (repository), cancellationToken: cancellationToken); + return repo.RunOperationAsync (GitRepository, (repository, token) => GetPrevious (repository), cancellationToken: cancellationToken); } internal Revision GetPrevious (LibGit2Sharp.Repository repository) diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion.csproj b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion.csproj index a5af64d19d..4e7abfcd91 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion.csproj +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion.csproj @@ -27,11 +27,6 @@ <Name>MonoDevelop.Ide</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\..\..\..\external\mono-addins\Mono.Addins\Mono.Addins.csproj"> <Project>{91DD5A2D-9FE3-4C3C-9253-876141874DAD}</Project> <Name>Mono.Addins</Name> diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/ComparisonWidget.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/ComparisonWidget.cs index dad45ed698..9e5247472b 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/ComparisonWidget.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/ComparisonWidget.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using Mono.TextEditor; using MonoDevelop.Ide; using MonoDevelop.Components; +using MonoDevelop.Components.AtkCocoaHelper; using System.ComponentModel; using MonoDevelop.Core; using MonoDevelop.Ide.Gui; @@ -87,6 +88,12 @@ namespace MonoDevelop.VersionControl.Views new MonoTextEditor (new TextDocument (), options), new MonoTextEditor (new TextDocument (), options), }; + editors [0].Accessible.SetShouldIgnore (false); + editors [0].Accessible.SetRole (AtkCocoa.Roles.AXGroup); + editors [0].Accessible.SetTitle (GettextCatalog.GetString ("Comparing Revision Editor")); + editors [1].Accessible.SetShouldIgnore (false); + editors [1].Accessible.SetRole (AtkCocoa.Roles.AXGroup); + editors [1].Accessible.SetTitle (GettextCatalog.GetString ("Original Revision Editor")); if (!viewOnly) { revisionStore = new ListStore (typeof(Revision), typeof (string), typeof (string), typeof (string)); @@ -109,7 +116,8 @@ namespace MonoDevelop.VersionControl.Views originalComboBox.PackStart (authorRenderer, true); originalComboBox.AddAttribute (authorRenderer, "text", 3); - // originalComboBox.AccessibilityTextFormat = GettextCatalog.GetString ("Select original revision, current: {0}"); + originalComboBox.Accessible.SetTitle (GettextCatalog.GetString ("Original Revision")); + originalComboBox.Active = 0; originalComboBox.Sensitive = false; @@ -122,7 +130,8 @@ namespace MonoDevelop.VersionControl.Views diffComboBox.PackStart (authorRenderer, true); diffComboBox.AddAttribute (authorRenderer, "text", 3); - // diffComboBox.AccessibilityTextFormat = GettextCatalog.GetString ("Select diff revision, current: {0}"); + diffComboBox.Accessible.SetTitle (GettextCatalog.GetString ("Compared Revision")); + diffComboBox.Active = 0; diffComboBox.Sensitive = false; this.headerWidgets = new [] { diffComboBox, originalComboBox }; diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/DiffParser.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/DiffParser.cs index 715d6f4e26..bf10db70d4 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/DiffParser.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/DiffParser.cs @@ -29,8 +29,6 @@ using System.IO; using System.Text.RegularExpressions; using MonoDevelop.Ide.TypeSystem; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.TypeSystem.Implementation; using MonoDevelop.Projects; using MonoDevelop.Core.Text; @@ -55,62 +53,6 @@ namespace MonoDevelop.VersionControl.Views public override System.Threading.Tasks.Task<ParsedDocument> Parse (ParseOptions parseOptions, System.Threading.CancellationToken cancellationToken) { ParsedDocument doc = new DefaultParsedDocument (parseOptions.FileName); - - DefaultUnresolvedTypeDefinition currentFile = null; - DefaultUnresolvedProperty currentRegion = null; - - string eol = Environment.NewLine; - string content = parseOptions.Content.Text; - Match eolMatch = eolExpression.Match (content); - if (eolMatch != null && eolMatch.Success) - eol = eolMatch.Groups ["eol"].Value; - - string[] lines = content.Split (new string[]{eol}, StringSplitOptions.None); - int linenum = 1; - Match lineMatch; - foreach (string line in lines) { - lineMatch = fileHeaderExpression.Match (line.Trim ()); - if (lineMatch != null && lineMatch.Success) { - if (currentFile != null) // Close out previous file region - currentFile.BodyRegion = new DomRegion (currentFile.BodyRegion.BeginLine, - currentFile.BodyRegion.BeginColumn, - linenum - 1, int.MaxValue); - if (currentRegion != null) // Close out previous chunk region - currentRegion.BodyRegion = new DomRegion (currentRegion.BodyRegion.BeginLine, - currentRegion.BodyRegion.BeginColumn, - linenum - 1, int.MaxValue); - - // Create new file region - currentFile = new DefaultUnresolvedTypeDefinition (string.Empty, string.Empty); - currentFile.Region = currentFile.BodyRegion = new DomRegion (lastToken (lineMatch.Groups ["filepath"].Value), linenum, line.Length + 1, linenum, int.MaxValue); - // doc.TopLevelTypeDefinitions.Add (currentFile); - } else { - lineMatch = chunkExpression.Match (line); - if (lineMatch != null && lineMatch.Success && currentFile != null) { - if (currentRegion != null) // Close out previous chunk region - currentRegion.BodyRegion = new DomRegion (currentRegion.BodyRegion.BeginLine, - currentRegion.BodyRegion.BeginColumn, - linenum - 1, int.MaxValue); - - // Create new chunk region - currentRegion = new DefaultUnresolvedProperty (currentFile, lineMatch.Groups ["chunk"].Value); - currentRegion.Region = currentRegion.BodyRegion = new DomRegion (currentFile.Region.FileName, linenum, line.Length + 1, linenum, int.MaxValue); - currentFile.Members.Add (currentRegion); - } - } - ++linenum; - } - - // Close out trailing regions - if (currentFile != null) - currentFile.BodyRegion = new DomRegion (currentFile.BodyRegion.BeginLine, - currentFile.BodyRegion.BeginColumn, - Math.Max (1, linenum - 2), int.MaxValue); - if (currentRegion != null) - currentRegion.BodyRegion = new DomRegion (currentRegion.BodyRegion.BeginLine, - currentRegion.BodyRegion.BeginColumn, - Math.Max (1, linenum - 2), int.MaxValue); - return System.Threading.Tasks.Task.FromResult (doc); } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/EditorCompareWidgetBase.MiddleArea.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/EditorCompareWidgetBase.MiddleArea.cs index 7362d853ec..6c0ec76084 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/EditorCompareWidgetBase.MiddleArea.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/EditorCompareWidgetBase.MiddleArea.cs @@ -480,14 +480,13 @@ namespace MonoDevelop.VersionControl.Views Accessible.PerformPress += PerformPress; Accessible.SetRole (AtkCocoa.Roles.AXButton); - Accessible.Label = widget.useLeft ? GettextCatalog.GetString ("Revert left changes button") : GettextCatalog.GetString ("Revert right changes button"); if (hunk.Inserted > 0) { - Accessible.Label = GettextCatalog.GetString ("Revert {0} inserted lines starting at {1}", hunk.Inserted, hunk.InsertStart); + Accessible.Label = GettextCatalog.GetPluralString ("Revert {0} inserted line starting at {1}", "Revert {0} inserted lines starting at {1}", hunk.Inserted, hunk.Inserted, hunk.InsertStart); } else if (hunk.Removed > 0) { - Accessible.Label = GettextCatalog.GetString ("Revert {0} removed lines starting at {1}", hunk.Removed, hunk.RemoveStart); + Accessible.Label = GettextCatalog.GetPluralString ("Revert {0} removed line starting at {1}", "Revert {0} removed lines starting at {1}", hunk.Removed, hunk.Removed, hunk.RemoveStart); } else { - Accessible.Label = GettextCatalog.GetString ("Revert {0} replaced lines starting at {1}", hunk.Removed, hunk.InsertStart); + Accessible.Label = GettextCatalog.GetPluralString ("Revert {0} replaced line starting at {1}", "Revert {0} replaced lines starting at {1}", hunk.Removed, hunk.Removed, hunk.InsertStart); } } diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/StatusView.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/StatusView.cs index efdbfd9b2f..bdf60945f5 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/StatusView.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/StatusView.cs @@ -459,7 +459,7 @@ namespace MonoDevelop.VersionControl.Views } CancellationTokenSource cancelUpdate = new CancellationTokenSource (); - Task updateTask = Task.FromResult (true); + Task updateTask = Task.CompletedTask; async Task RunUpdate (CancellationToken cancel) { diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.csproj b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.csproj index 9d63654140..c7e6f72840 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.csproj +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.csproj @@ -37,11 +37,6 @@ <Name>MonoDevelop.Debugger</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\..\..\..\external\mono-addins\Mono.Addins\Mono.Addins.csproj"> <Project>{91DD5A2D-9FE3-4C3C-9253-876141874DAD}</Project> <Name>Mono.Addins</Name> diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessHostController.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessHostController.cs index 536d9c3dd4..5b6df84f51 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessHostController.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessHostController.cs @@ -131,7 +131,7 @@ namespace MonoDevelop.Core.Execution cmd.DebugMode = isDebugMode; OperationConsole cons = console ?? new ProcessHostConsole (); var p = process = executionHandlerFactory.Execute (cmd, cons); - Counters.ExternalHostProcesses++; + Counters.ExternalHostProcesses.Inc (1); process.Task.ContinueWith ((t) => ProcessExited (p)); @@ -159,8 +159,8 @@ namespace MonoDevelop.Core.Execution { lock (this) { - Counters.ExternalHostProcesses--; - + Counters.ExternalHostProcesses.Dec (1); + // Remove all callbacks from existing objects foreach (object ob in remoteObjects) RemotingService.UnregisterMethodCallback (ob, "Dispose"); @@ -204,7 +204,7 @@ namespace MonoDevelop.Core.Execution RemotingService.RegisterMethodCallback (obj, "Dispose", RemoteProcessObjectDisposing, null); RemotingService.RegisterMethodCallback (obj, "Shutdown", RemoteProcessObjectShuttingDown, null); remoteObjects.Add (obj); - Counters.ExternalObjects++; + Counters.ExternalObjects.Inc (1); return obj; } catch { ReleaseInstance (null); @@ -234,7 +234,7 @@ namespace MonoDevelop.Core.Execution RemotingService.RegisterMethodCallback (obj, "Dispose", RemoteProcessObjectDisposing, null); RemotingService.RegisterMethodCallback (obj, "Shutdown", RemoteProcessObjectShuttingDown, null); remoteObjects.Add (obj); - Counters.ExternalObjects++; + Counters.ExternalObjects.Inc (1); return obj; } catch { ReleaseInstance (null); @@ -272,7 +272,7 @@ namespace MonoDevelop.Core.Execution public void ReleaseInstance (object proc, int shutdownTimeout) { - Counters.ExternalObjects--; + Counters.ExternalObjects.Dec (1); if (processHost == null) return; diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessService.cs index ca6db5972a..6e39a2368d 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessService.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessService.cs @@ -156,7 +156,7 @@ namespace MonoDevelop.Core.Execution // p.Exited += exited; // p.EnableRaisingEvents = true; - Counters.ProcessesStarted++; + Counters.ProcessesStarted.Inc (1); p.Start (); if (exited != null) @@ -212,7 +212,7 @@ namespace MonoDevelop.Core.Execution if (p != null) { if (exited != null) p.Task.ContinueWith (t => exited (p, EventArgs.Empty), Runtime.MainTaskScheduler); - Counters.ProcessesStarted++; + Counters.ProcessesStarted.Inc (1); return p; } else { LoggingService.LogError ("Could not create external console for command: " + command + " " + arguments); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessWrapper.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessWrapper.cs index f6d15c43bf..635c056507 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessWrapper.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessWrapper.cs @@ -44,11 +44,11 @@ namespace MonoDevelop.Core.Execution // We need these wrappers, as the alternatives are not good enough. // OutputDataReceived does not persist newlines. if (OutputStreamChanged != null) { - Task.Run (CaptureOutput, cs.Token); + Task.Run (CaptureOutput, cs.Token).Ignore (); } if (ErrorStreamChanged != null) { - Task.Run (CaptureError, cs.Token); + Task.Run (CaptureError, cs.Token).Ignore (); } operation = new ProcessAsyncOperation (Task, cs) { diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FileService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FileService.cs index 4158d36ccf..4aca642c0a 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FileService.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FileService.cs @@ -805,9 +805,9 @@ namespace MonoDevelop.Core { foreach (FileEventInfo fi in args) { if (fi.IsDirectory) - Counters.DirectoriesCreated++; + Counters.DirectoriesCreated.Inc (1); else - Counters.FilesCreated++; + Counters.FilesCreated.Inc (1); } eventQueue.RaiseEvent (EventDataKind.Created, args); @@ -830,9 +830,9 @@ namespace MonoDevelop.Core { foreach (FileEventInfo fi in args) { if (fi.IsDirectory) - Counters.DirectoriesRenamed++; + Counters.DirectoriesRenamed.Inc (1); else - Counters.FilesRenamed++; + Counters.FilesRenamed.Inc (1); } eventQueue.RaiseEvent (EventDataKind.Renamed, args); @@ -843,9 +843,9 @@ namespace MonoDevelop.Core { foreach (FileEventInfo fi in args) { if (fi.IsDirectory) - Counters.DirectoriesRemoved++; + Counters.DirectoriesRemoved.Inc (1); else - Counters.FilesRemoved++; + Counters.FilesRemoved.Inc (1); } eventQueue.RaiseEvent (EventDataKind.Removed, args); @@ -854,7 +854,7 @@ namespace MonoDevelop.Core public static event EventHandler<FileEventArgs> FileChanged; static void OnFileChanged (FileEventArgs args) { - Counters.FileChangeNotifications++; + Counters.FileChangeNotifications.Inc (1); eventQueue.RaiseEvent (EventDataKind.Changed, args); } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/IProgressMonitor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/IProgressMonitor.cs index 8f728d8422..b1a4aa1853 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/IProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/IProgressMonitor.cs @@ -44,11 +44,11 @@ namespace MonoDevelop.Core public class AsyncOperation { - public static AsyncOperation CompleteOperation = new AsyncOperation (Task.FromResult(0), null); + public static AsyncOperation CompleteOperation = new AsyncOperation (Task.CompletedTask, null); protected AsyncOperation () { - Task = Task.FromResult (0); + Task = Task.CompletedTask; CancellationTokenSource = new CancellationTokenSource (); } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CompiledAssemblyProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CompiledAssemblyProject.cs index 4bb348eddc..e506fd1cd4 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CompiledAssemblyProject.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CompiledAssemblyProject.cs @@ -201,7 +201,7 @@ namespace MonoDevelop.Projects internal protected override Task OnSave (ProgressMonitor monitor) { // Compiled assemblies can't be saved - return Task.FromResult (0); + return Task.CompletedTask; } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ConditionedPropertyCollection.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ConditionedPropertyCollection.cs index ec1c010046..bd43f395e7 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ConditionedPropertyCollection.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ConditionedPropertyCollection.cs @@ -33,8 +33,8 @@ namespace MonoDevelop.Projects { public class ConditionedPropertyCollection { - Dictionary<string, ImmutableList<string>> props = new Dictionary<string, ImmutableList<string>> (); - Dictionary<KeySet, ImmutableList<ValueSet>> combinedProps = new Dictionary<KeySet, ImmutableList<ValueSet>> (StructEqualityComparer<KeySet>.Instance); + Dictionary<string, ImmutableArray<string>> props = new Dictionary<string, ImmutableArray<string>> (); + Dictionary<KeySet, ImmutableArray<ValueSet>> combinedProps = new Dictionary<KeySet, ImmutableArray<ValueSet>> (StructEqualityComparer<KeySet>.Instance); /// <summary> /// A set of strings, which can be compared to other sets ignoring the order. @@ -178,14 +178,14 @@ namespace MonoDevelop.Projects foreach (var e in other.props) { var otherList = e.Value; var key = e.Key; - ImmutableList<string> list; + ImmutableArray<string> list; if (props.TryGetValue (key, out list)) { var lb = list.ToBuilder (); foreach (var c in otherList) { if (!lb.Contains (c)) lb.Add (c); } - props [key] = lb.ToImmutableList (); + props [key] = lb.ToImmutable (); } else props [key] = otherList; } @@ -193,7 +193,7 @@ namespace MonoDevelop.Projects foreach (var e in other.combinedProps) { var otherList = e.Value; var key = e.Key; - ImmutableList<ValueSet> thisList; + ImmutableArray<ValueSet> thisList; if (combinedProps.TryGetValue (key, out thisList)) { var list = thisList.ToBuilder (); foreach (var c in otherList) { @@ -210,13 +210,13 @@ namespace MonoDevelop.Projects internal void AddPropertyValues (IList<string> names, IList<string> values) { var key = new KeySet (names); - ImmutableList<ValueSet> list; + ImmutableArray<ValueSet> list; ValueSet valueSet; // First register the combination of values if (!combinedProps.TryGetValue (key, out list)) { - list = ImmutableList<ValueSet>.Empty; + list = ImmutableArray<ValueSet>.Empty; valueSet = new ValueSet (names, names, values); } else { // If there is already a list, there must be at least one item. @@ -229,12 +229,12 @@ namespace MonoDevelop.Projects // Now register each value individually - ImmutableList<string> valList; + ImmutableArray<string> valList; for (int n = 0; n < names.Count; n++) { var name = names [n]; var val = values [n]; if (!props.TryGetValue (name, out valList)) - valList = ImmutableList<string>.Empty; + valList = ImmutableArray<string>.Empty; if (!valList.Contains (val)) props[name] = valList.Add (val); } @@ -252,12 +252,12 @@ namespace MonoDevelop.Projects /// <summary> /// Gets the values used in conditions for the given property /// </summary> - public ImmutableList<string> GetAllPropertyValues (string property) + public ImmutableArray<string> GetAllPropertyValues (string property) { - ImmutableList<string> list; + ImmutableArray<string> list; if (props.TryGetValue (property, out list)) return list; - return ImmutableList<string>.Empty; + return ImmutableArray<string>.Empty; } /// <summary> @@ -266,12 +266,12 @@ namespace MonoDevelop.Projects /// Platform, it will return values for those properties specified in conditions that reference both /// Configuration and Platform. /// </summary> - public ImmutableList<ValueSet> GetCombinedPropertyValues (params string[] properties) + public ImmutableArray<ValueSet> GetCombinedPropertyValues (params string[] properties) { - ImmutableList<ValueSet> list; + ImmutableArray<ValueSet> list; if (combinedProps.TryGetValue (new KeySet (properties), out list)) return list; - return ImmutableList<ValueSet>.Empty; + return ImmutableArray<ValueSet>.Empty; } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/FileWatcherService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/FileWatcherService.cs index c2bf45fd01..b438d3e13d 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/FileWatcherService.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/FileWatcherService.cs @@ -585,7 +585,8 @@ namespace MonoDevelop.Projects // the original file still exists.
if (File.Exists (e.OldFullPath))
FileService.NotifyFileChanged (e.OldFullPath);
- else
+ // Handle odd file watcher events which look like a folder being renamed to a file.
+ else if (!Directory.Exists (e.OldFullPath))
FileService.NotifyFileRemoved (e.OldFullPath);
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs index fcd55fd427..deb72f980d 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs @@ -2433,9 +2433,9 @@ namespace MonoDevelop.Projects ProjectConfiguration config = GetConfiguration (configuration) as ProjectConfiguration; if (config == null) monitor.ReportError (GettextCatalog.GetString ("Configuration '{0}' not found in project '{1}'", configuration, Name), null); - return Task.FromResult (0); + return Task.CompletedTask; } - + /// <summary> /// Gets the absolute path to the output file generated by this project. /// </summary> @@ -2971,7 +2971,7 @@ namespace MonoDevelop.Projects // Now add configurations for which a platform has not been specified, but only if no other configuration // exists with the same name. Combine them with individually specified platforms, if available foreach (var c in confValues.Select (v => v.GetValue ("Configuration"))) { - if (platValues.Count > 0) { + if (platValues.Length > 0) { foreach (var plat in platValues.Select (v => v.GetValue ("Platform"))) { var ep = plat == "AnyCPU" ? "" : plat; if (!configData.Any (cd => cd.Config == c && cd.Platform == ep)) diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SdkProjectReader.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SdkProjectReader.cs index 2d42a1576f..3a5273948a 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SdkProjectReader.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SdkProjectReader.cs @@ -65,7 +65,8 @@ namespace MonoDevelop.Projects // 2) An Sdk node as a child of the Project node // 3) An Sdk attribute on any Import node var document = new XmlDocument (); - document.Load (new StreamReader (file)); + using (var sr = new StreamReader (file)) + document.Load (sr); XmlNode projectNode = document.SelectSingleNode ("/Project"); if (projectNode != null) { XmlAttribute sdkAttr = projectNode.Attributes ["Sdk"]; diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs index 4e87f0af31..5986e425e5 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs @@ -80,7 +80,7 @@ namespace MonoDevelop.Projects internal Solution (bool loading) { loadingFromConstructor = loading; - Counters.SolutionsLoaded++; + Counters.SolutionsLoaded.Inc (1); configurations = new SolutionConfigurationCollection (this); runConfigurations = new MultiItemSolutionRunConfigurationCollection (this); format = MSBuildFileFormat.DefaultFormat; @@ -592,7 +592,7 @@ namespace MonoDevelop.Projects // Dispose the root folder after we dispose the base item, as we need the root folder // to contain the items when unregistering from the file watcher service. RootFolder.Dispose (); - Counters.SolutionsLoaded--; + Counters.SolutionsLoaded.Dec (1); } internal bool IsSolutionItemEnabled (string solutionItemPath) @@ -925,7 +925,7 @@ namespace MonoDevelop.Projects /*protected virtual*/ Task OnPrepareExecution (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration, SolutionRunConfiguration runConfiguration) { - return Task.FromResult (0); + return Task.CompletedTask; } /*protected virtual*/ void OnStartupItemChanged(EventArgs e) diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolder.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolder.cs index 725a7b2cf3..0047fd2b8d 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolder.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolder.cs @@ -399,7 +399,7 @@ namespace MonoDevelop.Projects public Task Execute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { - return Task.FromResult (false); + return Task.CompletedTask; } public bool CanExecute (ExecutionContext context, ConfigurationSelector configuration) @@ -409,7 +409,7 @@ namespace MonoDevelop.Projects public Task PrepareExecution (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { - return Task.FromResult (false); + return Task.CompletedTask; } // note: although executing folders isn't supported, this may still get called when diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs index d3296fdee1..1cb0bdf6bc 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs @@ -85,7 +85,7 @@ namespace MonoDevelop.Projects configurations = new SolutionItemConfigurationCollection (this); configurations.ConfigurationAdded += OnConfigurationAddedToCollection; configurations.ConfigurationRemoved += OnConfigurationRemovedFromCollection; - Counters.ItemsLoaded++; + Counters.ItemsLoaded.Inc (1); fileStatusTracker = new FileStatusTracker<SolutionItemEventArgs> (this, OnReloadRequired, new SolutionItemEventArgs (this)); } @@ -123,7 +123,7 @@ namespace MonoDevelop.Projects fileStatusTracker.Dispose (); base.OnDispose (); - Counters.ItemsLoaded--; + Counters.ItemsLoaded.Dec (1); // items = null; // wildcardItems = null; @@ -1080,7 +1080,7 @@ namespace MonoDevelop.Projects [Obsolete ("Use overload that takes a RunConfiguration")] protected virtual Task OnExecute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { - return Task.FromResult (0); + return Task.CompletedTask; } /// <summary> @@ -1105,7 +1105,7 @@ namespace MonoDevelop.Projects [Obsolete ("Use overload that takes a RunConfiguration")] protected virtual Task OnPrepareExecution (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { - return Task.FromResult (true); + return Task.CompletedTask; } bool DoGetCanExecute (ExecutionContext context, ConfigurationSelector configuration, SolutionItemRunConfiguration runConfiguration) diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownSolutionItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownSolutionItem.cs index e718d5e03c..e89aa6476e 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownSolutionItem.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/UnknownSolutionItem.cs @@ -101,7 +101,7 @@ namespace MonoDevelop.Projects protected internal override Task OnSave (ProgressMonitor monitor) { - return Task.FromResult (0); + return Task.CompletedTask; } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItem.cs index dafbe867f6..2927163932 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItem.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItem.cs @@ -280,7 +280,7 @@ namespace MonoDevelop.Projects protected internal virtual Task OnSave (ProgressMonitor monitor) { - return Task.FromResult (0); + return Task.CompletedTask; } public virtual bool NeedsReload { @@ -330,7 +330,7 @@ namespace MonoDevelop.Projects { Loading = false; fileStatusTracker.ResetLoadTimes (); - return Task.FromResult (true); + return Task.CompletedTask; } /// <summary> diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/CommandSearchCategory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/CommandSearchCategory.cs index 4f6e636415..eacb97fb2d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/CommandSearchCategory.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/CommandSearchCategory.cs @@ -64,18 +64,8 @@ namespace MonoDevelop.Components.MainToolbar sortOrder = CommandCategoryOrder; } - readonly string[] validTags = { "cmd", "command", "c" }; - - public override string [] Tags { - get { - return validTags; - } - } - - public override bool IsValidTag (string tag) - { - return validTags.Any (t => t == tag); - } + public override string [] Tags { get; } = { "cmd", "command", "c" }; + public override bool IsValidTag (string tag) => Array.IndexOf (Tags, tag) >= 0; public override Task GetResults (ISearchResultCallback searchResultCallback, SearchPopupSearchPattern pattern, CancellationToken token) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/FileSearchCategory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/FileSearchCategory.cs index 76e923f2ac..9c8875a4d6 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/FileSearchCategory.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/FileSearchCategory.cs @@ -86,18 +86,8 @@ namespace MonoDevelop.Components.MainToolbar return list; } - string [] validTags = new [] { "file", "f" }; - - public override string [] Tags { - get { - return validTags; - } - } - - public override bool IsValidTag (string tag) - { - return validTags.Any (t => t == tag); - } + public override string [] Tags { get; } = { "file", "f" }; + public override bool IsValidTag (string tag) => Array.IndexOf (Tags, tag) >= 0; static List<Tuple<string, string, ProjectFile>> allFilesCache; static SemaphoreSlim allFilesLock = new SemaphoreSlim (1, 1); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs index c73b1972b1..959db38cb8 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs @@ -575,6 +575,7 @@ namespace MonoDevelop.Components.MainToolbar currentSolution.StartupConfigurationChanged -= HandleStartupItemChanged; currentSolution.Saved -= HandleSolutionSaved; currentSolution.EntrySaved -= HandleSolutionEntrySaved; + currentSolution.SolutionItemAdded -= HandleSolutionItemAdded; } currentSolution = e.Solution; @@ -583,6 +584,7 @@ namespace MonoDevelop.Components.MainToolbar currentSolution.StartupConfigurationChanged += HandleStartupItemChanged; currentSolution.Saved += HandleSolutionSaved; currentSolution.EntrySaved += HandleSolutionEntrySaved; + currentSolution.SolutionItemAdded += HandleSolutionItemAdded; } TrackStartupProject (); @@ -625,6 +627,14 @@ namespace MonoDevelop.Components.MainToolbar HandleSolutionSaved (sender, e); } + void HandleSolutionItemAdded (object sender, SolutionItemChangeEventArgs e) + { + // When a solution item is added due to a reload we need to ensure the configurationMergers dictionary is + // using the new project and not the old disposed project. + if (e.Reloading) + UpdateCombos (); + } + void HandleStartupItemChanged (object sender, EventArgs e) { TrackStartupProject (); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/RoslynSearchCategory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/RoslynSearchCategory.cs index 4bbded7af5..c34ef49227 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/RoslynSearchCategory.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/RoslynSearchCategory.cs @@ -56,23 +56,14 @@ namespace MonoDevelop.Components.MainToolbar sortOrder = FirstCategoryOrder;
}
- static readonly string [] tags = new [] {
+ public override string [] Tags { get; } = new [] {
// Types
"type", "t", "class", "struct", "interface", "enum", "delegate",
// Members
"member", "m", "method", "property", "field", "event"
- };
-
- public override string [] Tags {
- get {
- return tags;
- }
- }
-
- public override bool IsValidTag (string tag)
- {
- return tags.Contains (tag);
- }
+ }; + + public override bool IsValidTag (string tag) => Array.IndexOf (Tags, tag) >= 0;
static readonly IImmutableSet<string> typeKinds = ImmutableHashSet.Create (
NavigateToItemKind.Class,
@@ -154,7 +145,7 @@ namespace MonoDevelop.Components.MainToolbar if (string.IsNullOrEmpty (searchPattern.Pattern))
return Task.CompletedTask;
- if (searchPattern.Tag != null && !tags.Contains (searchPattern.Tag) || searchPattern.HasLineNumber)
+ if (searchPattern.Tag != null && Array.IndexOf (Tags, searchPattern.Tag) < 0 || searchPattern.HasLineNumber)
return Task.CompletedTask;
return Task.Run (async delegate {
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs index d3d6474915..ec317bad20 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs @@ -59,18 +59,9 @@ namespace MonoDevelop.Components.MainToolbar // return (ISearchDataSource)new SearchInSolutionDataSource (searchPattern); // }); //} - static readonly string[] tags = { "search" }; + public override string [] Tags { get; } = { "search" }; - public override string[] Tags { - get { - return tags; - } - } - - public override bool IsValidTag (string tag) - { - return tag == "search"; - } + public override bool IsValidTag (string tag) => tag == "search"; class SearchInSolutionSearchResult : SearchResult { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.BuildOutputView/BuildOutputViewContent.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.BuildOutputView/BuildOutputViewContent.cs index ff00434baf..b773ca4a4e 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.BuildOutputView/BuildOutputViewContent.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.BuildOutputView/BuildOutputViewContent.cs @@ -60,7 +60,7 @@ namespace MonoDevelop.Ide.BuildOutputView { this.buildOutput = buildOutput; DocumentTitle = $"{GettextCatalog.GetString ("Build Output")} {DateTime.Now.ToString ("h:mm tt yyyy-MM-dd")}.binlog"; - Counters.OpenedFromIDE++; + Counters.OpenedFromIDE.Inc (1); } protected override async Task OnInitialize (ModelDescriptor modelDescriptor, Properties status) @@ -70,7 +70,7 @@ namespace MonoDevelop.Ide.BuildOutputView if (modelDescriptor is FileDescriptor file) { FilePath = file.FilePath; loadedFromFile = true; - Counters.OpenedFromFile++; + Counters.OpenedFromFile.Inc (1); } } @@ -206,7 +206,7 @@ namespace MonoDevelop.Ide.BuildOutputView [CommandHandler (FileCommands.Save)] protected override Task OnSave () { - Counters.SavedToFile++; + Counters.SavedToFile.Inc (1); return control.SaveAs (); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Codons/PadCodon.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Codons/PadCodon.cs index 27a2ee4598..77a8ba0e26 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Codons/PadCodon.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Codons/PadCodon.cs @@ -135,7 +135,7 @@ namespace MonoDevelop.Ide.Codons protected virtual PadContent CreatePad () { - Counters.PadsLoaded++; + Counters.PadsLoaded.Inc (1); return (PadContent) Addin.CreateInstance (ClassName, true); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs index 2ecb25f055..47c7c983c9 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs @@ -513,6 +513,8 @@ namespace MonoDevelop.Ide.Desktop public static bool AccessibilityKeyboardFocusInUse { get; protected set; } + internal virtual void MakeAccessibilityAnnouncement (string text) { } + internal virtual string GetNativeRuntimeDescription () { return null; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/AutoSave.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/AutoSave.cs index 5d5adc3915..ad93550190 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/AutoSave.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/AutoSave.cs @@ -111,7 +111,7 @@ namespace MonoDevelop.Ide.Editor if (File.Exists (autosaveFileName)) File.Delete (autosaveFileName); content.WriteTextTo (autosaveFileName); - Counters.AutoSavedFiles++; + Counters.AutoSavedFiles.Inc (1); } catch (Exception e) { LoggingService.LogError ("Error in auto save while creating: " + fileName +". Disableing auto save.", e); DisableAutoSave (); @@ -158,20 +158,20 @@ namespace MonoDevelop.Ide.Editor } } } - static Task finishedTask = Task.FromResult (true); + internal static Task InformAutoSaveThread (ITextSource content, string fileName, bool isDirty) { if (content == null) throw new ArgumentNullException (nameof (content)); if (!autoSaveEnabled || string.IsNullOrEmpty (fileName)) - return finishedTask; + return Task.CompletedTask; if (isDirty) { return Task.Run (() => { CreateAutoSave (fileName, content); }); } else { RemoveAutoSaveFile (fileName); - return finishedTask; + return Task.CompletedTask; } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DefaultSourceEditorOptions.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DefaultSourceEditorOptions.cs index cc9805e70f..53745babf6 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DefaultSourceEditorOptions.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DefaultSourceEditorOptions.cs @@ -333,7 +333,7 @@ namespace MonoDevelop.Ide.Editor private Task UpdateContextOptions (object sender, CodingConventionsChangedEventArgs arg) { if (context == null) - return Task.FromResult (false); + return Task.CompletedTask; bool followCodingConventions = IdeApp.Preferences.Editor.FollowCodingConventions; @@ -368,7 +368,7 @@ namespace MonoDevelop.Ide.Editor } } this.FireChange (); - return Task.FromResult (true); + return Task.CompletedTask; } #region new options diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/VersionInformationTabPage.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/VersionInformationTabPage.cs index 13b54f8d59..d766d37830 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/VersionInformationTabPage.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/VersionInformationTabPage.cs @@ -105,7 +105,7 @@ namespace MonoDevelop.Ide.Gui.Dialogs contentBox.BorderWidth = 4; contentBox.PackStart (buf, false, false, 0); - var asmButton = new Gtk.Button ("Show loaded assemblies"); + var asmButton = new Gtk.Button (GettextCatalog.GetString ("Show loaded assemblies")); asmButton.Clicked += (sender, e) => { asmButton.Hide (); contentBox.PackStart (CreateAssembliesTable (), false, false, 0); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs index d7cb48b503..4fe44f4e70 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs @@ -366,19 +366,22 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad folderFile.Subtype = Subtype.Directory; project.Files.Add (folderFile); } - var children = FileNestingService.GetDependentOrNestedTree (file); if (children != null) { foreach (var child in children.ToArray ()) { - project.Files.Remove (child); - if(delete) + // Delete file before removing them from the project to avoid Remove items being added + // if the project is currently being saved in memory or to disk. + if (delete) FileService.DeleteFile (child.Name); + project.Files.Remove (child); } } - project.Files.Remove (file); + // Delete file before removing them from the project to avoid Remove items being added + // if the project is currently being saved in memory or to disk. if (delete && !file.IsLink) FileService.DeleteFile (file.Name); + project.Files.Remove (file); } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs index 5070f796f1..f0404a5e03 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs @@ -230,19 +230,20 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad break; projects.Add (project); - - //remove the files and link files in the directory - foreach (var f in files) - project.Files.Remove (f); - - // also remove the folder's own ProjectFile, if it exists - // FIXME: it probably was already in the files list - if (folderPf != null) - project.Files.Remove (folderPf); } - + // Delete folder before removing it and its files from the project to avoid Remove items being + // added to the project if the project is currently being saved in memory or to disk. DeleteFolder (folder); - + + //remove the files and link files in the directory + foreach (var f in files) + project.Files.Remove (f); + + // also remove the folder's own ProjectFile, if it exists + // FIXME: it probably was already in the files list + if (folderPf != null) + project.Files.Remove (folderPf); + if (isProjectFolder && folder.Path.ParentDirectory != project.BaseDirectory) { // If it's the last item in the parent folder, make sure we keep a reference to the parent // folder, so it is not deleted from the tree. diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/UnknownEntryNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/UnknownEntryNodeBuilder.cs index cc9212fe44..6ada8f0715 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/UnknownEntryNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/UnknownEntryNodeBuilder.cs @@ -97,7 +97,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public async void OnReload () { var solutions = new HashSet<Solution> (); - Task task = Task.FromResult (0); + Task task = Task.CompletedTask; using (ProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetProjectLoadProgressMonitor (true)) { m.BeginTask (null, CurrentNodes.Length); foreach (ITreeNavigator node in CurrentNodes) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs index c826300f8a..aac3a29b8f 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs @@ -1041,7 +1041,7 @@ namespace MonoDevelop.Ide.Gui.Pads SetInitialOutputViewSize (control.Allocation.Width); if (visible) { - Counters.BuildLogShown++; + Counters.BuildLogShown.Inc (1); } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Shell/DefaultWorkbench.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Shell/DefaultWorkbench.cs index 4dad8a2ecb..253d1f5483 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Shell/DefaultWorkbench.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Shell/DefaultWorkbench.cs @@ -470,7 +470,7 @@ namespace MonoDevelop.Ide.Gui PadWindow win = (PadWindow) GetPadWindow (codon); if (win != null) { win.NotifyDestroyed (); - Counters.PadsLoaded--; + Counters.PadsLoaded.Dec (1); padCodons.Remove (win); } if (item != null) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Wizard/WizardDialogController.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Wizard/WizardDialogController.cs index 94ee7d76f6..b99021a5cc 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Wizard/WizardDialogController.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Wizard/WizardDialogController.cs @@ -141,7 +141,7 @@ namespace MonoDevelop.Ide.Gui.Wizard protected virtual Task OnCompleted (CancellationToken token) { - return Task.FromResult (true); + return Task.CompletedTask; } protected virtual void OnPropertyChanged (string propertyName) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs index 72fc681f2f..90185898da 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs @@ -236,7 +236,7 @@ namespace MonoDevelop.Ide.Gui internal Document (DocumentManager documentManager, IShell shell, DocumentController controller, DocumentControllerDescription controllerDescription, IWorkbenchWindow window) { - Counters.OpenDocuments++; + Counters.OpenDocuments.Inc (1); this.shell = shell; this.documentManager = documentManager; @@ -377,7 +377,7 @@ namespace MonoDevelop.Ide.Gui public ITextBuffer TextBuffer => GetContent<ITextBuffer> (); - Task currentOperationTask = Task.FromResult (true); + Task currentOperationTask = Task.CompletedTask; Task RunAsyncOperation (Func<Task> action) { @@ -578,7 +578,7 @@ namespace MonoDevelop.Ide.Gui shell.CloseView (window, true); - Counters.OpenDocuments--; + Counters.OpenDocuments.Dec (1); Dispose (); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.cs index 33c9d388a1..b4fa2f72b7 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.cs @@ -78,23 +78,7 @@ namespace MonoDevelop.Ide.Projects actionHandler.PerformShowMenu += PerformShowMenu;
} - void ProjectCreationFailed (object obj, EventArgs args) => ShowProjectCreationAccessibityNotification (true);
- void ProjectCreated(object obj, EventArgs args) => ShowProjectCreationAccessibityNotification (false);
async void NextButtonClicked (object sender, EventArgs e) => await MoveToNextPage ();
-
- void ShowProjectCreationAccessibityNotification (bool hasError)
- {
- var projectTemplate = controller.SelectedTemplate;
-
- string messageText; -
- if (hasError) - messageText = GettextCatalog.GetString ("{0} failed to create", projectTemplate.Name); - else - messageText = GettextCatalog.GetString ("{0} successfully created", projectTemplate.Name);
-
- this.Accessible.MakeAccessibilityAnnouncement (messageText); - }
public void ShowDialog ()
{
@@ -114,8 +98,6 @@ namespace MonoDevelop.Ide.Projects public void RegisterController (INewProjectDialogController controller)
{
this.controller = controller;
- controller.ProjectCreationFailed += ProjectCreationFailed;
- controller.ProjectCreated += ProjectCreated;
languageCellRenderer.SelectedLanguage = controller.SelectedLanguage;
topBannerLabel.Text = controller.BannerText;
LoadTemplates ();
@@ -299,9 +281,6 @@ namespace MonoDevelop.Ide.Projects if (!controller.IsLastPage)
projectConfigurationWidget.Destroy ();
- controller.ProjectCreationFailed -= ProjectCreationFailed;
- controller.ProjectCreated -= ProjectCreated;
-
base.OnDestroyed ();
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs index 455929c782..41705740a0 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs @@ -613,6 +613,8 @@ namespace MonoDevelop.Ide.Projects public async Task Create ()
{
+ Runtime.AssertMainThread (); + OnProjectCreating (); projectCreated = new TaskCompletionSource<bool> ();
if (wizardProvider.HasWizard)
@@ -620,7 +622,7 @@ namespace MonoDevelop.Ide.Projects if (!await CreateProject ()) { projectCreated.SetResult (false);
- ProjectCreationFailed?.Invoke (this, EventArgs.Empty);
+ OnProjectCreationFailed (); return;
}
@@ -714,13 +716,41 @@ namespace MonoDevelop.Ide.Projects UpdateDefaultSettings (); projectCreated.SetResult (true); - await Runtime.RunInMainThread (() => ProjectCreated?.Invoke (this, EventArgs.Empty)); + OnProjectCreated (); } catch (Exception ex) { projectCreated.SetException (ex); throw; }
} + void OnProjectCreating () + { + if (IdeServices.DesktopService.AccessibilityInUse) { + var announcement = GettextCatalog.GetString ("Creating project {0}", SelectedTemplate.Name); + IdeServices.DesktopService.MakeAccessibilityAnnouncement (announcement); + } + } + + void OnProjectCreationFailed () + { + ProjectCreationFailed?.Invoke (this, EventArgs.Empty); + + if (IdeServices.DesktopService.AccessibilityInUse) { + var announcement = GettextCatalog.GetString ("{0} failed to create", SelectedTemplate.Name); + IdeServices.DesktopService.MakeAccessibilityAnnouncement (announcement); + } + } + + void OnProjectCreated () + { + ProjectCreated?.Invoke (this, EventArgs.Empty); + + if (IdeServices.DesktopService.AccessibilityInUse) { + var announcement = GettextCatalog.GetString ("{0} successfully created", SelectedTemplate.Name); + IdeServices.DesktopService.MakeAccessibilityAnnouncement (announcement); + } + } + public Task<bool> ProjectCreation => projectCreated?.Task; TaskCompletionSource<bool> projectCreated;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/PropertyDescriptionTemplate.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/PropertyDescriptionTemplate.cs index 7b223911fe..0294419425 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/PropertyDescriptionTemplate.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/PropertyDescriptionTemplate.cs @@ -75,7 +75,7 @@ namespace MonoDevelop.Ide.Templates var fileName = StringParserService.Parse (name, model); project.ProjectProperties.SetValue (typeAtt.Value, string.IsNullOrEmpty (fileName) ? propertyInnerText : string.Concat (fileName, extension)); - return Task.FromResult(true); + return Task.FromResult (true); } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.cs index bdd4b2039c..0032dd5951 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.cs @@ -336,7 +336,10 @@ namespace MonoDevelop.Ide.TypeSystem protected override void ClearProjectData (ProjectId projectId)
{
var actualProject = ProjectMap.RemoveProject (projectId);
- UnloadMonoProject (actualProject);
+ // Do not unload the project if there are still project ids mappings defined for this project.
+ // This prevents the Project.Modified event being unsubscribed for the wrong project on project reload.
+ if (actualProject != null && ProjectMap.GetIds (actualProject) == null)
+ UnloadMonoProject (actualProject);
dynamicFileManager?.UnloadProject (projectId);
base.ClearProjectData (projectId);
@@ -994,7 +997,7 @@ namespace MonoDevelop.Ide.TypeSystem /// Used by tests to validate that project has been saved.
/// </summary>
/// <value>The task that can be awaited to validate saving has finished.</value>
- internal Task ProjectSaveTask { get; private set; } = Task.FromResult<object> (null);
+ internal Task ProjectSaveTask { get; private set; } = Task.CompletedTask;
internal override bool TryApplyChanges (Solution newSolution, IProgressTracker progressTracker)
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs index 37c4cd60c9..a44b14be25 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs @@ -447,6 +447,11 @@ namespace MonoDevelop.Ide PlatformService.RestartIde (reopenWorkspace); } + public void MakeAccessibilityAnnouncement(string text) + { + PlatformService.MakeAccessibilityAnnouncement (text); + } + public bool AccessibilityInUse { get { return PlatformService.AccessibilityInUse; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ImageService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ImageService.cs index b1dc79a125..cd1b75f497 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ImageService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ImageService.cs @@ -913,7 +913,7 @@ namespace MonoDevelop.Ide class CustomImageLoader : Xwt.Drawing.IImageLoader { RuntimeAddin addin; - Dictionary<System.Reflection.Assembly, string []> resources = new Dictionary<System.Reflection.Assembly, string[]> (); + static Dictionary<System.Reflection.Assembly, List<string>> resources = new Dictionary<System.Reflection.Assembly, List<string>> (); public CustomImageLoader (RuntimeAddin addin) { @@ -924,11 +924,12 @@ namespace MonoDevelop.Ide { var r = addin.GetResourceInfo (fileName); - string [] resourceList; - if (!resources.TryGetValue (r.ReferencedAssembly, out resourceList)) - resourceList = resources [r.ReferencedAssembly] = r.ReferencedAssembly.GetManifestResourceNames (); + if (!resources.TryGetValue (r.ReferencedAssembly, out var resourceList)) { + resourceList = resources [r.ReferencedAssembly] = r.ReferencedAssembly.GetManifestResourceNames ().ToList (); + resourceList.Sort (); // sort resources by name + } - return resourceList; + return resourceList.Where (r => r.StartsWith (baseName) && r.EndsWith (ext)); } public Stream LoadImage (string fileName) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs index d324842b72..190e9db83b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs @@ -529,7 +529,7 @@ namespace MonoDevelop.Ide return SaveAsync ((IWorkspaceFileObject)item); if (item.ParentObject != null) return SaveAsync (item.ParentObject); - return Task.FromResult (0); + return Task.CompletedTask; } async Task SaveAsync (IWorkspaceFileObject item) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs index c3303b93ab..0b95aad703 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs @@ -429,7 +429,7 @@ namespace MonoDevelop.Ide Task IBuildTarget.PrepareExecution (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) { - return Task.FromResult (0); + return Task.CompletedTask; } public Task Execute (ProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration) diff --git a/main/src/core/MonoDevelop.Startup/app.config b/main/src/core/MonoDevelop.Startup/app.config index ac6d9c0ea6..31a7a20181 100644 --- a/main/src/core/MonoDevelop.Startup/app.config +++ b/main/src/core/MonoDevelop.Startup/app.config @@ -36,20 +36,20 @@ <dependentAssembly><assemblyIdentity name="Mono.Cecil" culture="neutral" publicKeyToken="50cebf1cceb9d05e" /><bindingRedirect oldVersion="0.0.0.0-0.10.1.0" newVersion="0.10.1.0" /></dependentAssembly> <dependentAssembly><assemblyIdentity name="mscorlib" culture="neutral" publicKeyToken="b77a5c561934e089" /><bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" /></dependentAssembly> <dependentAssembly><assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" /></dependentAssembly> - <dependentAssembly><assemblyIdentity name="NuGet.Commands" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.3.0.3" newVersion="5.3.0.3" /></dependentAssembly> - <dependentAssembly><assemblyIdentity name="NuGet.Common" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.3.0.3" newVersion="5.3.0.3" /></dependentAssembly> - <dependentAssembly><assemblyIdentity name="NuGet.Configuration" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.3.0.3" newVersion="5.3.0.3" /></dependentAssembly> - <dependentAssembly><assemblyIdentity name="NuGet.Credentials" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.3.0.3" newVersion="5.3.0.3" /></dependentAssembly> - <dependentAssembly><assemblyIdentity name="NuGet.DependencyResolver.Core" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.3.0.3" newVersion="5.3.0.3" /></dependentAssembly> - <dependentAssembly><assemblyIdentity name="NuGet.Frameworks" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.3.0.3" newVersion="5.3.0.3" /></dependentAssembly> - <dependentAssembly><assemblyIdentity name="NuGet.Indexing" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.3.0.3" newVersion="5.3.0.3" /></dependentAssembly> - <dependentAssembly><assemblyIdentity name="NuGet.LibraryModel" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.3.0.3" newVersion="5.3.0.3" /></dependentAssembly> - <dependentAssembly><assemblyIdentity name="NuGet.PackageManagement" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.3.0.3" newVersion="5.3.0.3" /></dependentAssembly> - <dependentAssembly><assemblyIdentity name="NuGet.Packaging" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.3.0.3" newVersion="5.3.0.3" /></dependentAssembly> - <dependentAssembly><assemblyIdentity name="NuGet.ProjectModel" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.3.0.3" newVersion="5.3.0.3" /></dependentAssembly> - <dependentAssembly><assemblyIdentity name="NuGet.Protocol" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.3.0.3" newVersion="5.3.0.3" /></dependentAssembly> - <dependentAssembly><assemblyIdentity name="NuGet.Resolver" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.3.0.3" newVersion="5.3.0.3" /></dependentAssembly> - <dependentAssembly><assemblyIdentity name="NuGet.Versioning" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.3.0.3" newVersion="5.3.0.3" /></dependentAssembly> + <dependentAssembly><assemblyIdentity name="NuGet.Commands" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.4.0.3" newVersion="5.4.0.3" /></dependentAssembly> + <dependentAssembly><assemblyIdentity name="NuGet.Common" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.4.0.3" newVersion="5.4.0.3" /></dependentAssembly> + <dependentAssembly><assemblyIdentity name="NuGet.Configuration" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.4.0.3" newVersion="5.4.0.3" /></dependentAssembly> + <dependentAssembly><assemblyIdentity name="NuGet.Credentials" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.4.0.3" newVersion="5.4.0.3" /></dependentAssembly> + <dependentAssembly><assemblyIdentity name="NuGet.DependencyResolver.Core" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.4.0.3" newVersion="5.4.0.3" /></dependentAssembly> + <dependentAssembly><assemblyIdentity name="NuGet.Frameworks" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.4.0.3" newVersion="5.4.0.3" /></dependentAssembly> + <dependentAssembly><assemblyIdentity name="NuGet.Indexing" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.4.0.3" newVersion="5.4.0.3" /></dependentAssembly> + <dependentAssembly><assemblyIdentity name="NuGet.LibraryModel" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.4.0.3" newVersion="5.4.0.3" /></dependentAssembly> + <dependentAssembly><assemblyIdentity name="NuGet.PackageManagement" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.4.0.3" newVersion="5.4.0.3" /></dependentAssembly> + <dependentAssembly><assemblyIdentity name="NuGet.Packaging" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.4.0.3" newVersion="5.4.0.3" /></dependentAssembly> + <dependentAssembly><assemblyIdentity name="NuGet.ProjectModel" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.4.0.3" newVersion="5.4.0.3" /></dependentAssembly> + <dependentAssembly><assemblyIdentity name="NuGet.Protocol" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.4.0.3" newVersion="5.4.0.3" /></dependentAssembly> + <dependentAssembly><assemblyIdentity name="NuGet.Resolver" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.4.0.3" newVersion="5.4.0.3" /></dependentAssembly> + <dependentAssembly><assemblyIdentity name="NuGet.Versioning" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.4.0.3" newVersion="5.4.0.3" /></dependentAssembly> <dependentAssembly><assemblyIdentity name="SQLitePCLRaw.batteries_v2" culture="neutral" publicKeyToken="8226ea5df37bcae9" /><bindingRedirect oldVersion="0.0.0.0-1.1.12.351" newVersion="1.1.12.351" /></dependentAssembly> <dependentAssembly><assemblyIdentity name="SQLitePCLRaw.core" culture="neutral" publicKeyToken="1488e028ca7ab535" /><bindingRedirect oldVersion="0.0.0.0-1.1.12.351" newVersion="1.1.12.351" /></dependentAssembly> <dependentAssembly><assemblyIdentity name="StreamJsonRpc" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" /><bindingRedirect oldVersion="0.0.0.0-1.5.0.0" newVersion="1.5.0.0" /></dependentAssembly> diff --git a/main/tests/Ide.Tests/MonoDevelop.Ide.Tests.csproj b/main/tests/Ide.Tests/MonoDevelop.Ide.Tests.csproj index 438d915dea..9e7ca507cf 100644 --- a/main/tests/Ide.Tests/MonoDevelop.Ide.Tests.csproj +++ b/main/tests/Ide.Tests/MonoDevelop.Ide.Tests.csproj @@ -169,11 +169,6 @@ <Name>MonoDevelop.Debugger</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\MonoDevelop.Core.Tests\MonoDevelop.Core.Tests.csproj"> <Project>{FDA43CAA-1C2A-4593-8601-3E2EE06D9E03}</Project> <Name>MonoDevelop.Core.Tests</Name> diff --git a/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/TypeSystemServiceTests.cs b/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/TypeSystemServiceTests.cs index b26364025f..635ac0fb31 100644 --- a/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/TypeSystemServiceTests.cs +++ b/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/TypeSystemServiceTests.cs @@ -304,6 +304,98 @@ namespace MonoDevelop.Ide.TypeSystem } } + /// <summary> + /// Simulates a .NET Standard sdk project being change to a multi-target project in the text editor, saved, + /// then adding a new file to the project. Previously the Project.Modified event handler would be removed + /// and the type system would never update itself. + /// </summary> + [Test] + public async Task SingleTargetFramework_ReloadProjectAfterChangingToMultiTargetFramework_TypeSystemRespondsToProjectModifiedEvents () + { + FilePath solFile = Util.GetSampleProject ("multi-target-reload", "multi-target-reload.sln"); + + CreateNuGetConfigFile (solFile.ParentDirectory); + Util.RunMSBuild ($"/t:Restore /p:RestoreDisableParallel=true \"{solFile}\""); + + using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile)) + using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) { + try { + var project = sol.GetAllProjects ().Single (); + + var projectIds = ws.CurrentSolution.ProjectIds.ToArray (); + var projects = ws.CurrentSolution.Projects.ToArray (); + + // Should be one Roslyn project. + Assert.AreEqual (1, projectIds.Length); + Assert.AreEqual (1, projects.Length); + + var updatedProjectFileName = project.FileName.ChangeName ("multi-target-reload"); + + string xml = File.ReadAllText (updatedProjectFileName); + File.WriteAllText (project.FileName, xml); + + var reloadedProject = (DotNetProject)await sol.RootFolder.ReloadItem (Util.GetMonitor (), project); + + // Try a few times since the type system needs time to reload + const int timeout = 10000; // ms + int howLong = 0; + const int interval = 200; // ms + + + while (true) { + var newProjectIds = ws.CurrentSolution.ProjectIds.ToArray (); + projects = ws.CurrentSolution.Projects.ToArray (); + + var netstandardProject = projects.FirstOrDefault (p => p.Name == "netstandard (netstandard2.0)"); + var netframeworkProject = projects.FirstOrDefault (p => p.Name == "netstandard (net462)"); + if (netframeworkProject != null && netstandardProject != null) { + Assert.AreEqual (2, newProjectIds.Length); + Assert.AreEqual (2, projects.Length); + break; + } + + if (howLong >= timeout) { + Assert.Fail ("Timed out waiting for type system information to be updated."); + } + + await Task.Delay (interval); + howLong += interval; + } + + // Add a new file. + var projectFileName = reloadedProject.BaseDirectory.Combine ("Test.cs"); + File.WriteAllText (projectFileName, "class Test { }"); + + var projectFile = new ProjectFile (projectFileName, BuildAction.Compile); + reloadedProject.Files.Add (projectFile); + + howLong = 0; + + while (true) { + projects = ws.CurrentSolution.Projects.ToArray (); + + var netstandardProject = projects.FirstOrDefault (p => p.Name == "netstandard (netstandard2.0)"); + var netframeworkProject = projects.FirstOrDefault (p => p.Name == "netstandard (net462)"); + + if (netstandardProject.Documents.Any (d => d.Name == "Test.cs") && + netframeworkProject.Documents.Any (d => d.Name == "Test.cs")) { + // OK - document registered with type system service. + return; + } + + if (howLong >= timeout) { + Assert.Fail ("Timed out waiting for type system information to be updated after adding file."); + } + + await Task.Delay (interval); + howLong += interval; + } + } finally { + TypeSystemServiceTestExtensions.UnloadSolution (sol); + } + } + } + [Test] public async Task CSharpFile_BuildActionNone_FileNotUsed () { diff --git a/main/tests/IdeUnitTests/IdeUnitTests.csproj b/main/tests/IdeUnitTests/IdeUnitTests.csproj index ba837a8c72..f542f3f167 100644 --- a/main/tests/IdeUnitTests/IdeUnitTests.csproj +++ b/main/tests/IdeUnitTests/IdeUnitTests.csproj @@ -67,11 +67,6 @@ <Name>Xwt</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\..\external\guiunit\src\framework\GuiUnit_NET_4_5.csproj"> <Project>{D12F0F7B-8DE3-43EC-BA49-41052D065A9B}</Project> <Name>GuiUnit_NET_4_5</Name> diff --git a/main/tests/MacPlatform.Tests/MacPlatformTest.cs b/main/tests/MacPlatform.Tests/MacPlatformTest.cs index e5a415f5af..4e06e884c7 100644 --- a/main/tests/MacPlatform.Tests/MacPlatformTest.cs +++ b/main/tests/MacPlatform.Tests/MacPlatformTest.cs @@ -181,7 +181,7 @@ namespace MacPlatform.Tests public void CriticalErrorsExceptionsHaveFullStacktracesInLog () { var logger = new CapturingLogger { - EnabledLevel = EnabledLoggingLevel.Fatal, + EnabledLevel = EnabledLoggingLevel.Error, }; try { @@ -192,7 +192,7 @@ namespace MacPlatform.Tests Assert.Throws<ObjCException> (() => void_objc_msgSend (ex.Handle, selector)); - var (_, message) = logger.LogMessages.Single (x => x.Level == LogLevel.Fatal); + var (_, message) = logger.LogMessages.Single (x => x.Level == LogLevel.Error); AssertMacPlatformStacktrace (message); } finally { LoggingService.RemoveLogger (logger.Name); @@ -203,7 +203,7 @@ namespace MacPlatform.Tests { Assert.That (stacktrace, Contains.Substring ("at MonoDevelopProcessHost.Main")); Assert.That (stacktrace, Contains.Substring ("at MacPlatform.Tests.MacPlatformTest.void_objc_msgSend")); - Assert.That (stacktrace, Contains.Substring ("at MonoDevelop.MacIntegration.MacPlatformService.HandleUncaughtException")); + Assert.That (stacktrace, Contains.Substring ("at MonoDevelop.MacIntegration.MacPlatformService+MarshalledObjCException..ctor")); } diff --git a/main/tests/MonoDevelop.CSharpBinding.Tests/MonoDevelop.CSharpBinding.Tests.csproj b/main/tests/MonoDevelop.CSharpBinding.Tests/MonoDevelop.CSharpBinding.Tests.csproj index 47ad6e424f..b7dacf1b38 100644 --- a/main/tests/MonoDevelop.CSharpBinding.Tests/MonoDevelop.CSharpBinding.Tests.csproj +++ b/main/tests/MonoDevelop.CSharpBinding.Tests/MonoDevelop.CSharpBinding.Tests.csproj @@ -47,6 +47,7 @@ <Compile Include="Features\Completion\AbstractCSharpCompletionProviderTests.cs" /> <Compile Include="Features\Completion\ProtocolMemberCompletionTests.cs" /> <Compile Include="MonoDevelop.CSharpBinding\CSharpCompletionTextEditorTests.cs" /> + <Compile Include="MonoDevelop.CSharpBinding\CSharpCompilerParametersTests.cs" /> <Compile Include="MonoDevelop.CSharpBinding\CSharpProjectPropertiesTests.cs" /> <Compile Include="MonoDevelop.CSharpBinding\CSharpTextEditorIndentationTests.cs" /> <Compile Include="MonoDevelop.CSharpBinding\FindMemberVisitorTests.cs" /> diff --git a/main/tests/MonoDevelop.CSharpBinding.Tests/MonoDevelop.CSharpBinding/CSharpCompilerParametersTests.cs b/main/tests/MonoDevelop.CSharpBinding.Tests/MonoDevelop.CSharpBinding/CSharpCompilerParametersTests.cs new file mode 100644 index 0000000000..f345326848 --- /dev/null +++ b/main/tests/MonoDevelop.CSharpBinding.Tests/MonoDevelop.CSharpBinding/CSharpCompilerParametersTests.cs @@ -0,0 +1,64 @@ +// +// CSharpCompilerParametersTests.cs +// +// Author: +// Matt Ward <matt.ward@microsoft.com> +// +// Copyright (c) 2020 Microsoft Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using MonoDevelop.CSharp.Project; +using MonoDevelop.Projects; +using NUnit.Framework; +using UnitTests; + +namespace MonoDevelop.CSharpBinding +{ + [TestFixture] + public class CSharpCompilerParametersTests : TestBase + { + /// <summary> + /// Ensure OutputType has a default value that allows the compilation options to be created when the + /// project is not loaded from a file. + /// </summary> + [Test] + public void OutputType_NewProjectNotLoadedFromDisk_CompilationOptionsCanBeCreated () + { + using (var solution = new Solution ()) { + var project = Services.ProjectService.CreateDotNetProject ("C#"); + solution.RootFolder.AddItem (project); + project.CompileTarget = CompileTarget.Library; + var config = project.CreateConfiguration ("Debug", ConfigurationKind.Debug) as DotNetProjectConfiguration; + project.Configurations.Add (config); + var parameters = config.CompilationParameters as CSharpCompilerParameters; + + var options = parameters.CreateCompilationOptions (); + + Assert.AreEqual (Microsoft.CodeAnalysis.OutputKind.DynamicallyLinkedLibrary, options.OutputKind); + + // Change project's compile target to Exe. + project.CompileTarget = CompileTarget.Exe; + options = parameters.CreateCompilationOptions (); + + Assert.AreEqual (Microsoft.CodeAnalysis.OutputKind.ConsoleApplication, options.OutputKind); + } + } + } +} diff --git a/main/tests/test-projects/multi-target-reload/Class1.cs b/main/tests/test-projects/multi-target-reload/Class1.cs new file mode 100644 index 0000000000..b9a6178638 --- /dev/null +++ b/main/tests/test-projects/multi-target-reload/Class1.cs @@ -0,0 +1,8 @@ +using System;
+
+namespace netstandard_sdk
+{ + public class Class1 + { + }
+}
diff --git a/main/tests/test-projects/multi-target-reload/multi-target-reload.csproj b/main/tests/test-projects/multi-target-reload/multi-target-reload.csproj new file mode 100644 index 0000000000..3a7cf65410 --- /dev/null +++ b/main/tests/test-projects/multi-target-reload/multi-target-reload.csproj @@ -0,0 +1,7 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFrameworks>netstandard2.0;net462</TargetFrameworks> + </PropertyGroup> + +</Project> diff --git a/main/tests/test-projects/multi-target-reload/multi-target-reload.sln b/main/tests/test-projects/multi-target-reload/multi-target-reload.sln new file mode 100644 index 0000000000..c51af14ae8 --- /dev/null +++ b/main/tests/test-projects/multi-target-reload/multi-target-reload.sln @@ -0,0 +1,17 @@ +
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "netstandard", "netstandard.csproj", "{5B443F8D-6C84-443F-A395-5429E8F4A47D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {5B443F8D-6C84-443F-A395-5429E8F4A47D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5B443F8D-6C84-443F-A395-5429E8F4A47D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5B443F8D-6C84-443F-A395-5429E8F4A47D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5B443F8D-6C84-443F-A395-5429E8F4A47D}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/main/tests/test-projects/multi-target-reload/netstandard.csproj b/main/tests/test-projects/multi-target-reload/netstandard.csproj new file mode 100644 index 0000000000..b290d67fb7 --- /dev/null +++ b/main/tests/test-projects/multi-target-reload/netstandard.csproj @@ -0,0 +1,7 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>netstandard1.4</TargetFramework> + </PropertyGroup> + +</Project> diff --git a/version-checks b/version-checks index 9d11c93500..8ccdbf35c8 100644 --- a/version-checks +++ b/version-checks @@ -17,7 +17,7 @@ DEP[0]=md-addins DEP_NAME[0]=MDADDINS DEP_PATH[0]=${top_srcdir}/../md-addins DEP_MODULE[0]=git@github.com:xamarin/md-addins.git -DEP_NEEDED_VERSION[0]=d907b662ffa091473695a099278a1f97b4e48a4c +DEP_NEEDED_VERSION[0]=62dda236bb09444226c14098de6346c1394fad0c DEP_BRANCH_AND_REMOTE[0]="master origin/master" # other dependencies |