Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorLluis Sanchez <llsan@microsoft.com>2019-04-02 14:47:19 +0300
committerLluis Sanchez <llsan@microsoft.com>2019-04-02 14:47:19 +0300
commit034efec5570d1ca12d7314ce2447692e379f446f (patch)
tree2ea03cbffcf1167f8b4b931a139729d496f073f6 /main
parent8fc7d7e202598c31fdbb54d84e3e1fcd1003eb1c (diff)
parent0331b37ed370c639781c87ac969992f362d34eb0 (diff)
Merge remote-tracking branch 'xamarin/master-vnext' into new-service-model
Diffstat (limited to 'main')
-rwxr-xr-xmain/build/MacOSX/BinaryCompatBaseline.txt12
m---------main/external/Xamarin.PropertyEditing0
-rw-r--r--main/src/addins/MacPlatform/MacPlatform.cs8
-rw-r--r--main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore/AspNetCoreCertificateManager.cs25
-rw-r--r--main/src/addins/MonoDevelop.AspNetCore/Properties/MonoDevelop.AspNetCore.addin.xml41
-rw-r--r--main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewImportsPage.xft.xml5
-rw-r--r--main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewLayoutPage.xft.xml5
-rw-r--r--main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewPage.xft.xml5
-rw-r--r--main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewStartPage.xft.xml5
-rw-r--r--main/src/addins/MonoDevelop.AspNetCore/Templates/RazorPage.xft.xml5
-rw-r--r--main/src/addins/MonoDevelop.AspNetCore/Templates/RazorPageWithPageModel.xft.xml5
-rw-r--r--main/src/addins/MonoDevelop.AspNetCore/Templates/RazorTagHelper.xft.xml5
-rw-r--r--main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/packages.config1
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/AddinInfo.cs5
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/Styles.cs4
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.csproj1
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/MacPropertyGrid.cs6
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/DirectoryPathPropertyInfo.cs2
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/FilePathPropertyInfo.cs8
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadEditorProvider.cs9
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadItem.cs69
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadObjectEditor.cs63
-rw-r--r--main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateTests.cs3
-rw-r--r--main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.csproj2
-rw-r--r--main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/DotNetProjectExtensions.cs2
-rw-r--r--main/src/addins/MonoDevelop.Packaging/Templates/CrossPlatformLibrary.xpt.xml8
-rw-r--r--main/src/addins/MonoDevelop.Packaging/Templates/PackagingProject.xpt.xml2
-rw-r--r--main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs13
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskOverviewMode.cs34
-rw-r--r--main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/MonoDevelop.TextEditor.csproj2
-rw-r--r--main/src/addins/PerformanceDiagnostics/PerformanceDiagnostics/Commands.cs7
-rw-r--r--main/src/addins/PerformanceDiagnostics/PerformanceDiagnostics/UIThreadMonitor.cs105
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs2
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/SelectRepositoryDialog.cs3
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/CellRendererDiff.cs140
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/StatusView.cs64
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs4
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlService.cs44
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/VersionControl.addin.xml2
-rw-r--r--main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs120
-rw-r--r--main/src/addins/Xml/Editor/BaseXmlEditorExtension.cs13
-rw-r--r--main/src/addins/Xml/Tests/CodeCompletion/XmlCodeCompletionTests.cs41
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml4
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml2
-rw-r--r--main/src/core/MonoDevelop.Ide/Gui/MonoDevelop.Ide.Projects.AddExternalFileDialog.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockContainer.cs81
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/FoldingTextEditorExtension.cs124
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/EditorPreferences.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs10
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs19
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MiscellaneousFilesWorkspace.cs10
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.ProjectSystemHandler.cs18
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs83
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs134
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartupTracker.cs205
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs4
-rw-r--r--main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/MonoDevelopMetadataReferenceManager.MetadataReferenceCacheTests.cs92
-rw-r--r--main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/MonoDevelopMetadataReferenceManagerTests.cs6
-rw-r--r--main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspaceTests.cs8
-rw-r--r--main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/TypeSystemServiceTests.cs14
-rw-r--r--main/tests/Ide.Tests/MonoDevelop.Ide/RoslynSearchCategoryTests.cs34
-rw-r--r--main/tests/Ide.Tests/MonoDevelop.Ide/TypeSystemServiceTests.cs240
-rw-r--r--main/tests/MonoDevelop.Core.Tests/MonoDevelop.Core.Tests.csproj1
-rw-r--r--main/tests/MonoDevelop.Core.Tests/MonoDevelop.Core/UserProfileTests.cs39
-rw-r--r--main/tests/StressTest/MonoDevelop.StressTest/IEditorTestScenario.cs16
-rw-r--r--main/tests/StressTest/MonoDevelop.StressTest/Profiler/LeakProcessor.cs2
-rw-r--r--main/tests/StressTest/MonoDevelop.StressTest/Profiler/TestScenarioLeakExtensions.cs2
-rw-r--r--main/tests/StressTest/MonoDevelop.StressTest/Scenarios/DefaultScenario.cs6
-rw-r--r--main/tests/StressTest/MonoDevelop.StressTest/StressTestApp.cs56
-rw-r--r--main/tests/StressTest/StressTest.csproj2
-rw-r--r--main/tests/StressTest/UserInterfaceTests/Properties.cs15
-rw-r--r--main/tests/StressTest/UserInterfaceTests/WorkbenchExtensions.cs2
-rw-r--r--main/tests/UserInterfaceTests/Ide.cs103
-rw-r--r--main/tests/UserInterfaceTests/IdeQuery.cs58
-rw-r--r--main/tests/UserInterfaceTests/Workbench.cs23
76 files changed, 1481 insertions, 836 deletions
diff --git a/main/build/MacOSX/BinaryCompatBaseline.txt b/main/build/MacOSX/BinaryCompatBaseline.txt
index 66c17fd2ed..3d32a9625c 100755
--- a/main/build/MacOSX/BinaryCompatBaseline.txt
+++ b/main/build/MacOSX/BinaryCompatBaseline.txt
@@ -8,7 +8,7 @@ Could not load file or assembly 'Microsoft.Build.Utilities.Core, Version=15.1.0.
Could not load file or assembly 'Microsoft.Developer.IdentityService.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies
Could not load file or assembly 'Microsoft.ServiceHub.Client, Version=1.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies
Could not load file or assembly 'Microsoft.TestPlatform.Utilities, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies
-Could not load file or assembly 'MonoTouch.Hosting, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies
+Could not load file or assembly 'MonoTouch.Hosting, Version=0.0.0.0, Culture=neutral, PublicKeyToken=5caa9e03e69a5abd' or one of its dependencies
Could not load file or assembly 'System.Net.Http.Primitives, Version=1.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies
Could not load file or assembly 'System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies
Could not load file or assembly 'Xamarin.Ide.Identity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies
@@ -118,14 +118,14 @@ In assembly 'MonoDevelop.Core, Version=2.6.0.0, Culture=neutral, PublicKeyToken=
In assembly 'MonoDevelop.Debugger.Soft.IPhone, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null': unable to resolve reference to 'Xamarin.MacDev.Ide, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
In assembly 'MonoDevelop.Ide, Version=2.6.0.0, Culture=neutral, PublicKeyToken=3ead7498f347467b': unable to resolve reference to 'Microsoft.Build, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
In assembly 'MonoDevelop.Ide, Version=2.6.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 'MonoDevelop.IPhone, Version=4.0.0.0, Culture=neutral, PublicKeyToken=3ead7498f347467b': unable to resolve reference to 'MonoTouch.Hosting, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
+In assembly 'MonoDevelop.IPhone, Version=4.0.0.0, Culture=neutral, PublicKeyToken=3ead7498f347467b': unable to resolve reference to 'MonoTouch.Hosting, Version=0.0.0.0, Culture=neutral, PublicKeyToken=5caa9e03e69a5abd'
In assembly 'MonoDevelop.IPhone, Version=4.0.0.0, Culture=neutral, PublicKeyToken=3ead7498f347467b': unable to resolve reference to 'Xamarin.MacDev.Ide, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
In assembly 'MonoDevelop.MacDev, Version=4.0.0.0, Culture=neutral, PublicKeyToken=3ead7498f347467b': unable to resolve reference to 'Xamarin.MacDev.Ide, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
In assembly 'MonoDevelop.MSBuildBuilder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3ead7498f347467b': unable to resolve reference to 'Microsoft.Build, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
In assembly 'MonoDevelop.MSBuildBuilder, 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 '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=null': unable to resolve reference to 'MonoTouch.Hosting, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
+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=4.8.2.0, 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=4.8.2.0, 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=4.8.2.0, 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'
@@ -144,11 +144,11 @@ In assembly 'System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b
In assembly 'System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a': Unable to resolve type reference 'System.Net.ComNetOS' in '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 type reference 'System.Net.UnsafeNclNativeMethods/NativePKI' in 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
In assembly 'System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35': unable to resolve reference to 'System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
-In assembly 'Xamarin.Addins.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3ead7498f347467b': unable to resolve reference to 'MonoTouch.Hosting, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
-In assembly 'Xamarin.AndroidDesigner.Mac, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null': unable to resolve reference to 'MonoTouch.Hosting, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
+In assembly 'Xamarin.Addins.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3ead7498f347467b': unable to resolve reference to 'MonoTouch.Hosting, Version=0.0.0.0, Culture=neutral, PublicKeyToken=5caa9e03e69a5abd'
+In assembly 'Xamarin.AndroidDesigner.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 '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=null': unable to resolve reference to 'MonoTouch.Hosting, Version=0.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 '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/external/Xamarin.PropertyEditing b/main/external/Xamarin.PropertyEditing
-Subproject 9b122cef903d72475c4b58bf51f26060b54994f
+Subproject 031d650c59320206ca662753e938a40d473729e
diff --git a/main/src/addins/MacPlatform/MacPlatform.cs b/main/src/addins/MacPlatform/MacPlatform.cs
index 6dfb61f82f..b0dda5c1ea 100644
--- a/main/src/addins/MacPlatform/MacPlatform.cs
+++ b/main/src/addins/MacPlatform/MacPlatform.cs
@@ -640,7 +640,7 @@ namespace MonoDevelop.MacIntegration
//OpenFiles may pump the mainloop, but can't do that from an AppleEvent
GLib.Idle.Add (delegate {
Ide.WelcomePage.WelcomePageService.HideWelcomePageOrWindow ();
- var trackTTC = IdeApp.StartTimeToCodeLoadTimer ();
+ var trackTTC = IdeStartupTracker.StartupTracker.StartTimeToCodeLoadTimer ();
IdeApp.OpenFiles (e.Documents.Select (
doc => new FileOpenInformation (doc.Key, null, doc.Value, 1, OpenDocumentOptions.DefaultInternal)),
null
@@ -651,7 +651,7 @@ namespace MonoDevelop.MacIntegration
var firstFile = e.Documents.First ().Key;
- IdeApp.TrackTimeToCode (GetDocumentTypeFromFilename (firstFile));
+ IdeStartupTracker.StartupTracker.TrackTimeToCode (GetDocumentTypeFromFilename (firstFile));
});
return false;
});
@@ -660,7 +660,7 @@ namespace MonoDevelop.MacIntegration
ApplicationEvents.OpenUrls += delegate (object sender, ApplicationUrlEventArgs e) {
GLib.Idle.Add (delegate {
- var trackTTC = IdeApp.StartTimeToCodeLoadTimer ();
+ var trackTTC = IdeStartupTracker.StartupTracker.StartTimeToCodeLoadTimer ();
// Open files via the monodevelop:// URI scheme, compatible with the
// common TextMate scheme: http://blog.macromates.com/2007/the-textmate-url-scheme/
IdeApp.OpenFiles (e.Urls.Select (url => {
@@ -690,7 +690,7 @@ namespace MonoDevelop.MacIntegration
}
var firstFile = e.Urls.First ();
- IdeApp.TrackTimeToCode (GetDocumentTypeFromFilename (firstFile));
+ IdeStartupTracker.StartupTracker.TrackTimeToCode (GetDocumentTypeFromFilename (firstFile));
});
return false;
});
diff --git a/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore/AspNetCoreCertificateManager.cs b/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore/AspNetCoreCertificateManager.cs
index 1e5ec4d5ab..d6bcd21706 100644
--- a/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore/AspNetCoreCertificateManager.cs
+++ b/main/src/addins/MonoDevelop.AspNetCore/MonoDevelop.AspNetCore/AspNetCoreCertificateManager.cs
@@ -37,7 +37,8 @@ namespace MonoDevelop.AspNetCore
static class AspNetCoreCertificateManager
{
public static bool IsDevelopmentCertificateTrusted { get; private set; }
-
+ static readonly DotNetCoreVersion MinimumCoreRuntime = DotNetCoreVersion.Parse ("2.1");
+ static readonly DotNetCoreVersion MinimumCoreSDK = DotNetCoreVersion.Parse ("2.1.300");
/// <summary>
/// Only supported projects should be checked. If the development certificate
/// was found to be trusted then do not check again for the current IDE session.
@@ -52,8 +53,8 @@ namespace MonoDevelop.AspNetCore
}
/// <summary>
- /// Only .NET Core 2.1 projects are supported.
- /// Also need .NET Core SDK 2.1 to be installed.
+ /// Only .NET Core 2.1 projects and higher are supported.
+ /// Also need .NET Core SDK 2.1 or higher to be installed.
/// Also check if the project is using https.
/// </summary>
public static bool IsProjectSupported (DotNetProject project, SolutionItemRunConfiguration runConfiguration)
@@ -63,8 +64,8 @@ namespace MonoDevelop.AspNetCore
return false;
}
- return project.TargetFramework.IsNetCoreApp ("2.1") &&
- IsNetCoreSdk21Installed () &&
+ return project.TargetFramework.IsNetCoreAppOrHigher (MinimumCoreRuntime) &&
+ IsNetCoreSdk21OrHigherInstalled () &&
UsingHttps (runConfiguration);
}
@@ -74,21 +75,15 @@ namespace MonoDevelop.AspNetCore
return aspNetCoreRunConfiguration?.UsingHttps () == true;
}
- static bool IsNetCoreSdk21Installed ()
- {
- return DotNetCoreSdk.Versions.Any (IsNetCoreSdk21);
- }
+ static bool IsNetCoreSdk21OrHigherInstalled () => DotNetCoreSdk.Versions.Any (IsNetCoreSdk21OrHigher);
/// <summary>
- /// This checks for .NET Core SDK 2.1 to be installed. Note that the
- /// .NET Core SDK versions is confusing. Here we want the .NET Core 2.1
+ /// This checks for .NET Core SDK 2.1 or higher to be installed. Note that the
+ /// .NET Core SDK versions is confusing. Here we want at least the .NET Core 2.1
/// SDK that supports .NET Core App 2.1. Not the .NET Core 2.1 SDK that
/// supports .NET Core App 2.0 only.
/// </summary>
- static bool IsNetCoreSdk21 (DotNetCoreVersion version)
- {
- return version.Major == 2 && version.Minor == 1 && version.Patch >= 300;
- }
+ static bool IsNetCoreSdk21OrHigher (DotNetCoreVersion version) => version >= MinimumCoreSDK;
public static async Task TrustDevelopmentCertificate (ProgressMonitor monitor)
{
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 a91a288055..f7ce13dbca 100644
--- a/main/src/addins/MonoDevelop.AspNetCore/Properties/MonoDevelop.AspNetCore.addin.xml
+++ b/main/src/addins/MonoDevelop.AspNetCore/Properties/MonoDevelop.AspNetCore.addin.xml
@@ -79,7 +79,7 @@
For example, .NET Core 1.1 SDK does not have a Razor template so having the 1.1 templates first
would cause the Razor template to be last in the New Project dialog if both 1.1 and 2.x templates
are available. -->
- <Condition id="AspNetCoreSdkInstalled" sdkVersion="3.0">
+ <Condition id="AspNetCoreSdkInstalled" sdkVersion="3.0">
<Template
id="Microsoft.Web.Empty.CSharp"
templateId="Microsoft.Web.Empty.CSharp.3.0"
@@ -169,6 +169,19 @@
category="netcore/app/aspnet"
formatExclude="*.min.css|*.min.js|*.map"
defaultParameters="IncludeLaunchSettings=true" />
+ <Template
+ id="Microsoft.Web.Razor.Library.CSharp"
+ templateId="Microsoft.Web.Razor.Library.CSharp.3.0"
+ _overrideName="Razor Class Library"
+ _overrideDescription="A project for creating a Razor class library that targets .NET Standard"
+ path="${DotNetCoreSdk.3.0.Templates.Web.ProjectTemplates.nupkg}"
+ icon="md-netcore-empty-project"
+ imageId="md-netcore-empty-project"
+ wizard="MonoDevelop.DotNetCore.ProjectTemplateWizard"
+ condition="UseNetCore30=true"
+ category="netcore/app/aspnet"
+ formatExclude="*.min.css|*.min.js|*.map"
+ defaultParameters="IncludeLaunchSettings=true" />
</Condition>
<Condition id="AspNetCoreSdkInstalled" sdkVersion="2.2">
<Template
@@ -260,6 +273,19 @@
category="netcore/app/aspnet"
formatExclude="*.min.css|*.min.js|*.map"
defaultParameters="IncludeLaunchSettings=true" />
+ <Template
+ id="Microsoft.Web.Razor.Library.CSharp"
+ templateId="Microsoft.Web.Razor.Library.CSharp.2.2"
+ _overrideName="Razor Class Library"
+ _overrideDescription="A project for creating a Razor class library that targets .NET Standard"
+ path="${DotNetCoreSdk.2.2.Templates.Web.ProjectTemplates.nupkg}"
+ icon="md-netcore-empty-project"
+ imageId="md-netcore-empty-project"
+ wizard="MonoDevelop.DotNetCore.ProjectTemplateWizard"
+ condition="UseNetCore22=true"
+ category="netcore/app/aspnet"
+ formatExclude="*.min.css|*.min.js|*.map"
+ defaultParameters="IncludeLaunchSettings=true" />
</Condition>
<Condition id="AspNetCoreSdkInstalled" sdkVersion="2.1">
<Template
@@ -351,6 +377,19 @@
category="netcore/app/aspnet"
formatExclude="*.min.css|*.min.js|*.map"
defaultParameters="IncludeLaunchSettings=true" />
+ <Template
+ id="Microsoft.Web.Razor.Library.CSharp"
+ templateId="Microsoft.Web.Razor.Library.CSharp.2.1"
+ _overrideName="Razor Class Library"
+ _overrideDescription="A project for creating a Razor class library that targets .NET Standard"
+ path="${DotNetCoreSdk.2.1.Templates.Web.ProjectTemplates.nupkg}"
+ icon="md-netcore-empty-project"
+ imageId="md-netcore-empty-project"
+ wizard="MonoDevelop.DotNetCore.ProjectTemplateWizard"
+ condition="UseNetCore21=true"
+ category="netcore/app/aspnet"
+ formatExclude="*.min.css|*.min.js|*.map"
+ defaultParameters="IncludeLaunchSettings=true" />
</Condition>
<Condition id="AspNetCoreSdkInstalled" sdkVersion="2.0">
<Template
diff --git a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewImportsPage.xft.xml b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewImportsPage.xft.xml
index 8393e4a536..9b1002de01 100644
--- a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewImportsPage.xft.xml
+++ b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewImportsPage.xft.xml
@@ -14,7 +14,10 @@
</TemplateConfiguration>
<Conditions>
- <AspNetCore />
+ <Or>
+ <AspNetCore />
+ <ProjectCapability Name="DotNetCoreRazor"/>
+ </Or>
</Conditions>
<!-- Template Content -->
diff --git a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewLayoutPage.xft.xml b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewLayoutPage.xft.xml
index 5fbc33c8f3..dd332cb77b 100644
--- a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewLayoutPage.xft.xml
+++ b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewLayoutPage.xft.xml
@@ -14,7 +14,10 @@
</TemplateConfiguration>
<Conditions>
- <AspNetCore />
+ <Or>
+ <AspNetCore />
+ <ProjectCapability Name="DotNetCoreRazor"/>
+ </Or>
</Conditions>
<!-- Template Content -->
diff --git a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewPage.xft.xml b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewPage.xft.xml
index 39106f6040..3ba1cd42df 100644
--- a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewPage.xft.xml
+++ b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewPage.xft.xml
@@ -14,7 +14,10 @@
</TemplateConfiguration>
<Conditions>
- <AspNetCore />
+ <Or>
+ <AspNetCore />
+ <ProjectCapability Name="DotNetCoreRazor"/>
+ </Or>
</Conditions>
<!-- Template Content -->
diff --git a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewStartPage.xft.xml b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewStartPage.xft.xml
index 9615880eae..b7306129ec 100644
--- a/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewStartPage.xft.xml
+++ b/main/src/addins/MonoDevelop.AspNetCore/Templates/MVCViewStartPage.xft.xml
@@ -14,7 +14,10 @@
</TemplateConfiguration>
<Conditions>
- <AspNetCore />
+ <Or>
+ <AspNetCore />
+ <ProjectCapability Name="DotNetCoreRazor"/>
+ </Or>
</Conditions>
<!-- Template Content -->
diff --git a/main/src/addins/MonoDevelop.AspNetCore/Templates/RazorPage.xft.xml b/main/src/addins/MonoDevelop.AspNetCore/Templates/RazorPage.xft.xml
index 68fce01577..30ddd41fc5 100644
--- a/main/src/addins/MonoDevelop.AspNetCore/Templates/RazorPage.xft.xml
+++ b/main/src/addins/MonoDevelop.AspNetCore/Templates/RazorPage.xft.xml
@@ -14,7 +14,10 @@
</TemplateConfiguration>
<Conditions>
- <AspNetCore minVersion="2.0"/>
+ <Or>
+ <AspNetCore minVersion="2.0"/>
+ <ProjectCapability Name="DotNetCoreRazor"/>
+ </Or>
</Conditions>
<!-- Template Content -->
diff --git a/main/src/addins/MonoDevelop.AspNetCore/Templates/RazorPageWithPageModel.xft.xml b/main/src/addins/MonoDevelop.AspNetCore/Templates/RazorPageWithPageModel.xft.xml
index a2db23ea8e..dcd7c8fc53 100644
--- a/main/src/addins/MonoDevelop.AspNetCore/Templates/RazorPageWithPageModel.xft.xml
+++ b/main/src/addins/MonoDevelop.AspNetCore/Templates/RazorPageWithPageModel.xft.xml
@@ -14,7 +14,10 @@
</TemplateConfiguration>
<Conditions>
- <AspNetCore minVersion="2.0" />
+ <Or>
+ <AspNetCore minVersion="2.0"/>
+ <ProjectCapability Name="DotNetCoreRazor"/>
+ </Or>
</Conditions>
<!-- Template Content -->
diff --git a/main/src/addins/MonoDevelop.AspNetCore/Templates/RazorTagHelper.xft.xml b/main/src/addins/MonoDevelop.AspNetCore/Templates/RazorTagHelper.xft.xml
index 637686310e..42562c570f 100644
--- a/main/src/addins/MonoDevelop.AspNetCore/Templates/RazorTagHelper.xft.xml
+++ b/main/src/addins/MonoDevelop.AspNetCore/Templates/RazorTagHelper.xft.xml
@@ -14,7 +14,10 @@
</TemplateConfiguration>
<Conditions>
- <AspNetCore />
+ <Or>
+ <AspNetCore />
+ <ProjectCapability Name="DotNetCoreRazor"/>
+ </Or>
</Conditions>
<!-- Template Content -->
diff --git a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/packages.config b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/packages.config
deleted file mode 100644
index 5f282702bb..0000000000
--- a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/packages.config
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/AddinInfo.cs b/main/src/addins/MonoDevelop.DesignerSupport/AddinInfo.cs
index 3fa48ba6ac..60adee7d2d 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/AddinInfo.cs
+++ b/main/src/addins/MonoDevelop.DesignerSupport/AddinInfo.cs
@@ -14,3 +14,8 @@ using Mono.Addins.Description;
[assembly:AddinDependency ("Core", MonoDevelop.BuildInfo.Version)]
[assembly:AddinDependency ("Ide", MonoDevelop.BuildInfo.Version)]
+
+#if MAC
+[assembly: ImportAddinAssembly ("Xamarin.PropertyEditing.dll")]
+[assembly: ImportAddinAssembly ("Xamarin.PropertyEditing.Mac.dll")]
+#endif
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/Styles.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/Styles.cs
index 6b62628491..0963655a61 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/Styles.cs
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/Styles.cs
@@ -1,4 +1,4 @@
-#if MAC
+#if MAC
using AppKit;
using MonoDevelop.Ide;
using Xamarin.PropertyEditing.Mac;
@@ -29,14 +29,12 @@ namespace MonoDevelop.DesignerSupport
public static void LoadStyles ()
{
if (IdeApp.Preferences.UserInterfaceTheme == Theme.Light) {
- PropertyEditorPanel.ThemeManager.Theme = Xamarin.PropertyEditing.Themes.PropertyEditorTheme.Light;
HeaderBackgroundColor = NSColor.FromRgb (0.98f, 0.98f, 0.98f);
HeaderBorderBackgroundColor = NSColor.FromRgb (0.96f, 0.96f, 0.96f);
LabelSelectedForegroundColor = NSColor.Highlight;
ToolbarBackgroundColor = NSColor.White;
CellBackgroundSelectedColor = NSColor.FromRgb (0.36f, 0.54f, 0.90f);
} else {
- PropertyEditorPanel.ThemeManager.Theme = Xamarin.PropertyEditing.Themes.PropertyEditorTheme.Dark;
CellBackgroundSelectedColor = NSColor.FromRgb (0.38f, 0.55f, 0.91f);
HeaderBackgroundColor = NSColor.FromRgb (0.29f, 0.29f, 0.29f);
HeaderBorderBackgroundColor = NSColor.FromRgb (0.29f, 0.29f, 0.29f);
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.csproj b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.csproj
index 27cb32a163..86aa268f00 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.csproj
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.csproj
@@ -144,6 +144,7 @@
<Compile Include="MonoDevelop.DesignerSupport\NativePropertyEditors\PropertyInfo\DirectoryPathPropertyInfo.cs" />
<Compile Include="MonoDevelop.DesignerSupport\IPropertyPad.cs" />
<Compile Include="MonoDevelop.DesignerSupport\NativePropertyEditors\PropertyInfo\FlagDescriptorPropertyInfo.cs" />
+ <Compile Include="MonoDevelop.DesignerSupport\NativePropertyEditors\PropertyPadItem.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="MonoDevelop.DesignerSupport.addin.xml" />
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/MacPropertyGrid.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/MacPropertyGrid.cs
index de3512f570..29d0001577 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/MacPropertyGrid.cs
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/MacPropertyGrid.cs
@@ -116,15 +116,15 @@ namespace MonoDevelop.DesignerSupport
}
}
- Tuple<object, object []> currentSelectedObject;
+ PropertyPadItem currentSelectedObject;
public void SetCurrentObject (object lastComponent, object [] propertyProviders)
{
if (lastComponent != null) {
- var selection = new Tuple<object, object []> (lastComponent, propertyProviders);
+ var selection = new PropertyPadItem (lastComponent, propertyProviders);
if (currentSelectedObject != selection) {
propertyEditorPanel.SelectedItems.Clear ();
- propertyEditorPanel.SelectedItems.Add (new Tuple<object, object []> (lastComponent, propertyProviders));
+ propertyEditorPanel.SelectedItems.Add (selection);
currentSelectedObject = selection;
}
}
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/DirectoryPathPropertyInfo.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/DirectoryPathPropertyInfo.cs
index 6a070d80c1..6de957d826 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/DirectoryPathPropertyInfo.cs
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/DirectoryPathPropertyInfo.cs
@@ -24,7 +24,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#if MAC
+#if MAC && false
using System;
using System.Threading.Tasks;
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/FilePathPropertyInfo.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/FilePathPropertyInfo.cs
index 563c5eee6b..393416929a 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/FilePathPropertyInfo.cs
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/FilePathPropertyInfo.cs
@@ -40,11 +40,11 @@ namespace MonoDevelop.DesignerSupport
{
}
- public override Type Type => typeof (FilePath);
+ public override Type Type => typeof (Xamarin.PropertyEditing.Common.FilePath);
internal override void SetValue<T> (object target, T value)
{
- if (value is FilePath filePath) {
+ if (value is Xamarin.PropertyEditing.Common.FilePath filePath) {
PropertyDescriptor.SetValue (PropertyProvider, new MonoDevelop.Core.FilePath (filePath.Source));
} else {
throw new Exception (string.Format ("Value: {0} of type {1} is not a DirectoryPath", value, value.GetType ()));
@@ -53,8 +53,8 @@ namespace MonoDevelop.DesignerSupport
internal override Task<T> GetValueAsync<T> (object target)
{
- if (target is Core.FilePath directoryPath) {
- T result = (T)(object)new FilePath (directoryPath.FullPath);
+ if (target is MonoDevelop.Core.FilePath directoryPath) {
+ T result = (T)(object)new Xamarin.PropertyEditing.Common.FilePath (directoryPath.FullPath);
return Task.FromResult (result);
}
Core.LoggingService.LogWarning ("Value: {0} of type {1} is not a DirectoryPath", target, target.GetType ());
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadEditorProvider.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadEditorProvider.cs
index 1d74baaf33..8752869230 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadEditorProvider.cs
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadEditorProvider.cs
@@ -41,19 +41,14 @@ namespace MonoDevelop.DesignerSupport
class PropertyPadEditorProvider
: IEditorProvider
{
- Tuple<object, object[]> currentObject;
- IObjectEditor currentEditor;
-
public IReadOnlyDictionary<Type, ITypeInfo> KnownTypes {
get;
} = new Dictionary<Type, ITypeInfo> ();
public Task<IObjectEditor> GetObjectEditorAsync (object item)
{
- if (item is Tuple<object, object []> tuple) {
- this.currentObject = tuple;
- this.currentEditor = new PropertyPadObjectEditor (tuple); ;
- return Task.FromResult (currentEditor);
+ if (item is PropertyPadItem propertyPadItem) {
+ return Task.FromResult<IObjectEditor> (new PropertyPadObjectEditor (propertyPadItem));
}
return Task.FromResult<IObjectEditor> (null);
}
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadItem.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadItem.cs
new file mode 100644
index 0000000000..ecd5235fd8
--- /dev/null
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadItem.cs
@@ -0,0 +1,69 @@
+//
+// PropertyPadItem.cs
+//
+// Author:
+// jmedrano <josmed@microsoft.com>
+//
+// Copyright (c) 2018
+//
+// 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.
+
+#if MAC
+
+using System;
+using System.Threading.Tasks;
+using MonoDevelop.Core;
+using Xamarin.PropertyEditing;
+
+namespace MonoDevelop.DesignerSupport
+{
+ class PropertyPadItem
+ {
+ public PropertyPadItem (object target, object [] providers)
+ {
+ Target = target;
+ Providers = providers;
+ }
+
+ public object Target { get; }
+ public object[] Providers { get; }
+
+ public async Task<ValueInfo<T>> GetPropertyValueInfoAsProppyType<T> (DescriptorPropertyInfo propertyInfo)
+ {
+ T value = await propertyInfo.GetValueAsync<T> (this);
+ return new ValueInfo<T> {
+ Value = value,
+ Source = ValueSource.Local,
+ //ValueDescriptor = valueInfoString.ValueDescriptor,
+ //CustomExpression = valueString
+ };
+ }
+
+ public void SetPropertyValueInfoAsProppyType<T> (DescriptorPropertyInfo info, ValueInfo<T> value, PropertyVariation variations)
+ {
+ try {
+ info.SetValue (this, value.Value);
+ } catch (Exception ex) {
+ LoggingService.LogError ("Error setting the value", ex);
+ }
+ }
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadObjectEditor.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadObjectEditor.cs
index 40fa6dc49a..c272b78a4a 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadObjectEditor.cs
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadObjectEditor.cs
@@ -39,9 +39,9 @@ using MonoDevelop.Core;
namespace MonoDevelop.DesignerSupport
{
class PropertyPadObjectEditor
- : IObjectEditor, INameableObject, IObjectEventEditor
+ : IObjectEditor, INameableObject
{
- private readonly object target;
+ private readonly PropertyPadItem propertyItem;
public string Name {
get;
private set;
@@ -51,7 +51,7 @@ namespace MonoDevelop.DesignerSupport
private static readonly IObjectEditor [] EmptyDirectChildren = new IObjectEditor [0];
private readonly List<PropertyDescriptorEventInfo> events = new List<PropertyDescriptorEventInfo> ();
- public object Target => this.target;
+ public object Target => this.propertyItem;
public ITypeInfo TargetType => ToTypeInfo (Target.GetType ());
@@ -65,7 +65,7 @@ namespace MonoDevelop.DesignerSupport
public IReadOnlyDictionary<IPropertyInfo, KnownProperty> KnownProperties => null;
- public IObjectEditor Parent => throw new NotImplementedException ();
+ public IObjectEditor Parent => null;
public IReadOnlyList<IObjectEditor> DirectChildren => EmptyDirectChildren;
@@ -73,10 +73,10 @@ namespace MonoDevelop.DesignerSupport
public event EventHandler<EditorPropertyChangedEventArgs> PropertyChanged;
- public PropertyPadObjectEditor (Tuple<object, object []> target)
+ public PropertyPadObjectEditor (PropertyPadItem propertyItem)
{
- this.target = target.Item1;
- foreach (object propertyProvider in target.Item2) {
+ this.propertyItem = propertyItem;
+ foreach (object propertyProvider in propertyItem.Providers) {
var props = GetProperties (propertyProvider, null);
for (int i = 0; i < props.Count; i++) {
@@ -118,10 +118,10 @@ namespace MonoDevelop.DesignerSupport
}
if (propertyDescriptor.PropertyType.IsAssignableFrom (typeof (Core.FilePath))) {
- var isDirectoryPropertyDescriptor = GetPropertyDescriptor (propertyDescriptor.GetChildProperties (), nameof (Core.FilePath.IsDirectory));
- if (isDirectoryPropertyDescriptor != null && (bool)isDirectoryPropertyDescriptor.GetValue (target)) {
- return new DirectoryPathPropertyInfo (propertyDescriptor, PropertyProvider, valueSources);
- }
+ //var isDirectoryPropertyDescriptor = GetPropertyDescriptor (propertyDescriptor.GetChildProperties (), nameof (Core.FilePath.IsDirectory));
+ //if (isDirectoryPropertyDescriptor != null && (bool)isDirectoryPropertyDescriptor.GetValue (propertyItem)) {
+ // return new DirectoryPathPropertyInfo (propertyDescriptor, PropertyProvider, valueSources);
+ //}
return new FilePathPropertyInfo (propertyDescriptor, PropertyProvider, valueSources);
}
@@ -139,20 +139,6 @@ namespace MonoDevelop.DesignerSupport
return TypeDescriptor.GetProperties (component);
}
- #region NOT SUPORTED
-
- public Task AttachHandlerAsync (IEventInfo ev, string handlerName)
- {
- throw new NotImplementedException ();
- }
-
- public Task DetachHandlerAsync (IEventInfo ev, string handlerName)
- {
- throw new NotImplementedException ();
- }
-
- #endregion
-
public async Task<AssignableTypesResult> GetAssignableTypesAsync (IPropertyInfo property, bool childTypes)
{
return new AssignableTypesResult (Array.Empty<ITypeInfo> ());
@@ -166,7 +152,7 @@ namespace MonoDevelop.DesignerSupport
if (!(ev is Xamarin.PropertyEditing.Reflection.ReflectionEventInfo info))
throw new ArgumentException ();
- return Task.FromResult (info.GetHandlers (this.target));
+ return Task.FromResult (info.GetHandlers (this.propertyItem));
}
public Task<string> GetNameAsync ()
@@ -184,17 +170,10 @@ namespace MonoDevelop.DesignerSupport
if (property == null)
throw new ArgumentNullException (nameof (property));
- if (!(property is DescriptorPropertyInfo info))
- throw new ArgumentException ();
-
- T value = await info.GetValueAsync<T> (this.target);
+ if (!(property is DescriptorPropertyInfo propertyInfo))
+ throw new ArgumentException ("Property should be a DescriptorPropertyInfo", nameof (property));
- return new ValueInfo<T> {
- Value = value,
- Source = ValueSource.Local,
- //ValueDescriptor = valueInfoString.ValueDescriptor,
- //CustomExpression = valueString
- };
+ return await propertyItem.GetPropertyValueInfoAsProppyType<T> (propertyInfo);
}
public Task RemovePropertyVariantAsync (IPropertyInfo property, PropertyVariation variant)
@@ -208,21 +187,19 @@ namespace MonoDevelop.DesignerSupport
return Task.FromResult (true);
}
- public Task SetValueAsync<T> (IPropertyInfo propertyInfo, ValueInfo<T> valueInfo, PropertyVariation variations = null)
+ public Task SetValueAsync<T> (IPropertyInfo propertyInfo, ValueInfo<T> value, PropertyVariation variations = null)
{
if (propertyInfo == null)
throw new ArgumentNullException (nameof (propertyInfo));
if (propertyInfo is DescriptorPropertyInfo info && info.CanWrite) {
- try {
- info.SetValue (this.target, valueInfo.Value);
- } catch (Exception ex) {
- LoggingService.LogError ("Error setting the value", ex);
- }
+
+ propertyItem.SetPropertyValueInfoAsProppyType (info, value, variations);
OnPropertyChanged (info);
+ return Task.CompletedTask;
}
- return Task.CompletedTask;
+ throw new ArgumentException ($"Property should be a writeable {nameof (DescriptorPropertyInfo)}.", nameof (propertyInfo));
}
protected virtual void OnPropertyChanged (IPropertyInfo property)
diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateTests.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateTests.cs
index 7a51d6a7f7..4522ea3c8e 100644
--- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateTests.cs
+++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateTests.cs
@@ -271,6 +271,7 @@ namespace MonoDevelop.DotNetCore.Tests
[TestCase ("Microsoft.Web.RazorPages.CSharp", "UseNetCore21=true")]
[TestCase ("Microsoft.Web.WebApi.CSharp", "UseNetCore21=true")]
[TestCase ("Microsoft.Web.WebApi.FSharp", "UseNetCore21=true")]
+ [TestCase ("Microsoft.Web.Razor.Library.CSharp", "UseNetCore21=true")]
public async Task AspNetCore21 (string templateId, string parameters)
{
if (!IsDotNetCoreSdk21Installed ()) {
@@ -287,6 +288,7 @@ namespace MonoDevelop.DotNetCore.Tests
[TestCase ("Microsoft.Web.RazorPages.CSharp", "UseNetCore22=true")]
[TestCase ("Microsoft.Web.WebApi.CSharp", "UseNetCore22=true")]
[TestCase ("Microsoft.Web.WebApi.FSharp", "UseNetCore22=true")]
+ [TestCase ("Microsoft.Web.Razor.Library.CSharp", "UseNetCore22=true")]
public async Task AspNetCore22 (string templateId, string parameters)
{
if (!IsDotNetCoreSdk22Installed ()) {
@@ -304,6 +306,7 @@ namespace MonoDevelop.DotNetCore.Tests
[TestCase ("Microsoft.Web.RazorPages.CSharp", "UseNetCore30=true")]
[TestCase ("Microsoft.Web.WebApi.CSharp", "UseNetCore30=true")]
[TestCase ("Microsoft.Web.WebApi.FSharp", "UseNetCore30=true")]
+ [TestCase ("Microsoft.Web.Razor.Library.CSharp", "UseNetCore30=true")]
public async Task AspNetCore30 (string templateId, string parameters)
{
if (!IsDotNetCoreSdk30Installed ()) {
diff --git a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.csproj b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.csproj
index d1da520ca1..bc0bde87a3 100644
--- a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.csproj
+++ b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.csproj
@@ -7,7 +7,7 @@
<ProjectGuid>{443311BF-766D-4863-B5A1-AFAA7F41DBDA}</ProjectGuid>
<TargetFrameworkVersion>$(MDFrameworkVersion)</TargetFrameworkVersion>
<OutputPath>..\..\..\build\AddIns\MonoDevelop.Packaging</OutputPath>
- <_BuildPackagingVersion>0.2.0</_BuildPackagingVersion>
+ <_BuildPackagingVersion>0.2.5-dev.8</_BuildPackagingVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' " />
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
diff --git a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/DotNetProjectExtensions.cs b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/DotNetProjectExtensions.cs
index 8f6eb98264..b973cfecd6 100644
--- a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/DotNetProjectExtensions.cs
+++ b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/DotNetProjectExtensions.cs
@@ -70,7 +70,7 @@ namespace MonoDevelop.Packaging
public static void InstallBuildPackagingNuGetPackage (IEnumerable<Project> projects)
{
string packagesFolder = GetPackagesFolder ();
- var packageReference = new PackageManagementPackageReference ("NuGet.Build.Packaging", "0.2.0");
+ var packageReference = new PackageManagementPackageReference ("NuGet.Build.Packaging", "0.2.5-dev.8");
var packageReferences = new [] { packageReference };
diff --git a/main/src/addins/MonoDevelop.Packaging/Templates/CrossPlatformLibrary.xpt.xml b/main/src/addins/MonoDevelop.Packaging/Templates/CrossPlatformLibrary.xpt.xml
index 2bfa014101..bbc1befa97 100644
--- a/main/src/addins/MonoDevelop.Packaging/Templates/CrossPlatformLibrary.xpt.xml
+++ b/main/src/addins/MonoDevelop.Packaging/Templates/CrossPlatformLibrary.xpt.xml
@@ -29,7 +29,7 @@
DefaultNamespace="${ProjectName}"
HideGettingStarted="true" />
<Packages>
- <Package ID="NuGet.Build.Packaging" Version="0.2.0" directory="../packages" />
+ <Package ID="NuGet.Build.Packaging" Version="0.2.5-dev.8" directory="../packages" />
</Packages>
<Files>
<FileTemplateReference TemplateID="EmptyClass" name="MyClass.cs" />
@@ -50,7 +50,7 @@
<Reference type="Project" refto="${ProjectName}.Shared" />
</References>
<Packages>
- <Package ID="NuGet.Build.Packaging" Version="0.2.0" directory="../packages" />
+ <Package ID="NuGet.Build.Packaging" Version="0.2.5-dev.8" directory="../packages" />
</Packages>
<Files>
<FileTemplateReference TemplateID="CSharpAssemblyInfo" name="AssemblyInfo.cs" />
@@ -67,7 +67,7 @@
<Reference type="Project" refto="${ProjectName}.Shared" />
</References>
<Packages>
- <Package ID="NuGet.Build.Packaging" Version="0.2.0" directory="../packages" />
+ <Package ID="NuGet.Build.Packaging" Version="0.2.5-dev.8" directory="../packages" />
</Packages>
<Files>
<FileTemplateReference TemplateID="CSharpAssemblyInfo" name="AssemblyInfo.cs" />
@@ -77,7 +77,7 @@
<Project name="${ProjectName}.NuGet" directory="${ProjectName}.NuGet" type="NuGetPackaging" if="CreateNuGetProject">
<Options TargetFrameworkVersion="4.5" DefaultNamespace="${ProjectName}" HideGettingStarted="true" />
<Packages>
- <Package ID="NuGet.Build.Packaging" Version="0.2.0" directory="../packages" />
+ <Package ID="NuGet.Build.Packaging" Version="0.2.5-dev.8" directory="../packages" />
</Packages>
<References>
<Reference type="Project" refto="${ProjectName}.Android" if="CreateAndroidProject" />
diff --git a/main/src/addins/MonoDevelop.Packaging/Templates/PackagingProject.xpt.xml b/main/src/addins/MonoDevelop.Packaging/Templates/PackagingProject.xpt.xml
index e5d699884f..82dbbd1fc5 100644
--- a/main/src/addins/MonoDevelop.Packaging/Templates/PackagingProject.xpt.xml
+++ b/main/src/addins/MonoDevelop.Packaging/Templates/PackagingProject.xpt.xml
@@ -18,7 +18,7 @@
<Project name="${ProjectName}" directory="." type="NuGetPackaging">
<Options TargetFrameworkVersion="4.5" />
<Packages>
- <Package ID="NuGet.Build.Packaging" Version="0.2.0" directory="../packages" />
+ <Package ID="NuGet.Build.Packaging" Version="0.2.5-dev.8" directory="../packages" />
</Packages>
<Files>
<File name="readme.txt"><![CDATA[
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs
index 38dd1c42a4..3da12a678e 100644
--- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs
+++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs
@@ -186,7 +186,18 @@ namespace MonoDevelop.CodeActions
{
Runtime.AssertMainThread ();
var caretOffset = Editor.CaretOffset;
- return collections.Select (c => FilterOnUIThread (c, workspace)).Where(x => x != null).OrderBy(x => GetDistance (x, caretOffset)).ToImmutableArray ();
+ var builder = ImmutableArray.CreateBuilder<CodeFixCollection> (collections.Length);
+ var ids = new HashSet<string> ();
+ foreach (var c in collections) {
+ if (!ids.Add (c.FirstDiagnostic.Id))
+ continue;
+ var filtered = FilterOnUIThread (c, workspace);
+ if (filtered == null)
+ continue;
+ builder.Add (filtered);
+ }
+ builder.Sort ((x, y) => GetDistance (x, caretOffset).CompareTo (GetDistance (y, caretOffset)));
+ return builder.ToImmutableArray ();
}
static int GetDistance (CodeFixCollection fixCollection, int caretOffset)
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskOverviewMode.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskOverviewMode.cs
index 6af63e47b2..87836059be 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskOverviewMode.cs
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskOverviewMode.cs
@@ -86,14 +86,14 @@ namespace MonoDevelop.SourceEditor.QuickTasks
get {
return okImage;
}
- }
-
- Cairo.Color win81Slider;
+ }
+
+ Cairo.Color win81Slider;
Cairo.Color win81SliderPrelight;
int win81ScrollbarWidth;
- protected override void OnStyleSet (Style previous_style)
- {
+ protected override void OnStyleSet (Style previous_style)
+ {
base.OnStyleSet (previous_style);
if (Core.Platform.IsWindows) {
using (var scrollstyle = Rc.GetStyleByPaths (Settings, null, null, VScrollbar.GType)) {
@@ -228,7 +228,7 @@ namespace MonoDevelop.SourceEditor.QuickTasks
}
void DestroyBackgroundSurface ()
- {
+ {
if (backgroundSurface != null) {
backgroundSurface.Dispose ();
backgroundSurface = null;
@@ -1002,20 +1002,20 @@ namespace MonoDevelop.SourceEditor.QuickTasks
}
void IndicatorSurfaceTimeoutHandler (bool forceUpdate)
- {
- indicatorIdleTimout = 0;
- if (!IsRealized)
- return;
- var allocation = Allocation;
- src?.Cancel ();
- src = new CancellationTokenSource ();
- new IdleUpdater (this, src.Token) { ForceUpdate = forceUpdate }.Start ();
+ {
+ indicatorIdleTimout = 0;
+ if (!IsRealized)
+ return;
+ var allocation = Allocation;
+ src?.Cancel ();
+ src = new CancellationTokenSource ();
+ new IdleUpdater (this, src.Token) { ForceUpdate = forceUpdate }.Start ();
}
void RemoveIndicatorIdleHandler ()
{
+ src?.Cancel ();
if (indicatorIdleTimout > 0) {
- src?.Cancel ();
GLib.Source.Remove (indicatorIdleTimout);
indicatorIdleTimout = 0;
}
@@ -1415,8 +1415,8 @@ namespace MonoDevelop.SourceEditor.QuickTasks
public QuickTaskAccessible (QuickTaskStrip parent, QuickTaskOverviewMode parentMode, QuickTask t) : this (parent, parentMode)
{
task = t;
- usage = null;
-
+ usage = null;
+
var line = mode.TextEditor.OffsetToLineNumber (t.Location);
Accessible.Title = t.Description;
Accessible.Help = string.Format (GettextCatalog.GetString ("Jump to line {0}"), line.ToString ());
diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/MonoDevelop.TextEditor.csproj b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/MonoDevelop.TextEditor.csproj
index 30e59d1313..c728874351 100644
--- a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/MonoDevelop.TextEditor.csproj
+++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/MonoDevelop.TextEditor.csproj
@@ -18,7 +18,7 @@
<InternalsVisibleTo Include="MonoDevelop.TextEditor.Wpf" />
<Reference Include="PresentationFramework" />
<Reference Include="PresentationCore" />
- <ProjectReference Include="..\..\MonoDevelop.DesignerSupport\MonoDevelop.DesignerSupport.csproj" />
+ <ProjectReference Include="..\..\MonoDevelop.DesignerSupport\MonoDevelop.DesignerSupport.csproj" Private="false" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\..\external\vs-editor-core\src\Editor\Text\Impl\BaseViewImpl\VacuousTextDataModel.cs" Link="Util\VacuousTextDataModel.cs" />
diff --git a/main/src/addins/PerformanceDiagnostics/PerformanceDiagnostics/Commands.cs b/main/src/addins/PerformanceDiagnostics/PerformanceDiagnostics/Commands.cs
index b82de9cb12..852c472a20 100644
--- a/main/src/addins/PerformanceDiagnostics/PerformanceDiagnostics/Commands.cs
+++ b/main/src/addins/PerformanceDiagnostics/PerformanceDiagnostics/Commands.cs
@@ -25,6 +25,12 @@ namespace PerformanceDiagnosticsAddIn
public class ProfileFor5SecondsHandler : CommandHandler
{
+ protected override void Update (CommandInfo info)
+ {
+ info.DisableOnShellLock = false;
+ base.Update (info);
+ }
+
protected override void Run ()
{
UIThreadMonitor.Instance.Profile (5);
@@ -46,6 +52,7 @@ namespace PerformanceDiagnosticsAddIn
protected override void Update(CommandInfo info)
{
info.Checked = UIThreadMonitor.Instance.ToggleProfilingChecked;
+ info.DisableOnShellLock = false;
base.Update(info);
}
diff --git a/main/src/addins/PerformanceDiagnostics/PerformanceDiagnostics/UIThreadMonitor.cs b/main/src/addins/PerformanceDiagnostics/PerformanceDiagnostics/UIThreadMonitor.cs
index cfa5c6c497..894fee35d9 100644
--- a/main/src/addins/PerformanceDiagnostics/PerformanceDiagnostics/UIThreadMonitor.cs
+++ b/main/src/addins/PerformanceDiagnostics/PerformanceDiagnostics/UIThreadMonitor.cs
@@ -210,7 +210,11 @@ namespace PerformanceDiagnosticsAddIn
internal static void ConvertJITAddressesToMethodNames (string fileName, string profilingType)
{
+ // sample line to replace:
+ // ??? (in <unknown binary>) [0x103648455]
var rx = new Regex (@"\?\?\? \(in <unknown binary>\) \[0x([0-9a-f]+)\]", RegexOptions.Compiled);
+
+
if (File.Exists (fileName) && new FileInfo (fileName).Length > 0) {
Directory.CreateDirectory (Options.OutputPath);
var outputFilename = Path.Combine (Options.OutputPath, $"{BrandingService.ApplicationName}_{profilingType}_{DateTime.Now:yyyy-MM-dd__HH-mm-ss}.txt");
@@ -219,14 +223,18 @@ namespace PerformanceDiagnosticsAddIn
using (var sw = new StreamWriter (outputFilename)) {
string line;
while ((line = sr.ReadLine ()) != null) {
- if (rx.IsMatch (line)) {
- var match = rx.Match (line);
+
+ var match = rx.Match (line);
+ if (match.Success) {
var offset = long.Parse (match.Groups [1].Value, NumberStyles.HexNumber);
- string pmipMethodName;
- if (!methodsCache.TryGetValue (offset, out pmipMethodName)) {
+
+ if (!methodsCache.TryGetValue (offset, out var pmipMethodName)) {
pmipMethodName = mono_pmip (offset)?.TrimStart ();
+ if (pmipMethodName != null)
+ pmipMethodName = PmipParser.ToSample (pmipMethodName, offset);
methodsCache.Add (offset, pmipMethodName);
}
+
if (pmipMethodName != null) {
line = line.Remove (match.Index, match.Length);
line = line.Insert (match.Index, pmipMethodName);
@@ -238,6 +246,95 @@ namespace PerformanceDiagnosticsAddIn
}
}
+ static class PmipParser
+ {
+ // pmip output:
+ // (wrapper managed-to-native) Gtk.Application:gtk_main () [{0x7f968e48d1e8} + 0xdf] (0x122577d50 0x122577f28) [0x7f9682702c90 - MonoDevelop.exe]
+ // MonoDevelop.Startup.MonoDevelopMain:Main (string[]) [{0x7faef5700948} + 0x93] [/Users/therzok/Work/md/monodevelop/main/src/core/MonoDevelop.Startup/MonoDevelop.Startup/MonoDevelopMain.cs :: 39u] (0x10e7609c0 0x10e760aa8) [0x7faef7002d80 - MonoDevelop.exe]
+
+ // sample symbolified line:
+ // start (in libdyld.dylib) + 1 [0x7fff79c7ded9]
+ // mono_hit_runtime_invoke (in mono64) + 1619 [0x102f90083] mini-runtime.c:3148
+ public static string ToSample (string initialInput, long offset)
+ {
+ try {
+ var input = initialInput.AsSpan ();
+ var sb = new StringBuilder ();
+ string filename = null;
+
+ // Cut off wrapper part.
+ if (input.StartsWith ("(wrapper".AsSpan ())) {
+ input = input.Slice (input.IndexOf (')') + 1).TrimStart ();
+ }
+
+ // If it starts with <Module>:, trim it.
+ if (input.StartsWith ("<Module>:".AsSpan ())) {
+ input = input.Slice ("<Module>:".Length);
+ }
+
+ // Usually a generic trampoline marker, don't bother parsing.
+ if (input[0] == '<')
+ return input.ToString ();
+
+ // Decode method signature
+ // Gtk.Application:gtk_main () [{0x7f968e48d1e8} + 0xdf]
+ var endMethodSignature = input.IndexOf ('{');
+ var methodSignature = input.Slice (0, endMethodSignature - 2); // " ["
+ input = input.Slice (endMethodSignature + 1).TrimStart ();
+
+ // Append chars, escaping what might be unreadable by instruments.
+ for (int i = 0; i < methodSignature.Length; ++i) {
+ var ch = methodSignature [i];
+ if (ch == ' ')
+ continue;
+
+ if (ch == ':') {
+ sb.Append ("::");
+ continue;
+ }
+
+ if (ch == '.') {
+ sb.Append ("_");
+ continue;
+ }
+
+ if (ch == '[' && methodSignature [i + 1] == ']') {
+ sb.Append ("*");
+ i++;
+ continue;
+ }
+
+ sb.Append (ch);
+ }
+
+ // Add some data to match format, + 0 is because it doesn't matter, we're not looking at native code.
+ sb.Append (" (in MonoDevelop.exe) + 0 [");
+ sb.AppendFormat ("0x{0:x}", offset);
+ sb.Append ("]");
+
+ // Skip the rest of the block(s) after the method signature until we get a path.
+ input = input.Slice (input.IndexOf ('[') + 1).TrimStart ();
+
+ if (input[0] == '/') {
+ // We have a filename
+ var end = input.IndexOf (']');
+ var filepath = input.Slice (0, end - 1).Trim (); // trim u
+ filename = filepath.ToString ();
+ }
+
+ if (filename != null) {
+ sb.Append (" ");
+ sb.Append (filename);
+ }
+
+ return sb.ToString ();
+ } catch (Exception e) {
+ LoggingService.LogInternalError ($"Failed to parse line '{initialInput}'", e);
+ return initialInput;
+ }
+ }
+ }
+
ConnectionInfo currentConnection;
class ConnectionInfo
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 c82a36cb7b..86a4f93b9f 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
@@ -1779,7 +1779,7 @@ namespace MonoDevelop.VersionControl.Git
public string GetCurrentBranch ()
{
- return RunOperation (() => RootRepository.Head.FriendlyName);
+ return RunSafeOperation (() => RootRepository.Head.FriendlyName);
}
void SwitchBranchInternal (ProgressMonitor monitor, string branch)
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/SelectRepositoryDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/SelectRepositoryDialog.cs
index cd80d2ceac..c65e4434cc 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/SelectRepositoryDialog.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/SelectRepositoryDialog.cs
@@ -402,7 +402,8 @@ namespace MonoDevelop.VersionControl.Dialogs
}
var vcs = systems [repCombo.Active];
- entryFolder.Text = defaultPath + vcs.GetRelativeCheckoutPathForRemote (edit.RelativePath);
+ var projectNameFolder = System.IO.Path.DirectorySeparatorChar + System.IO.Path.GetFileName (edit.RelativePath);
+ entryFolder.Text = defaultPath + vcs.GetRelativeCheckoutPathForRemote (projectNameFolder);
}
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/CellRendererDiff.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/CellRendererDiff.cs
index 54824f5ab1..2c41dd248d 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/CellRendererDiff.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/CellRendererDiff.cs
@@ -150,70 +150,8 @@ namespace MonoDevelop.VersionControl.Views
// Rendering is done in two steps:
// 1) Get a list of blocks to render
// 2) render the blocks
-
- int y = cell_area.Y + 2;
-
- // cline keeps track of the current source code line (the one to jump to when double clicking)
- int cline = 1;
- bool inHeader = true;
- BlockInfo currentBlock = null;
-
- List<BlockInfo> blocks = new List<BlockInfo> ();
-
- for (int n=0; n<lines.Length; n++, y += lineHeight) {
-
- string line = lines [n];
- if (line.Length == 0) {
- currentBlock = null;
- y -= lineHeight;
- continue;
- }
-
- char tag = line [0];
-
- if (line.StartsWith ("---", StringComparison.Ordinal) ||
- line.StartsWith ("+++", StringComparison.Ordinal)) {
- // Ignore this part of the header.
- currentBlock = null;
- y -= lineHeight;
- continue;
- }
- if (tag == '@') {
- int l = ParseCurrentLine (line);
- if (l != -1) cline = l - 1;
- inHeader = false;
- } else if (tag == '+' && !inHeader)
- cline++;
- BlockType type;
- switch (tag) {
- case '-': type = BlockType.Removed; break;
- case '+': type = BlockType.Added; break;
- case '@': type = BlockType.Info; break;
- default: type = BlockType.Unchanged; break;
- }
-
- if (currentBlock == null || type != currentBlock.Type) {
- if (y > maxy)
- break;
-
- // Starting a new block. Mark section ends between a change block and a normal code block
- if (currentBlock != null && IsChangeBlock (currentBlock.Type) && !IsChangeBlock (type))
- currentBlock.SectionEnd = true;
-
- currentBlock = new BlockInfo () {
- YStart = y,
- FirstLine = n,
- Type = type,
- SourceLineStart = cline,
- SectionStart = (blocks.Count == 0 || !IsChangeBlock (blocks[blocks.Count - 1].Type)) && IsChangeBlock (type)
- };
- blocks.Add (currentBlock);
- }
- // Include the line in the current block
- currentBlock.YEnd = y + lineHeight;
- currentBlock.LastLine = n;
- }
+ var blocks = CalculateBlocks (maxy, cell_area.Y + 2);
// Now render the blocks
@@ -315,7 +253,81 @@ namespace MonoDevelop.VersionControl.Views
window.DrawLayout (widget.Style.TextGC (GetState(widget, flags)), cell_area.X, y, layout);
}
}
-
+
+ List<BlockInfo> CalculateBlocks (int maxy, int y)
+ {
+ // cline keeps track of the current source code line (the one to jump to when double clicking)
+ int cline = 1;
+
+ BlockInfo currentBlock = null;
+
+ var result = new List<BlockInfo> ();
+ int removedLines = 0;
+ for (int n = 0; n < lines.Length; n++, y += lineHeight) {
+
+ string line = lines [n];
+ if (line.Length == 0) {
+ currentBlock = null;
+ y -= lineHeight;
+ continue;
+ }
+
+ char tag = line [0];
+
+ if (line.StartsWith ("---", StringComparison.Ordinal) ||
+ line.StartsWith ("+++", StringComparison.Ordinal)) {
+ // Ignore this part of the header.
+ currentBlock = null;
+ y -= lineHeight;
+ continue;
+ }
+ if (tag == '@') {
+ int l = ParseCurrentLine (line);
+ if (l != -1) cline = l - 1;
+ } else
+ cline++;
+
+ BlockType type;
+ switch (tag) {
+ case '-':
+ type = BlockType.Removed;
+ removedLines++;
+ break;
+ case '+': type = BlockType.Added; break;
+ case '@': type = BlockType.Info; break;
+ default: type = BlockType.Unchanged; break;
+ }
+
+ if (type != BlockType.Removed && removedLines > 0) {
+ cline -= removedLines;
+ removedLines = 0;
+ }
+
+ if (currentBlock == null || type != currentBlock.Type) {
+ if (y > maxy)
+ break;
+
+ // Starting a new block. Mark section ends between a change block and a normal code block
+ if (currentBlock != null && IsChangeBlock (currentBlock.Type) && !IsChangeBlock (type))
+ currentBlock.SectionEnd = true;
+
+ currentBlock = new BlockInfo {
+ YStart = y,
+ FirstLine = n,
+ Type = type,
+ SourceLineStart = cline,
+ SectionStart = (result.Count == 0 || !IsChangeBlock (result [result.Count - 1].Type)) && IsChangeBlock (type)
+ };
+ result.Add (currentBlock);
+ }
+ // Include the line in the current block
+ currentBlock.YEnd = y + lineHeight;
+ currentBlock.LastLine = n;
+ }
+
+ return result;
+ }
+
static bool IsChangeBlock (BlockType t)
{
return t == BlockType.Added || t == BlockType.Removed;
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 ff8d111a1c..30a2dd0338 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
@@ -13,6 +13,7 @@ using MonoDevelop.Components.Commands;
using MonoDevelop.Projects;
using MonoDevelop.Ide;
using System.Text;
+using System.Threading.Tasks;
namespace MonoDevelop.VersionControl.Views
{
@@ -447,29 +448,50 @@ namespace MonoDevelop.VersionControl.Views
showRemoteStatus.Sensitive = false;
buttonCommit.Sensitive = false;
- ThreadPool.QueueUserWorkItem (delegate {
- lock (updateLock) {
- if (fileList != null) {
- var group = fileList.GroupBy (v => v.IsDirectory || v.WorkspaceObject is SolutionFolderItem);
- foreach (var item in group) {
- // Is directory.
- if (item.Key) {
- foreach (var directory in item)
- changeSet.AddFiles (vc.GetDirectoryVersionInfo (directory.Path, remoteStatus, true));
- } else
- changeSet.AddFiles (item.Select (v => v.VersionInfo).ToArray ());
- }
- changeSet.AddFiles (fileList.Where (v => !v.IsDirectory).Select (v => v.VersionInfo).ToArray ());
- fileList = null;
+ lock (updateLock) {
+ if (!cancelUpdate.IsCancellationRequested)
+ cancelUpdate.Cancel ();
+ cancelUpdate = new CancellationTokenSource ();
+ var token = cancelUpdate.Token;
+ updateTask = updateTask.ContinueWith (t => RunUpdate (token), token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Default);
+ }
+ }
+
+ CancellationTokenSource cancelUpdate = new CancellationTokenSource ();
+ Task updateTask = Task.FromResult (true);
+
+ void RunUpdate (CancellationToken cancel)
+ {
+ try {
+ cancel.ThrowIfCancellationRequested ();
+ if (fileList != null) {
+ var group = fileList.GroupBy (v => v.IsDirectory || v.WorkspaceObject is SolutionFolderItem);
+ foreach (var item in group) {
+ // Is directory.
+ if (item.Key) {
+ foreach (var directory in item)
+ changeSet.AddFiles (vc.GetDirectoryVersionInfo (directory.Path, remoteStatus, true));
+ } else
+ changeSet.AddFiles (item.Select (v => v.VersionInfo).ToArray ());
}
- List<VersionInfo> newList = new List<VersionInfo> ();
- newList.AddRange (vc.GetDirectoryVersionInfo (filepath, remoteStatus, true));
- Runtime.RunInMainThread (delegate {
- if (!disposed)
- LoadStatus (newList);
- });
+ fileList = null;
}
- });
+
+ cancel.ThrowIfCancellationRequested ();
+ var newList = new List<VersionInfo> ();
+ newList.AddRange (vc.GetDirectoryVersionInfo (filepath, remoteStatus, true));
+
+ cancel.ThrowIfCancellationRequested ();
+ Runtime.RunInMainThread (delegate {
+ // skip status reloading if another update is queued
+ if (!cancel.IsCancellationRequested && !disposed)
+ LoadStatus (newList);
+ }).Ignore ();
+ } catch (Exception ex) {
+ if (!(ex is OperationCanceledException))
+ LoggingService.LogError ("VCS StatusView update failed", ex);
+ throw;
+ }
}
void LoadStatus (List<VersionInfo> newList)
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs
index 6153628e47..02316c9a1a 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs
@@ -106,7 +106,9 @@ namespace MonoDevelop.VersionControl
}
}
- VersionControlService.repositoryCache.TryRemove (RepositoryPath.CanonicalPath, out _);
+ lock (VersionControlService.repositoryCacheLock) {
+ VersionControlService.repositoryCache.Remove (RepositoryPath.CanonicalPath);
+ }
infoCache?.Dispose ();
infoCache = null;
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlService.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlService.cs
index c5d9b098d2..610af88219 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlService.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlService.cs
@@ -211,7 +211,8 @@ namespace MonoDevelop.VersionControl
return String.Empty;
}
- internal static ConcurrentDictionary<Repository, InternalRepositoryReference> referenceCache = new ConcurrentDictionary<Repository, InternalRepositoryReference> ();
+ internal static readonly object referenceCacheLock = new object ();
+ internal static Dictionary<Repository, InternalRepositoryReference> referenceCache = new Dictionary<Repository, InternalRepositoryReference> ();
public static Repository GetRepository (WorkspaceObject entry)
{
if (IsGloballyDisabled)
@@ -225,14 +226,20 @@ namespace MonoDevelop.VersionControl
InternalRepositoryReference rref = null;
if (repo != null) {
repo.AddRef ();
- rref = referenceCache.GetOrAdd (repo, r => new InternalRepositoryReference (r));
+ lock (referenceCacheLock) {
+ if (!referenceCache.TryGetValue (repo, out rref)) {
+ rref = new InternalRepositoryReference (repo);
+ referenceCache [repo] = rref;
+ }
+ }
}
entry.ExtendedProperties [typeof(InternalRepositoryReference)] = rref;
return repo;
}
- internal static readonly ConcurrentDictionary<FilePath,Repository> repositoryCache = new ConcurrentDictionary<FilePath,Repository> ();
+ internal static readonly object repositoryCacheLock = new object ();
+ internal static readonly Dictionary<FilePath,Repository> repositoryCache = new Dictionary<FilePath,Repository> ();
public static Repository GetRepositoryReference (string path, string id)
{
VersionControlSystem detectedVCS = null;
@@ -256,22 +263,21 @@ namespace MonoDevelop.VersionControl
bestMatch = bestMatch.CanonicalPath;
- try {
- return repositoryCache.GetOrAdd (bestMatch, p => {
- var result = detectedVCS?.GetRepositoryReference (p, id);
- if (result != null) {
+ lock (repositoryCacheLock) {
+ if (repositoryCache.TryGetValue (bestMatch, out var repository))
+ return repository;
+
+ try {
+ var repo = detectedVCS?.GetRepositoryReference (bestMatch, id);
+ if (repo != null) {
+ repositoryCache.Add (bestMatch, repo);
Instrumentation.Repositories.Inc (new RepositoryMetadata (detectedVCS));
- result.RepositoryPath = p.CanonicalPath;
- return result;
}
- // never add null values
- throw new ArgumentNullException ("result");
- });
- } catch (Exception e) {
- // ArgumentNullException for "result" is expected when GetRepositoryReference returns null, no need to log
- if (!(e is ArgumentNullException ne) || ne.ParamName != "result")
- LoggingService.LogInternalError ($"Could not query {detectedVCS.Name} repository reference", e);
- return null;
+ return repo;
+ } catch (Exception e) {
+ LoggingService.LogError ($"Could not query {detectedVCS.Name} repository reference", e);
+ return null;
+ }
}
}
@@ -839,7 +845,9 @@ namespace MonoDevelop.VersionControl
public void Dispose ()
{
- VersionControlService.referenceCache.TryRemove (repo, out _);
+ lock (VersionControlService.referenceCacheLock) {
+ VersionControlService.referenceCache.Remove (repo);
+ }
repo.Unref ();
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/VersionControl.addin.xml b/main/src/addins/VersionControl/MonoDevelop.VersionControl/VersionControl.addin.xml
index ec2e9bd127..e66d577a8a 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/VersionControl.addin.xml
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/VersionControl.addin.xml
@@ -204,6 +204,8 @@
<CommandItem id = "MonoDevelop.VersionControl.Commands.Diff"/>
<CommandItem id = "MonoDevelop.VersionControl.Commands.Log"/>
<CommandItem id = "MonoDevelop.VersionControl.Commands.Annotate"/>
+ <SeparatorItem/>
+ <CommandItem id = "MonoDevelop.VersionControl.Commands.Revert"/>
</ItemSet>
<SeparatorItem/>
</Extension>
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs
index 133db60e95..d5cb477e85 100644
--- a/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs
+++ b/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs
@@ -73,66 +73,66 @@ namespace MonoDevelop.Platform
}
#region Toolbar implementation
- Components.Commands.CommandManager commandManager;
- string commandMenuAddinPath;
- string appMenuAddinPath;
- public override bool SetGlobalMenu (Components.Commands.CommandManager commandManager, string commandMenuAddinPath, string appMenuAddinPath)
- {
- // Only store this information. Release it when creating the main toolbar.
- this.commandManager = commandManager;
- this.commandMenuAddinPath = commandMenuAddinPath;
- this.appMenuAddinPath = appMenuAddinPath;
-
- return true;
- }
-
- const int WM_SYSCHAR = 0x0106;
- internal override void AttachMainToolbar (Gtk.VBox parent, Components.MainToolbar.IMainToolbarView toolbar)
- {
- titleBar = new TitleBar ();
- var topMenu = new WPFTitlebar (titleBar);
-
- //commandManager.IncompleteKeyPressed += (sender, e) => {
- // if (e.Key == Gdk.Key.Alt_L) {
- // Keyboard.Focus(titleBar.DockTitle.Children[0]);
- // }
- //};
- parent.PackStart (topMenu, false, true, 0);
- SetupMenu ();
-
- parent.PackStart ((WPFToolbar)toolbar, false, true, 0);
- }
-
- void SetupMenu ()
- {
- // TODO: Use this?
- CommandEntrySet appCes = commandManager.CreateCommandEntrySet (appMenuAddinPath);
-
- CommandEntrySet ces = commandManager.CreateCommandEntrySet (commandMenuAddinPath);
- var mainMenu = new Menu {
- IsMainMenu = true,
- FocusVisualStyle = null,
- };
- foreach (CommandEntrySet ce in ces)
- {
- var item = new TitleMenuItem (commandManager, ce, menu: mainMenu);
- mainMenu.Items.Add(item);
- }
-
- titleBar.DockTitle.Children.Add (mainMenu);
- DockPanel.SetDock (mainMenu, Dock.Left);
-
- commandManager = null;
- commandMenuAddinPath = appMenuAddinPath = null;
- }
-
- TitleBar titleBar;
- internal override Components.MainToolbar.IMainToolbarView CreateMainToolbar (Gtk.Window window)
- {
- return new WPFToolbar {
- HeightRequest = 40,
- };
- }
+ //Components.Commands.CommandManager commandManager;
+ //string commandMenuAddinPath;
+ //string appMenuAddinPath;
+ //public override bool SetGlobalMenu (Components.Commands.CommandManager commandManager, string commandMenuAddinPath, string appMenuAddinPath)
+ //{
+ // // Only store this information. Release it when creating the main toolbar.
+ // this.commandManager = commandManager;
+ // this.commandMenuAddinPath = commandMenuAddinPath;
+ // this.appMenuAddinPath = appMenuAddinPath;
+
+ // return true;
+ //}
+
+ //const int WM_SYSCHAR = 0x0106;
+ // internal override void AttachMainToolbar (Gtk.VBox parent, Components.MainToolbar.IMainToolbarView toolbar)
+ //{
+ // titleBar = new TitleBar ();
+ // var topMenu = new WPFTitlebar (titleBar);
+
+ // //commandManager.IncompleteKeyPressed += (sender, e) => {
+ // // if (e.Key == Gdk.Key.Alt_L) {
+ // // Keyboard.Focus(titleBar.DockTitle.Children[0]);
+ // // }
+ // //};
+ // parent.PackStart (topMenu, false, true, 0);
+ // SetupMenu ();
+
+ // parent.PackStart ((WPFToolbar)toolbar, false, true, 0);
+ //}
+
+ //void SetupMenu ()
+ //{
+ // // TODO: Use this?
+ // CommandEntrySet appCes = commandManager.CreateCommandEntrySet (appMenuAddinPath);
+
+ // CommandEntrySet ces = commandManager.CreateCommandEntrySet (commandMenuAddinPath);
+ // var mainMenu = new Menu {
+ // IsMainMenu = true,
+ // FocusVisualStyle = null,
+ // };
+ // foreach (CommandEntrySet ce in ces)
+ // {
+ // var item = new TitleMenuItem (commandManager, ce, menu: mainMenu);
+ // mainMenu.Items.Add(item);
+ // }
+
+ // titleBar.DockTitle.Children.Add (mainMenu);
+ // DockPanel.SetDock (mainMenu, Dock.Left);
+
+ // commandManager = null;
+ // commandMenuAddinPath = appMenuAddinPath = null;
+ //}
+
+ //TitleBar titleBar;
+ //internal override Components.MainToolbar.IMainToolbarView CreateMainToolbar (Gtk.Window window)
+ //{
+ // return new WPFToolbar {
+ // HeightRequest = 40,
+ // };
+ //}
#endregion
public override bool GetIsFullscreen (Components.Window window)
diff --git a/main/src/addins/Xml/Editor/BaseXmlEditorExtension.cs b/main/src/addins/Xml/Editor/BaseXmlEditorExtension.cs
index b37fa41673..a645cf49c3 100644
--- a/main/src/addins/Xml/Editor/BaseXmlEditorExtension.cs
+++ b/main/src/addins/Xml/Editor/BaseXmlEditorExtension.cs
@@ -472,7 +472,7 @@ namespace MonoDevelop.Xml.Editor
var encoding = Editor.Encoding.WebName;
list.Add (new BaseXmlCompletionData($"?xml version=\"1.0\" encoding=\"{encoding}\" ?>"));
}
- AddCloseTag (list, Tracker.Engine.Nodes);
+ AddCloseTag (list, Tracker.Engine.Nodes, currentChar);
if (tracker.Engine.CurrentState is XmlNameState)
if (GetCompletionCommandOffset (out var cpos, out var wlen))
list.TriggerWordLength = wlen;
@@ -678,8 +678,8 @@ namespace MonoDevelop.Xml.Editor
}
return null;
}
-
- protected static void AddCloseTag (CompletionDataList completionList, NodeStack stack)
+
+ protected static void AddCloseTag (CompletionDataList completionList, NodeStack stack, char currentChar)
{
//FIXME: search forward to see if tag's closed already
var elements = new List<XElement> ();
@@ -692,7 +692,12 @@ namespace MonoDevelop.Xml.Editor
if (elements.Count == 0) {
string name = el.Name.FullName;
- completionList.Add (new XmlTagCompletionData ("/" + name + ">", 0, true) {
+ var sb = StringBuilderCache.Allocate ();
+ if (currentChar != '/')
+ sb.Append ("/");
+ sb.Append (name);
+ sb.Append (">");
+ completionList.Add (new XmlTagCompletionData (StringBuilderCache.ReturnAndFree (sb), 0, true) {
Description = GettextCatalog.GetString ("Closing tag for '{0}'", name)
});
} else {
diff --git a/main/src/addins/Xml/Tests/CodeCompletion/XmlCodeCompletionTests.cs b/main/src/addins/Xml/Tests/CodeCompletion/XmlCodeCompletionTests.cs
index 5ffe1c26ce..92afb0b270 100644
--- a/main/src/addins/Xml/Tests/CodeCompletion/XmlCodeCompletionTests.cs
+++ b/main/src/addins/Xml/Tests/CodeCompletion/XmlCodeCompletionTests.cs
@@ -6,6 +6,7 @@ using MonoDevelop.Ide.Editor.Extension;
using MonoDevelop.Xml.Editor;
using NUnit.Framework;
using MonoDevelop.Ide.CodeCompletion;
+using System.Linq;
namespace MonoDevelop.Xml.Tests.CodeCompletion
{
@@ -22,6 +23,46 @@ namespace MonoDevelop.Xml.Tests.CodeCompletion
await ext.TriggerCompletion (Ide.CodeCompletion.CompletionTriggerReason.CompletionCommand);
ext.KeyPress (KeyDescriptor.FromGtk (Gdk.Key.colon, ':', Gdk.ModifierType.None));
Assert.IsTrue (CompletionWindowManager.IsVisible);
+ CompletionWindowManager.Wnd.HideWindow ();
+ }
+ }
+
+ /// <summary>
+ /// FeedbackTicket 739349: XAML Editor: When a closing tag already has '</' present, choosing the closing element from the completion window enters an invalid closing tag such as <//ContentView>
+ /// </summary>
+ [Test]
+ public async Task TestVSTS739349 ()
+ {
+ const string input = @"
+<Foo>
+</F";
+ using (var testCase = await SetupTestCase (input, input.Length)) {
+ var doc = testCase.Document;
+ var ext = doc.GetContent<BaseXmlEditorExtension> ();
+ ext.CompletionWidget = doc.Editor.GetViewContent ().GetContent<ICompletionWidget> ();
+ await ext.TriggerCompletion (Ide.CodeCompletion.CompletionTriggerReason.CompletionCommand);
+ Assert.IsTrue (CompletionWindowManager.IsVisible);
+
+ Assert.AreEqual ("Foo>", CompletionWindowManager.Wnd.SelectedItem.DisplayText);
+ CompletionWindowManager.Wnd.HideWindow ();
+ }
+ }
+
+ [Test]
+ public async Task TestVSTS739349_Case2 ()
+ {
+ const string input = @"
+<Foo>
+<";
+ using (var testCase = await SetupTestCase (input, input.Length)) {
+ var doc = testCase.Document;
+ var ext = doc.GetContent<BaseXmlEditorExtension> ();
+ ext.CompletionWidget = doc.Editor.GetViewContent ().GetContent<ICompletionWidget> ();
+ await ext.TriggerCompletion (Ide.CodeCompletion.CompletionTriggerReason.CompletionCommand);
+ Assert.IsTrue (CompletionWindowManager.IsVisible);
+ var list = CompletionWindowManager.Wnd.GetFilteredItems ();
+ Assert.IsTrue (list.Any (i => i.DisplayText == "/Foo>"));
+ CompletionWindowManager.Wnd.HideWindow ();
}
}
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml
index 2335c3c0ce..1de3bd4529 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml
@@ -265,6 +265,8 @@
<CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.SplitWindowHorizontally" />
<CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.UnsplitWindow" />
<CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.SwitchSplitWindow" />-->
+ <SeparatorItem id = "welcomePageSep" />
+ <CommandItem id = "MonoDevelop.Ide.Commands.ViewCommands.ShowWelcomePage" />
<SeparatorItem id = "contentSep" />
<CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.OpenWindowList" />
<SeparatorItem id = "windowDocSep" />
@@ -278,8 +280,6 @@
<CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.OpenDocument8" />
<CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.OpenDocument9" />
<CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.OpenDocumentList" />
- <SeparatorItem id = "welcomePageSep" />
- <CommandItem id = "MonoDevelop.Ide.Commands.ViewCommands.ShowWelcomePage" />
</ItemSet>
<ItemSet id = "Help" _label = "_Help">
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml
index 7c053a7b9c..3ffd21814c 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml
@@ -68,7 +68,7 @@
<ExtensionPoint path = "/MonoDevelop/Ide/InitCompleteHandlers" name = "Post inialization handlers">
<Description>Commands to be automatically executed when the IDE finishes initalization.</Description>
- <ExtensionNode name="Class">
+ <ExtensionNode name="Class" objectType="MonoDevelop.Components.Commands.CommandHandler">
<Description>A subclass of MonoDevelop.Components.Commands.CommandHandler</Description>
</ExtensionNode>
</ExtensionPoint>
diff --git a/main/src/core/MonoDevelop.Ide/Gui/MonoDevelop.Ide.Projects.AddExternalFileDialog.cs b/main/src/core/MonoDevelop.Ide/Gui/MonoDevelop.Ide.Projects.AddExternalFileDialog.cs
index 76e6194b6f..075e8f449a 100644
--- a/main/src/core/MonoDevelop.Ide/Gui/MonoDevelop.Ide.Projects.AddExternalFileDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/Gui/MonoDevelop.Ide.Projects.AddExternalFileDialog.cs
@@ -242,7 +242,6 @@ namespace MonoDevelop.Ide.Projects
this.DefaultHeight = 286;
this.radioKeep.Hide ();
this.checkApplyAll.Hide ();
- this.Show ();
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockContainer.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockContainer.cs
index 9b63190523..39b63f339e 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockContainer.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockContainer.cs
@@ -403,50 +403,51 @@ namespace MonoDevelop.Components.Docking
internal bool UpdatePlaceholder (DockItem item, Gdk.Size size, bool allowDocking)
{
- if (!Runtime.IsMainThread) {
- var msg = "UpdatePlaceholder called from background thread.";
- LoggingService.LogInternalError ($"{msg}\n{Environment.StackTrace}", new InvalidOperationException (msg));
- }
+ try {
+ Runtime.AssertMainThread ();
- var placeholderWindow = this.placeholderWindow;
- var padTitleWindow = this.padTitleWindow;
+ var placeholderWindow = this.placeholderWindow;
+ var padTitleWindow = this.padTitleWindow;
- if (placeholderWindow == null || padTitleWindow == null)
- return false;
-
- int px, py;
- GetPointer (out px, out py);
-
- placeholderWindow.AllowDocking = allowDocking;
-
- int ox, oy;
- GdkWindow.GetOrigin (out ox, out oy);
-
- int tw, th;
- padTitleWindow.GetSize (out tw, out th);
- padTitleWindow.Move (ox + px - tw/2, oy + py - th/2);
- padTitleWindow.GdkWindow.KeepAbove = true;
-
- DockDelegate dockDelegate;
- Gdk.Rectangle rect;
- if (allowDocking && layout.GetDockTarget (item, px, py, out dockDelegate, out rect)) {
- placeholderWindow.Relocate (ox + rect.X, oy + rect.Y, rect.Width, rect.Height, true);
- placeholderWindow.Show ();
- placeholderWindow.SetDockInfo (dockDelegate, rect);
- return true;
- } else {
- int w,h;
- var gi = layout.FindDockGroupItem (item.Id);
- if (gi != null) {
- w = gi.Allocation.Width;
- h = gi.Allocation.Height;
+ if (placeholderWindow == null || padTitleWindow == null || !IsRealized)
+ return false;
+
+ int px, py;
+ GetPointer (out px, out py);
+
+ placeholderWindow.AllowDocking = allowDocking;
+
+ int ox, oy;
+ GdkWindow.GetOrigin (out ox, out oy);
+
+ int tw, th;
+ padTitleWindow.GetSize (out tw, out th);
+ padTitleWindow.Move (ox + px - tw / 2, oy + py - th / 2);
+ padTitleWindow.GdkWindow.KeepAbove = true;
+
+ DockDelegate dockDelegate;
+ Gdk.Rectangle rect;
+ if (allowDocking && layout.GetDockTarget (item, px, py, out dockDelegate, out rect)) {
+ placeholderWindow.Relocate (ox + rect.X, oy + rect.Y, rect.Width, rect.Height, true);
+ placeholderWindow.Show ();
+ placeholderWindow.SetDockInfo (dockDelegate, rect);
+ return true;
} else {
- w = item.DefaultWidth;
- h = item.DefaultHeight;
+ int w, h;
+ var gi = layout.FindDockGroupItem (item.Id);
+ if (gi != null) {
+ w = gi.Allocation.Width;
+ h = gi.Allocation.Height;
+ } else {
+ w = item.DefaultWidth;
+ h = item.DefaultHeight;
+ }
+ placeholderWindow.Relocate (ox + px - w / 2, oy + py - h / 2, w, h, false);
+ placeholderWindow.Show ();
+ placeholderWindow.AllowDocking = false;
}
- placeholderWindow.Relocate (ox + px - w / 2, oy + py - h / 2, w, h, false);
- placeholderWindow.Show ();
- placeholderWindow.AllowDocking = false;
+ } catch (Exception ex) {
+ LoggingService.LogInternalError ("Updating the dock container placeholder failed", ex);
}
return false;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/FoldingTextEditorExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/FoldingTextEditorExtension.cs
index 82eae3fc76..a8c3509b90 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/FoldingTextEditorExtension.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/FoldingTextEditorExtension.cs
@@ -82,73 +82,77 @@ namespace MonoDevelop.Ide.Editor.Extension
if (parsedDocument == null || !Editor.Options.ShowFoldMargin || parsedDocument.Flags.HasFlag (ParsedDocumentFlags.SkipFoldings))
return;
// don't update parsed documents that contain errors - the foldings from there may be invalid.
- if (await parsedDocument.HasErrorsAsync (token))
+ if (await parsedDocument.HasErrorsAsync (token).ConfigureAwait (false))
return;
+ IReadOnlyList<FoldingRegion> foldings = null;
try {
- var foldSegments = new List<IFoldSegment> ();
-
- foreach (FoldingRegion region in await parsedDocument.GetFoldingsAsync (token)) {
- if (token.IsCancellationRequested)
- return;
- var type = FoldingType.Unknown;
- bool setFolded = false;
- bool folded = false;
- //decide whether the regions should be folded by default
- switch (region.Type) {
- case FoldType.Member:
- type = FoldingType.TypeMember;
- break;
- case FoldType.Type:
- type = FoldingType.TypeDefinition;
- break;
- case FoldType.UserRegion:
- type = FoldingType.Region;
- setFolded = DefaultSourceEditorOptions.Instance.DefaultRegionsFolding;
- folded = true;
- break;
- case FoldType.Comment:
- type = FoldingType.Comment;
- setFolded = DefaultSourceEditorOptions.Instance.DefaultCommentFolding;
- folded = true;
- break;
- case FoldType.CommentInsideMember:
- type = FoldingType.Comment;
- setFolded = DefaultSourceEditorOptions.Instance.DefaultCommentFolding;
- folded = false;
- break;
- case FoldType.Undefined:
- setFolded = true;
- folded = region.IsFoldedByDefault;
- break;
- }
- var start = Editor.LocationToOffset (region.Region.Begin);
- var end = Editor.LocationToOffset (region.Region.End);
- var marker = Editor.CreateFoldSegment (start, end - start);
- foldSegments.Add (marker);
- marker.CollapsedText = region.Name;
- marker.FoldingType = type;
- //and, if necessary, set its fold state
- if (marker != null && setFolded && firstTime) {
- // only fold on document open, later added folds are NOT folded by default.
- marker.IsCollapsed = folded;
- continue;
- }
- if (marker != null && region.Region.Contains (caretLocation.Line, caretLocation.Column))
- marker.IsCollapsed = false;
- }
- if (firstTime) {
- Editor.SetFoldings (foldSegments);
- } else {
- Application.Invoke ((o, args) => {
- if (!token.IsCancellationRequested)
- Editor.SetFoldings (foldSegments);
- });
- }
+ foldings = await parsedDocument.GetFoldingsAsync(token).ConfigureAwait (false);
} catch (OperationCanceledException) {
+ return;
} catch (Exception ex) {
LoggingService.LogError ("Unhandled exception in ParseInformationUpdaterWorkerThread", ex);
}
+ if (token.IsCancellationRequested)
+ return;
+ await Runtime.RunInMainThread (delegate {
+ var foldSegments = new List<IFoldSegment> ();
+ try {
+ foreach (var region in foldings) {
+ if (token.IsCancellationRequested)
+ return;
+ var type = FoldingType.Unknown;
+ bool setFolded = false;
+ bool folded = false;
+ //decide whether the regions should be folded by default
+ switch (region.Type) {
+ case FoldType.Member:
+ type = FoldingType.TypeMember;
+ break;
+ case FoldType.Type:
+ type = FoldingType.TypeDefinition;
+ break;
+ case FoldType.UserRegion:
+ type = FoldingType.Region;
+ setFolded = DefaultSourceEditorOptions.Instance.DefaultRegionsFolding;
+ folded = true;
+ break;
+ case FoldType.Comment:
+ type = FoldingType.Comment;
+ setFolded = DefaultSourceEditorOptions.Instance.DefaultCommentFolding;
+ folded = true;
+ break;
+ case FoldType.CommentInsideMember:
+ type = FoldingType.Comment;
+ setFolded = DefaultSourceEditorOptions.Instance.DefaultCommentFolding;
+ folded = false;
+ break;
+ case FoldType.Undefined:
+ setFolded = true;
+ folded = region.IsFoldedByDefault;
+ break;
+ }
+ var start = Editor.LocationToOffset (region.Region.Begin);
+ var end = Editor.LocationToOffset (region.Region.End);
+ var marker = Editor.CreateFoldSegment (start, end - start);
+ foldSegments.Add (marker);
+ marker.CollapsedText = region.Name;
+ marker.FoldingType = type;
+ //and, if necessary, set its fold state
+ if (marker != null && setFolded && firstTime) {
+ // only fold on document open, later added folds are NOT folded by default.
+ marker.IsCollapsed = folded;
+ continue;
+ }
+ if (marker != null && region.Region.Contains (caretLocation.Line, caretLocation.Column))
+ marker.IsCollapsed = false;
+ }
+ Editor.SetFoldings (foldSegments);
+ } catch (OperationCanceledException) {
+ } catch (Exception ex) {
+ LoggingService.LogError ("Unhandled exception in ParseInformationUpdaterWorkerThread", ex);
+ }
+ });
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/EditorPreferences.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/EditorPreferences.cs
index e7de100b4b..eb3bf0f0a6 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/EditorPreferences.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/EditorPreferences.cs
@@ -90,7 +90,7 @@ namespace MonoDevelop.Ide.Editor
OutliningUndoStep = Wrap<bool> ("GenerateFormattingUndoStep", DefaultTextViewOptions.OutliningUndoOptionName);
ShowChangeTrackingMargin = Wrap ("EnableQuickDiff", DefaultTextViewHostOptions.ChangeTrackingName, false);
ShowGlyphMargin = Wrap<bool> ("ShowGlyphMargin", DefaultTextViewHostOptions.GlyphMarginName);
- ShowLineNumberMargin = Wrap<bool> ("ShowLineNumberMargin", DefaultTextViewHostOptions.LineNumberMarginName);
+ ShowLineNumberMargin = Wrap ("ShowLineNumberMargin", DefaultTextViewHostOptions.LineNumberMarginName, true);
ShowOutliningMargin = Wrap<bool> ("ShowFoldMargin", DefaultTextViewHostOptions.OutliningMarginName);
TrimTrailingWhitespace = Wrap ("RemoveTrailingWhitespaces", DefaultOptions.TrimTrailingWhiteSpaceOptionName, true);
// UseVirtualSpace should be a combination of IndentStyle == MonoDevelop.Ide.Editor.IndentStyle.Smart && RemoveTrailingWhitespaces
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs
index 9f737ed3b4..d1b25c2ca9 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs
@@ -503,7 +503,7 @@ namespace MonoDevelop.Ide.Gui.Components
var rect = text_render.GetStatusIconArea (tree, cellArea);
if (cx >= rect.X && cx <= rect.Right) {
tree.ConvertBinWindowToWidgetCoords (rect.X, rect.Y, out rect.X, out rect.Y);
- ShowStatusMessage (it, rect, info);
+ ShowStatusMessage (path, rect, info);
popupShown = true;
}
}
@@ -514,17 +514,17 @@ namespace MonoDevelop.Ide.Gui.Components
}
bool statusMessageVisible;
- Gtk.TreeIter statusIconIter;
+ Gtk.TreePath statusIconPath;
TooltipPopoverWindow statusPopover;
- void ShowStatusMessage (Gtk.TreeIter it, Gdk.Rectangle rect, NodeInfo info)
+ void ShowStatusMessage (Gtk.TreePath path, Gdk.Rectangle rect, NodeInfo info)
{
- if (statusMessageVisible && store.GetPath (it).Equals (store.GetPath (statusIconIter)))
+ if (statusMessageVisible && path.Equals (statusIconPath))
return;
if (statusPopover != null)
statusPopover.Destroy ();
statusMessageVisible = true;
- statusIconIter = it;
+ statusIconPath = path;
statusPopover = TooltipPopoverWindow.Create ();
statusPopover.ShowArrow = true;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs
index f98640dfaf..e3b9988b50 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs
@@ -81,6 +81,7 @@ namespace MonoDevelop.Ide.Gui
public event EventHandler GuiLocked;
public event EventHandler GuiUnlocked;
bool fileEventsFrozen;
+ bool hasEverBeenShown = false;
internal void Initialize (ProgressMonitor monitor)
{
@@ -134,20 +135,22 @@ namespace MonoDevelop.Ide.Gui
Counters.Initialization.Trace ("Setting memento");
workbench.Memento = memento;
- Counters.Initialization.Trace ("Setting layout");
- workbench.CurrentLayout = "Solution";
-
- // now we have an layout set notify it
- Counters.Initialization.Trace ("Setting layout");
- if (LayoutChanged != null)
- LayoutChanged (this, EventArgs.Empty);
-
Counters.Initialization.Trace ("Initializing monitors");
monitors.Initialize ();
}
internal void Show ()
{
+ if (!hasEverBeenShown) {
+ workbench.CurrentLayout = "Solution";
+
+ // now we have an layout set notify it
+ if (LayoutChanged != null)
+ LayoutChanged (this, EventArgs.Empty);
+
+ hasEverBeenShown = true;
+ }
+
// Very important: see https://github.com/mono/monodevelop/pull/6064
// Otherwise the editor may not be focused on IDE startup and can't be
// focused even by clicking with the mouse.
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MiscellaneousFilesWorkspace.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MiscellaneousFilesWorkspace.cs
index 7e3cecfdc0..247d065aba 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MiscellaneousFilesWorkspace.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MiscellaneousFilesWorkspace.cs
@@ -27,11 +27,16 @@ using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
+
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
+
using Microsoft.VisualStudio.Composition;
using Microsoft.VisualStudio.Text;
+
+using Mono.Addins;
+
using MonoDevelop.Ide.Composition;
namespace MonoDevelop.Ide.TypeSystem
@@ -65,7 +70,10 @@ namespace MonoDevelop.Ide.TypeSystem
[ImportingConstructor]
public MiscellaneousFilesWorkspace ()
: base (CompositionManager.Instance.HostServices, WorkspaceKind.MiscellaneousFiles)
- {
+ {
+ foreach (var factory in AddinManager.GetExtensionObjects<Microsoft.CodeAnalysis.Options.IDocumentOptionsProviderFactory> ("/MonoDevelop/Ide/TypeService/OptionProviders"))
+ Services.GetRequiredService<Microsoft.CodeAnalysis.Options.IOptionService> ().RegisterDocumentOptionsProvider (factory.Create (this));
+
defaultProjectId = ProjectId.CreateNewId (DefaultProjectName);
var compilationOptions = new CSharpCompilationOptions (OutputKind.ConsoleApplication);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.ProjectSystemHandler.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.ProjectSystemHandler.cs
index b0a37fe68c..ab63acc39e 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.ProjectSystemHandler.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.ProjectSystemHandler.cs
@@ -1,4 +1,4 @@
-//
+//
// MonoDevelopWorkspace.ProjectSystemHandler.cs
//
// Author:
@@ -104,8 +104,10 @@ namespace MonoDevelop.Ide.TypeSystem
var config = IdeApp.IsInitialized ? p.GetConfiguration (IdeApp.Workspace.ActiveConfiguration) as MonoDevelop.Projects.DotNetProjectConfiguration : null;
MonoDevelop.Projects.DotNetCompilerParameters cp = config?.CompilationParameters;
FilePath fileName = IdeApp.IsInitialized ? p.GetOutputFileName (IdeApp.Workspace.ActiveConfiguration) : (FilePath)"";
- if (fileName.IsNullOrEmpty)
+
+ if (fileName.IsNullOrEmpty) {
fileName = new FilePath (p.Name + ".dll");
+ }
if (!hackyCache.TryGetCachedItems (p, workspace.MetadataReferenceManager, projectMap, out var sourceFiles, out var analyzerFiles, out var references, out var projectReferences)) {
(references, projectReferences) = await metadataHandler.Value.CreateReferences (p, token).ConfigureAwait (false);
@@ -148,7 +150,7 @@ namespace MonoDevelop.Ide.TypeSystem
// TODO: Pass in the WorkspaceMetadataFileReferenceResolver
var info = ProjectInfo.Create (
projectId,
- VersionStamp.Create (),
+ GetVersionStamp (p),
p.Name,
fileName.FileNameWithoutExtension,
(p as MonoDevelop.Projects.DotNetProject)?.RoslynLanguageName ?? LanguageNames.CSharp,
@@ -169,6 +171,16 @@ namespace MonoDevelop.Ide.TypeSystem
return info;
}
+ VersionStamp GetVersionStamp (MonoDevelop.Projects.Project project)
+ {
+ try {
+ return VersionStamp.Create (File.GetLastWriteTimeUtc (project.FileName));
+ } catch (Exception e) {
+ LoggingService.LogInternalError ("Failed to create version stamp", e);
+ return VersionStamp.Create ();
+ }
+ }
+
async Task<ConcurrentBag<ProjectInfo>> CreateProjectInfos (IEnumerable<MonoDevelop.Projects.Project> mdProjects, CancellationToken token)
{
var projects = new ConcurrentBag<ProjectInfo> ();
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
index 5b4b8edaa4..91f1f0e7fa 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
@@ -4201,6 +4201,7 @@
<Compile Include="MonoDevelop.Components\Mac\NSStackViewExtensions.cs" />
<Compile Include="MonoDevelop.Components\Mac\NSLabel.cs" />
<Compile Include="MonoDevelop.Components\Mac\NSLine.cs" />
+ <Compile Include="MonoDevelop.Ide\IdeStartupTracker.cs" />
</ItemGroup>
<ItemGroup>
<Data Include="options\DefaultEditingLayout.xml" />
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs
index 960da88fd3..ca0bda6546 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs
@@ -100,22 +100,8 @@ namespace MonoDevelop.Ide
}
}
- static TimeToCodeMetadata ttcMetadata;
- static Stopwatch ttcStopwatch;
- static long startupCompletedTicks;
- static long ttcDuration = 3 * TimeSpan.TicksPerSecond; // Wait 3 seconds before ignoring TTC events
-
- internal static void OnStartupCompleted (StartupMetadata startupMetadata, Stopwatch ttcTimer)
+ internal static void OnStartupCompleted ()
{
- ttcMetadata = new TimeToCodeMetadata {
- StartupTime = startupMetadata.CorrectedStartupTime
- };
- ttcMetadata.AddProperties (startupMetadata);
-
- ttcStopwatch = ttcTimer;
- startupCompletedTicks = ttcStopwatch.ElapsedTicks;
- LoggingService.LogDebug ("TTC starting");
-
startupCompleted?.Invoke (null, EventArgs.Empty);
}
@@ -327,73 +313,6 @@ namespace MonoDevelop.Ide
Ide.IdeApp.Workbench.StatusBar.ShowWarning (e.Message);
}
- internal static void TrackTimeToCode (TimeToCodeMetadata.DocumentType documentType)
- {
- LoggingService.LogDebug("Tracking TTC");
- if (ttcStopwatch == null || timeToCodeSolutionTimer == null) {
- LoggingService.LogDebug("Ignoring TTC");
- return;
- }
-
- ttcStopwatch.Stop ();
- timeToCodeSolutionTimer.Stop ();
-
- if (ttcMetadata == null) {
- timeToCodeSolutionTimer = null;
- ttcStopwatch = null;
- throw new Exception ("SendTimeToCode called before initialisation completed");
- }
-
- LoggingService.LogDebug ("Processing TTC");
- ttcMetadata.SolutionLoadTime = timeToCodeSolutionTimer.ElapsedMilliseconds;
-
- ttcMetadata.CorrectedDuration = ttcStopwatch.ElapsedMilliseconds;
- ttcMetadata.Type = documentType;
-
- Counters.TimeToCode.Inc ("SolutionLoaded", ttcMetadata);
-
- timeToCodeSolutionTimer = null;
- timeToCodeWorkspaceTimer = Stopwatch.StartNew ();
-
- MonoDevelopWorkspace.LoadingFinished += CompleteTimeToIntellisense;
- }
-
- static void CompleteTimeToIntellisense (object sender, EventArgs e)
- {
- // Reuse ttcMetadata, as it already has other information set.
- MonoDevelopWorkspace.LoadingFinished -= CompleteTimeToIntellisense;
-
- timeToCodeWorkspaceTimer.Stop ();
-
- ttcMetadata.IntellisenseLoadTime = timeToCodeWorkspaceTimer.ElapsedMilliseconds;
- ttcMetadata.CorrectedDuration += timeToCodeWorkspaceTimer.ElapsedMilliseconds;
-
- Counters.TimeToIntellisense.Inc ("IntellisenseLoaded", ttcMetadata);
- }
-
-
- static Stopwatch timeToCodeSolutionTimer = new Stopwatch ();
- static Stopwatch timeToCodeWorkspaceTimer = null;
- internal static bool StartTimeToCodeLoadTimer ()
- {
- if (ttcStopwatch.ElapsedTicks - startupCompletedTicks > ttcDuration) {
- LoggingService.LogDebug ($"Not starting TTC timer: {ttcStopwatch.ElapsedTicks - startupCompletedTicks}");
- return false;
- }
- LoggingService.LogDebug ("Starting TTC timer");
- timeToCodeSolutionTimer.Start ();
-
- return true;
- }
-
- public static void BringToFront ()
- {
- Initialized += (sender, e) => {
- if (!Ide.WelcomePage.WelcomePageService.HasWindowImplementation)
- Workbench.Present ();
- };
- }
-
//this method is MIT/X11, 2009, Michael Hutchinson / (c) Novell
public static void OpenFiles (IEnumerable<FileOpenInformation> files)
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
index b12343faf4..2a69143203 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
@@ -62,10 +62,6 @@ namespace MonoDevelop.Ide
List<AddinError> errorsList = new List<AddinError> ();
bool initialized;
- static Stopwatch startupTimer = new Stopwatch ();
- static Stopwatch startupSectionTimer = new Stopwatch ();
- static Stopwatch timeToCodeTimer = new Stopwatch ();
- static Dictionary<string, long> sectionTimings = new Dictionary<string, long> ();
static bool hideWelcomePage;
static TimeToCodeMetadata ttcMetadata;
@@ -86,12 +82,10 @@ namespace MonoDevelop.Ide
//ensure native libs initialized before we hit anything that p/invokes
Platform.Initialize ();
- sectionTimings ["PlatformInitialization"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ IdeStartupTracker.StartupTracker.MarkSection ("PlatformInitialization");
GettextCatalog.Initialize ();
- sectionTimings ["GettextInitialization"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ IdeStartupTracker.StartupTracker.MarkSection ("GettextInitialization");
LoggingService.LogInfo ("Operating System: {0}", SystemInformation.GetOperatingSystemDescription ());
@@ -137,8 +131,10 @@ namespace MonoDevelop.Ide
LoggingService.LogError ("Error initialising GLib logging.", ex);
}
- sectionTimings ["GtkInitialization"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ var args = options.RemainingArgs.ToArray ();
+ IdeTheme.InitializeGtk (BrandingService.ApplicationName, ref args);
+
+ IdeStartupTracker.StartupTracker.MarkSection ("GtkInitialization");
LoggingService.LogInfo ("Using GTK+ {0}", IdeVersionInfo.GetGtkVersion ());
// XWT initialization
@@ -149,8 +145,7 @@ namespace MonoDevelop.Ide
Xwt.Toolkit.CurrentEngine.RegisterBackend<IExtendedTitleBarDialogBackend, GtkExtendedTitleBarDialogBackend> ();
IdeTheme.SetupXwtTheme ();
- sectionTimings ["XwtInitialization"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ IdeStartupTracker.StartupTracker.MarkSection ("XwtInitialization");
//default to Windows IME on Windows
if (Platform.IsWindows && GtkWorkarounds.GtkMinorVersion >= 16) {
@@ -166,14 +161,12 @@ namespace MonoDevelop.Ide
SynchronizationContext.SetSynchronizationContext (DispatchService.SynchronizationContext);
Runtime.MainSynchronizationContext = SynchronizationContext.Current;
- sectionTimings ["DispatchInitialization"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ IdeStartupTracker.StartupTracker.MarkSection ("DispatchInitialization");
// Initialize Roslyn's synchronization context
RoslynServices.RoslynService.Initialize ();
- sectionTimings ["RoslynInitialization"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ IdeStartupTracker.StartupTracker.MarkSection ("RoslynInitialization");
AddinManager.AddinLoadError += OnAddinError;
@@ -202,8 +195,7 @@ namespace MonoDevelop.Ide
if (!options.NewWindow && startupInfo.HasFiles && instanceConnection.TryConnect (startupInfo))
return 0;
- sectionTimings ["RuntimeInitialization"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ IdeStartupTracker.StartupTracker.MarkSection ("RuntimeInitialization");
bool restartRequested = PropertyService.Get ("MonoDevelop.Core.RestartRequested", false);
startupInfo.Restarted = restartRequested;
@@ -215,8 +207,7 @@ namespace MonoDevelop.Ide
IdeApp.Customizer.OnCoreInitialized ();
- sectionTimings ["ThemeInitialized"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ IdeStartupTracker.StartupTracker.MarkSection ("ThemeInitialized");
IdeApp.IsRunning = true;
@@ -254,8 +245,7 @@ namespace MonoDevelop.Ide
Counters.Initialization.Trace ("Initializing Platform Service");
await Runtime.GetService<DesktopService> ();
- sectionTimings["PlatformInitialization"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ IdeStartupTracker.StartupTracker.MarkSection ("PlatformInitialization");
monitor.Step (1);
@@ -263,8 +253,7 @@ namespace MonoDevelop.Ide
CheckFileWatcher ();
- sectionTimings["FileWatcherInitialization"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ IdeStartupTracker.StartupTracker.MarkSection ("FileWatcherInitialization");
Exception error = null;
int reportedFailures = 0;
@@ -274,8 +263,7 @@ namespace MonoDevelop.Ide
//force initialisation before the workbench so that it can register stock icons for GTK before they get requested
ImageService.Initialize ();
- sectionTimings ["ImageInitialization"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ IdeStartupTracker.StartupTracker.MarkSection ("ImageInitialization");
// If we display an error dialog before the main workbench window on OS X then a second application menu is created
// which is then replaced with a second empty Apple menu.
@@ -285,8 +273,7 @@ namespace MonoDevelop.Ide
hideWelcomePage = options.NoStartWindow || startupInfo.HasFiles || IdeApp.Preferences.StartupBehaviour.Value != OnStartupBehaviour.ShowStartWindow;
await IdeApp.Initialize (monitor);
- sectionTimings ["AppInitialization"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ IdeStartupTracker.StartupTracker.MarkSection ("AppInitialization");
if (errorsList.Count > 0) {
using (AddinLoadErrorDialog dlg = new AddinLoadErrorDialog (errorsList.ToArray (), false)) {
@@ -341,8 +328,7 @@ namespace MonoDevelop.Ide
errorsList = null;
AddinManager.AddinLoadError -= OnAddinError;
- sectionTimings["BasicInitializationCompleted"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ IdeStartupTracker.StartupTracker.MarkSection ("BasicInitializationCompleted");
instanceConnection.FileOpenRequested += (sender, a) => {
foreach (var e in a)
@@ -351,15 +337,13 @@ namespace MonoDevelop.Ide
instanceConnection.StartListening ();
- sectionTimings["SocketInitialization"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ IdeStartupTracker.StartupTracker.MarkSection ("SocketInitialization");
initialized = true;
MessageService.RootWindow = IdeApp.Workbench.RootWindow;
Xwt.MessageDialog.RootWindow = Xwt.Toolkit.CurrentEngine.WrapWindow (IdeApp.Workbench.RootWindow);
- sectionTimings["WindowOpened"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ IdeStartupTracker.StartupTracker.MarkSection ("WindowOpened");
Thread.CurrentThread.Name = "GUI Thread";
Counters.Initialization.Trace ("Running IdeApp");
@@ -374,11 +358,8 @@ namespace MonoDevelop.Ide
// we show the main window.
DispatchService.RunPendingEvents ();
- sectionTimings ["PumpEventLoop"] = startupSectionTimer.ElapsedMilliseconds;
- startupTimer.Stop ();
- startupSectionTimer.Stop ();
-
- CreateStartupMetadata (startupInfo, sectionTimings);
+ IdeStartupTracker.StartupTracker.MarkSection ("PumpEventLoop");
+ IdeStartupTracker.StartupTracker.Stop (startupInfo);
GLib.Idle.Add (OnIdle);
@@ -449,19 +430,6 @@ namespace MonoDevelop.Ide
return false;
}
- void CreateStartupMetadata (StartupInfo si, Dictionary<string, long> timings)
- {
- var result = IdeServices.DesktopService.PlatformTelemetry;
- if (result == null) {
- return;
- }
-
- var startupMetadata = GetStartupMetadata (si, result, timings);
- Counters.Startup.Inc (startupMetadata);
-
- IdeApp.OnStartupCompleted (startupMetadata, timeToCodeTimer);
- }
-
static DateTime lastIdle;
static bool lockupCheckRunning = true;
@@ -565,10 +533,11 @@ namespace MonoDevelop.Ide
{
if (args.Change == ExtensionChange.Add) {
try {
- if (typeof(CommandHandler).IsInstanceOfType (args.ExtensionObject))
- typeof(CommandHandler).GetMethod ("Run", System.Reflection.BindingFlags.NonPublic|System.Reflection.BindingFlags.Instance, null, Type.EmptyTypes, null).Invoke (args.ExtensionObject, null);
- else
+ if (args.ExtensionObject is CommandHandler handler) {
+ handler.InternalRun ();
+ } else {
LoggingService.LogError ("Type " + args.ExtensionObject.GetType () + " must be a subclass of MonoDevelop.Components.Commands.CommandHandler");
+ }
} catch (Exception ex) {
LoggingService.LogError (ex.ToString ());
}
@@ -706,13 +675,8 @@ namespace MonoDevelop.Ide
public static int Main (string[] args, IdeCustomizer customizer = null)
{
- // Using a Stopwatch instead of a TimerCounter since calling
- // TimerCounter.BeginTiming here would occur before any timer
- // handlers can be registered. So instead the startup duration is
- // set as a metadata property on the Counters.Startup counter.
- startupTimer.Start ();
- startupSectionTimer.Start ();
- timeToCodeTimer.Start ();
+
+ IdeStartupTracker.StartupTracker.Start ();
var options = MonoDevelopOptions.Parse (args);
if (options.ShowHelp || options.Error != null)
@@ -737,8 +701,7 @@ namespace MonoDevelop.Ide
exename = exename.ToLower ();
Runtime.SetProcessName (exename);
- sectionTimings ["mainInitialization"] = startupSectionTimer.ElapsedMilliseconds;
- startupSectionTimer.Restart ();
+ IdeStartupTracker.StartupTracker.MarkSection ("mainInitialization");
var app = new IdeStartup ();
ret = app.Run (options);
@@ -782,49 +745,6 @@ namespace MonoDevelop.Ide
return null;
}
- enum StartupType
- {
- Normal = 0x0,
- ConfigurationChange = 0x1,
- FirstLaunch = 0x2,
- DebuggerPresent = 0x10,
- CommandExecuted = 0x20,
- LaunchedAsDebugger = 0x40,
- FirstLaunchSetup = 0x80,
-
- // Monodevelop specific
- FirstLaunchAfterUpgrade = 0x10000
- }
-
- static StartupMetadata GetStartupMetadata (StartupInfo startupInfo, IPlatformTelemetryDetails platformDetails, Dictionary<string, long> timings)
- {
- var assetType = StartupAssetType.FromStartupInfo (startupInfo);
- StartupType startupType = StartupType.Normal;
-
- if (startupInfo.Restarted && !IdeApp.IsInitialRunAfterUpgrade) {
- startupType = StartupType.ConfigurationChange; // Assume a restart without upgrading was the result of a config change
- } else if (IdeApp.IsInitialRun) {
- startupType = StartupType.FirstLaunch;
- } else if (IdeApp.IsInitialRunAfterUpgrade) {
- startupType = StartupType.FirstLaunchAfterUpgrade;
- } else if (Debugger.IsAttached) {
- startupType = StartupType.DebuggerPresent;
- }
-
- return new StartupMetadata {
- CorrectedStartupTime = startupTimer.ElapsedMilliseconds,
- StartupType = Convert.ToInt32 (startupType),
- AssetTypeId = assetType.Id,
- AssetTypeName = assetType.Name,
- IsInitialRun = IdeApp.IsInitialRun,
- IsInitialRunAfterUpgrade = IdeApp.IsInitialRunAfterUpgrade,
- TimeSinceMachineStart = (long)platformDetails.TimeSinceMachineStart.TotalMilliseconds,
- TimeSinceLogin = (long)platformDetails.TimeSinceLogin.TotalMilliseconds,
- Timings = timings,
- StartupBehaviour = IdeApp.Preferences.StartupBehaviour.Value
- };
- }
-
internal static OpenWorkspaceItemMetadata GetOpenWorkspaceOnStartupMetadata ()
{
var metadata = new OpenWorkspaceItemMetadata {
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartupTracker.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartupTracker.cs
new file mode 100644
index 0000000000..c2579f0346
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartupTracker.cs
@@ -0,0 +1,205 @@
+//
+// IdeStartupTracker.cs
+//
+// Author:
+// iain <iaholmes@microsoft.com>
+//
+// Copyright (c) 2019
+//
+// 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.Diagnostics;
+
+using MonoDevelop.Core;
+
+using MonoDevelop.Ide.Desktop;
+using MonoDevelop.Ide.Gui;
+using MonoDevelop.Ide.TypeSystem;
+
+namespace MonoDevelop.Ide
+{
+ internal class IdeStartupTracker
+ {
+ static Lazy<IdeStartupTracker> startupTracker = new Lazy<IdeStartupTracker> (() => new IdeStartupTracker ());
+ static internal IdeStartupTracker StartupTracker => startupTracker.Value;
+
+ const long ttcDuration = 3 * TimeSpan.TicksPerSecond; // Wait 3 seconds before ignoring TTC events
+
+ Stopwatch startupTimer = new Stopwatch ();
+ Stopwatch startupSectionTimer = new Stopwatch ();
+ Stopwatch timeToCodeTimer = new Stopwatch ();
+ Stopwatch timeToCodeSolutionTimer = new Stopwatch ();
+ Stopwatch timeToCodeWorkspaceTimer;
+
+ Dictionary<string, long> sectionTimings = new Dictionary<string, long> ();
+ StartupInfo startupInfo;
+ TimeToCodeMetadata ttcMetadata;
+
+ IdeStartupTracker ()
+ {
+
+ }
+
+ internal void Start ()
+ {
+ // Using a Stopwatch instead of a TimerCounter since calling
+ // TimerCounter.BeginTiming here would occur before any timer
+ // handlers can be registered. So instead the startup duration is
+ // set as a metadata property on the Counters.Startup counter.
+ startupTimer.Start ();
+ startupSectionTimer.Start ();
+ timeToCodeTimer.Start ();
+ }
+
+ internal void Stop (StartupInfo startupInfo)
+ {
+ startupTimer.Stop ();
+ startupSectionTimer.Stop ();
+
+ this.startupInfo = startupInfo;
+
+ var result = DesktopService.PlatformTelemetry;
+ if (result == null) {
+ return;
+ }
+
+ StartupCompleted (result);
+ }
+
+ internal void StartupCompleted (IPlatformTelemetryDetails platformTelemetryDetails)
+ {
+ var startupMetadata = GetStartupMetadata (platformTelemetryDetails);
+ Counters.Startup.Inc (startupMetadata);
+
+ // Start TTC timer
+ ttcMetadata = new TimeToCodeMetadata {
+ StartupTime = startupMetadata.CorrectedStartupTime
+ };
+ ttcMetadata.AddProperties (startupMetadata);
+
+ LoggingService.LogDebug ("TTC starting");
+ }
+
+ internal void MarkSection (string name)
+ {
+ sectionTimings [name] = startupSectionTimer.ElapsedMilliseconds;
+ startupSectionTimer.Restart ();
+ }
+
+ enum StartupType
+ {
+ Normal = 0x0,
+ ConfigurationChange = 0x1,
+ FirstLaunch = 0x2,
+ DebuggerPresent = 0x10,
+ CommandExecuted = 0x20,
+ LaunchedAsDebugger = 0x40,
+ FirstLaunchSetup = 0x80,
+
+ // Monodevelop specific
+ FirstLaunchAfterUpgrade = 0x10000
+ }
+
+ StartupMetadata GetStartupMetadata (IPlatformTelemetryDetails platformDetails)
+ {
+ var assetType = StartupAssetType.FromStartupInfo (startupInfo);
+ StartupType startupType = StartupType.Normal;
+
+ if (startupInfo.Restarted && !IdeApp.IsInitialRunAfterUpgrade) {
+ startupType = StartupType.ConfigurationChange; // Assume a restart without upgrading was the result of a config change
+ } else if (IdeApp.IsInitialRun) {
+ startupType = StartupType.FirstLaunch;
+ } else if (IdeApp.IsInitialRunAfterUpgrade) {
+ startupType = StartupType.FirstLaunchAfterUpgrade;
+ } else if (Debugger.IsAttached) {
+ startupType = StartupType.DebuggerPresent;
+ }
+
+ return new StartupMetadata {
+ CorrectedStartupTime = startupTimer.ElapsedMilliseconds,
+ StartupType = Convert.ToInt32 (startupType),
+ AssetTypeId = assetType.Id,
+ AssetTypeName = assetType.Name,
+ IsInitialRun = IdeApp.IsInitialRun,
+ IsInitialRunAfterUpgrade = IdeApp.IsInitialRunAfterUpgrade,
+ TimeSinceMachineStart = (long)platformDetails.TimeSinceMachineStart.TotalMilliseconds,
+ TimeSinceLogin = (long)platformDetails.TimeSinceLogin.TotalMilliseconds,
+ Timings = sectionTimings,
+ StartupBehaviour = IdeApp.Preferences.StartupBehaviour.Value
+ };
+ }
+
+ internal void TrackTimeToCode (TimeToCodeMetadata.DocumentType documentType)
+ {
+ LoggingService.LogDebug ("Tracking TTC");
+ if (this.timeToCodeTimer == null || timeToCodeSolutionTimer == null) {
+ LoggingService.LogDebug ("Ignoring TTC");
+ return;
+ }
+
+ timeToCodeTimer.Stop ();
+ timeToCodeSolutionTimer.Stop ();
+
+ if (ttcMetadata == null) {
+ timeToCodeSolutionTimer = null;
+ timeToCodeTimer = null;
+ throw new Exception ("SendTimeToCode called before initialisation completed");
+ }
+
+ LoggingService.LogDebug ("Processing TTC");
+ ttcMetadata.SolutionLoadTime = timeToCodeSolutionTimer.ElapsedMilliseconds;
+
+ ttcMetadata.CorrectedDuration = timeToCodeTimer.ElapsedMilliseconds;
+ ttcMetadata.Type = documentType;
+
+ Counters.TimeToCode.Inc ("SolutionLoaded", ttcMetadata);
+
+ timeToCodeSolutionTimer = null;
+
+ timeToCodeWorkspaceTimer = Stopwatch.StartNew ();
+ MonoDevelopWorkspace.LoadingFinished += CompleteTimeToIntellisense;
+ }
+
+ void CompleteTimeToIntellisense (object sender, EventArgs args)
+ {
+ // Reuse ttcMetadata, as it already has other information set.
+ MonoDevelopWorkspace.LoadingFinished -= CompleteTimeToIntellisense;
+
+ timeToCodeWorkspaceTimer.Stop ();
+ ttcMetadata.IntellisenseLoadTime = timeToCodeWorkspaceTimer.ElapsedMilliseconds;
+ ttcMetadata.CorrectedDuration += timeToCodeWorkspaceTimer.ElapsedMilliseconds;
+
+ Counters.TimeToIntellisense.Inc ("IntellisenseLoaded", ttcMetadata);
+ }
+
+ internal bool StartTimeToCodeLoadTimer ()
+ {
+ if (timeToCodeTimer.ElapsedTicks - startupTimer.ElapsedTicks > ttcDuration) {
+ LoggingService.LogDebug ($"Not starting TTC timer: {timeToCodeTimer.ElapsedTicks - startupTimer.ElapsedTicks}");
+ return false;
+ }
+ LoggingService.LogDebug ("Starting TTC timer");
+ timeToCodeSolutionTimer.Start ();
+
+ return true;
+ }
+
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs
index ddab4c2070..2a7dc180ab 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs
@@ -947,8 +947,8 @@ namespace MonoDevelop.Ide
}
AlertButton delete = new AlertButton (GettextCatalog.GetString ("Delete from Disk"));
- AlertButton result = MessageService.AskQuestion (question, secondaryText,
- delete, AlertButton.Cancel, AlertButton.Remove);
+ AlertButton result = MessageService.GenericAlert (MessageService.RootWindow, Gui.Stock.Question, question, secondaryText,
+ delete, AlertButton.Cancel, AlertButton.Remove);
if (result == delete) {
if (!workspace.RequestItemUnload (prj))
return;
diff --git a/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/MonoDevelopMetadataReferenceManager.MetadataReferenceCacheTests.cs b/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/MonoDevelopMetadataReferenceManager.MetadataReferenceCacheTests.cs
index 9c3fdf0c50..acfda97f5d 100644
--- a/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/MonoDevelopMetadataReferenceManager.MetadataReferenceCacheTests.cs
+++ b/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/MonoDevelopMetadataReferenceManager.MetadataReferenceCacheTests.cs
@@ -19,36 +19,40 @@ namespace MonoDevelop.Ide.TypeSystem
using (var sol = (MonoDevelop.Projects.Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile))
using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) {
- var manager = ws.MetadataReferenceManager;
- var cache = new MonoDevelopMetadataReferenceManager.MetadataReferenceCache ();
+ try {
+ var manager = ws.MetadataReferenceManager;
+ var cache = new MonoDevelopMetadataReferenceManager.MetadataReferenceCache ();
- // Create one with default assembly properties
- var asm = typeof (MonoDevelopMetadataReferenceManagerMetadataReferenceCacheTests).Assembly.Location;
- var item = cache.GetOrCreate (manager, asm, MetadataReferenceProperties.Assembly);
- Assert.IsNotNull (item);
+ // Create one with default assembly properties
+ var asm = typeof (MonoDevelopMetadataReferenceManagerMetadataReferenceCacheTests).Assembly.Location;
+ var item = cache.GetOrCreate (manager, asm, MetadataReferenceProperties.Assembly);
+ Assert.IsNotNull (item);
- var item2 = cache.GetOrCreate (manager, asm, MetadataReferenceProperties.Assembly);
- Assert.AreSame (item, item2, "Item that is in cache should be returned");
+ var item2 = cache.GetOrCreate (manager, asm, MetadataReferenceProperties.Assembly);
+ Assert.AreSame (item, item2, "Item that is in cache should be returned");
- // Create one with custom properties
- var item3 = cache.GetOrCreate (manager, asm, MetadataReferenceProperties.Assembly.WithAliases (new [] { "a" }));
- Assert.IsNotNull (item3);
+ // Create one with custom properties
+ var item3 = cache.GetOrCreate (manager, asm, MetadataReferenceProperties.Assembly.WithAliases (new [] { "a" }));
+ Assert.IsNotNull (item3);
- var item4 = cache.GetOrCreate (manager, asm, MetadataReferenceProperties.Assembly.WithAliases (new [] { "a" }));
- Assert.AreSame (item3, item4, "Item that is in cache should be returned");
+ var item4 = cache.GetOrCreate (manager, asm, MetadataReferenceProperties.Assembly.WithAliases (new [] { "a" }));
+ Assert.AreSame (item3, item4, "Item that is in cache should be returned");
- // Clear the cache, new items should be returned from now on.
- cache.ClearCache ();
+ // Clear the cache, new items should be returned from now on.
+ cache.ClearCache ();
- var item5 = cache.GetOrCreate (manager, asm, MetadataReferenceProperties.Assembly);
- Assert.IsNotNull (item5);
+ var item5 = cache.GetOrCreate (manager, asm, MetadataReferenceProperties.Assembly);
+ Assert.IsNotNull (item5);
- Assert.AreNotSame (item, item5, "Cache was cleared, so new item should be returned");
+ Assert.AreNotSame (item, item5, "Cache was cleared, so new item should be returned");
- var item6 = cache.GetOrCreate (manager, asm, MetadataReferenceProperties.Assembly.WithAliases (new [] { "a" }));
- Assert.AreNotSame (item3, item6, "Cache was cleared, so new item should be returned");
+ var item6 = cache.GetOrCreate (manager, asm, MetadataReferenceProperties.Assembly.WithAliases (new [] { "a" }));
+ Assert.AreNotSame (item3, item6, "Cache was cleared, so new item should be returned");
- cache.ClearCache ();
+ cache.ClearCache ();
+ } finally {
+ TypeSystemServiceTestExtensions.UnloadSolution (sol);
+ }
}
}
@@ -64,38 +68,42 @@ namespace MonoDevelop.Ide.TypeSystem
try {
using (var sol = (MonoDevelop.Projects.Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile))
using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) {
- var manager = ws.MetadataReferenceManager;
- var item = manager.GetOrCreateMetadataReference (tempPath, MetadataReferenceProperties.Assembly);
- Assert.IsNotNull (item);
+ try {
+ var manager = ws.MetadataReferenceManager;
+ var item = manager.GetOrCreateMetadataReference (tempPath, MetadataReferenceProperties.Assembly);
+ Assert.IsNotNull (item);
- await FileWatcherService.Update ();
+ await FileWatcherService.Update ();
- var initialId = item.CurrentSnapshot.GetMetadataId ();
+ var initialId = item.CurrentSnapshot.GetMetadataId ();
- var taskForNewAsm = WaitForSnapshotChange (item);
+ var taskForNewAsm = WaitForSnapshotChange (item);
- // Replace the assembly with another one.
- var newAsm = typeof (MonoDevelopMetadataReference).Assembly.Location;
- File.Copy (newAsm, tempPath, true);
+ // Replace the assembly with another one.
+ var newAsm = typeof (MonoDevelopMetadataReference).Assembly.Location;
+ File.Copy (newAsm, tempPath, true);
- var argsForNewAsm = await taskForNewAsm;
+ var argsForNewAsm = await taskForNewAsm;
- Assert.AreSame (item.CurrentSnapshot, argsForNewAsm.OldSnapshot);
+ Assert.AreSame (item.CurrentSnapshot, argsForNewAsm.OldSnapshot);
- Assert.AreNotSame (argsForNewAsm.OldSnapshot, argsForNewAsm.NewSnapshot.Value);
- // item.CurrentSnapshot is now updated
- Assert.AreNotEqual (initialId, item.CurrentSnapshot.GetMetadataId ());
+ Assert.AreNotSame (argsForNewAsm.OldSnapshot, argsForNewAsm.NewSnapshot.Value);
+ // item.CurrentSnapshot is now updated
+ Assert.AreNotEqual (initialId, item.CurrentSnapshot.GetMetadataId ());
- var taskForOldAsm = WaitForSnapshotChange (item);
- File.Copy (oldAsm, tempPath, true);
+ var taskForOldAsm = WaitForSnapshotChange (item);
+ File.Copy (oldAsm, tempPath, true);
- var argsForOldAsm = await taskForOldAsm;
+ var argsForOldAsm = await taskForOldAsm;
- Assert.AreSame (item.CurrentSnapshot, argsForOldAsm.OldSnapshot);
+ Assert.AreSame (item.CurrentSnapshot, argsForOldAsm.OldSnapshot);
- Assert.AreNotSame (argsForNewAsm.OldSnapshot, argsForNewAsm.NewSnapshot.Value);
- // Even though the old assembly was put back, it has a new id this time.
- Assert.AreNotEqual (initialId, item.CurrentSnapshot.GetMetadataId ());
+ Assert.AreNotSame (argsForNewAsm.OldSnapshot, argsForNewAsm.NewSnapshot.Value);
+ // Even though the old assembly was put back, it has a new id this time.
+ Assert.AreNotEqual (initialId, item.CurrentSnapshot.GetMetadataId ());
+ } finally {
+ TypeSystemServiceTestExtensions.UnloadSolution (sol);
+ }
}
await FileWatcherService.Update ();
diff --git a/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/MonoDevelopMetadataReferenceManagerTests.cs b/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/MonoDevelopMetadataReferenceManagerTests.cs
index 5aadf6ffc2..d9df5c66f7 100644
--- a/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/MonoDevelopMetadataReferenceManagerTests.cs
+++ b/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/MonoDevelopMetadataReferenceManagerTests.cs
@@ -41,7 +41,11 @@ namespace MonoDevelop.Ide.TypeSystem
using (Solution sol = (Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile))
using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) {
- Assert.IsNotNull (ws.MetadataReferenceManager);
+ try {
+ Assert.IsNotNull (ws.MetadataReferenceManager);
+ } finally {
+ TypeSystemServiceTestExtensions.UnloadSolution (sol);
+ }
}
}
}
diff --git a/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspaceTests.cs b/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspaceTests.cs
index ada621fff6..a067f3fef5 100644
--- a/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspaceTests.cs
+++ b/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspaceTests.cs
@@ -46,9 +46,9 @@ namespace MonoDevelop.Ide.TypeSystem
FilePath projFile = Util.GetSampleProject ("workspace-metadata-references", "workspace-metadata-references.sln");
- using (var sol = (MonoDevelop.Projects.Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), projFile)) {
- using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) {
-
+ using (var sol = (MonoDevelop.Projects.Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), projFile))
+ using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) {
+ try {
DotNetProject mainProject = null, libraryProject = null, libraryProject461 = null;
foreach (var project in sol.GetAllProjects ()) {
if (project.Name == "workspace-metadata-references")
@@ -65,6 +65,8 @@ namespace MonoDevelop.Ide.TypeSystem
// Also, add test for net461 to net47.
await AddAssemblyReference (ws, libraryProject, mainProject, "System.Messaging");
await AddAssemblyReference (ws, libraryProject461, mainProject, "System.ServiceModel");
+ } finally {
+ TypeSystemServiceTestExtensions.UnloadSolution (sol);
}
}
}
diff --git a/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/TypeSystemServiceTests.cs b/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/TypeSystemServiceTests.cs
index ba6141ad1b..7e724f9c54 100644
--- a/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/TypeSystemServiceTests.cs
+++ b/main/tests/Ide.Tests/MonoDevelop.Ide.TypeSystem/TypeSystemServiceTests.cs
@@ -57,12 +57,16 @@ namespace MonoDevelop.Ide.TypeSystem
using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile))
using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) {
- var project = sol.GetAllProjects ().Single ();
+ try {
+ var project = sol.GetAllProjects ().Single ();
- foreach (var file in project.Files) {
- Assert.IsNotNull (TypeSystemService.GetDocumentId (project, file.FilePath.ResolveLinks ()));
- if (file.FilePath.FileName.EndsWith ("SymlinkedFile.cs", StringComparison.Ordinal))
- Assert.IsNull (TypeSystemService.GetDocumentId (project, file.FilePath));
+ foreach (var file in project.Files) {
+ Assert.IsNotNull (TypeSystemService.GetDocumentId (project, file.FilePath.ResolveLinks ()));
+ if (file.FilePath.FileName.EndsWith ("SymlinkedFile.cs", StringComparison.Ordinal))
+ Assert.IsNull (TypeSystemService.GetDocumentId (project, file.FilePath));
+ }
+ } finally {
+ TypeSystemServiceTestExtensions.UnloadSolution (sol);
}
}
}
diff --git a/main/tests/Ide.Tests/MonoDevelop.Ide/RoslynSearchCategoryTests.cs b/main/tests/Ide.Tests/MonoDevelop.Ide/RoslynSearchCategoryTests.cs
index 07066e6a71..3c76bda394 100644
--- a/main/tests/Ide.Tests/MonoDevelop.Ide/RoslynSearchCategoryTests.cs
+++ b/main/tests/Ide.Tests/MonoDevelop.Ide/RoslynSearchCategoryTests.cs
@@ -55,21 +55,25 @@ namespace MonoDevelop.Ide
using (Solution sol = (Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile))
using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) {
- var results = await Search ("");
- Assert.AreEqual (0, results.Count);
-
- results = await Search ("M");
- Assert.AreEqual (6, results.Count);
-
- results = await Search ("type:M");
- Assert.AreEqual (3, results.Count);
-
- results = await Search ("My");
- // Should be 4: https://github.com/dotnet/roslyn/issues/29031
- Assert.AreEqual (2, results.Count);
-
- results = await Search ("MC");
- Assert.AreEqual (5, results.Count);
+ try {
+ var results = await Search ("");
+ Assert.AreEqual (0, results.Count);
+
+ results = await Search ("M");
+ Assert.AreEqual (6, results.Count);
+
+ results = await Search ("type:M");
+ Assert.AreEqual (3, results.Count);
+
+ results = await Search ("My");
+ // Should be 4: https://github.com/dotnet/roslyn/issues/29031
+ Assert.AreEqual (2, results.Count);
+
+ results = await Search ("MC");
+ Assert.AreEqual (5, results.Count);
+ } finally {
+ TypeSystemServiceTestExtensions.UnloadSolution (sol);
+ }
}
}
diff --git a/main/tests/Ide.Tests/MonoDevelop.Ide/TypeSystemServiceTests.cs b/main/tests/Ide.Tests/MonoDevelop.Ide/TypeSystemServiceTests.cs
index dc65094cbf..3f1224824d 100644
--- a/main/tests/Ide.Tests/MonoDevelop.Ide/TypeSystemServiceTests.cs
+++ b/main/tests/Ide.Tests/MonoDevelop.Ide/TypeSystemServiceTests.cs
@@ -36,10 +36,13 @@ using System.Threading.Tasks;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Host;
+using Microsoft.CodeAnalysis.IncrementalCaches;
+using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.CodeAnalysis.SolutionSize;
using System.IO;
using System.Collections.Immutable;
+using System.Text;
namespace MonoDevelop.Ide
{
@@ -106,8 +109,12 @@ namespace MonoDevelop.Ide
using (Solution sol = (Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile))
using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) {
- var storageLocationService = (MonoDevelopPersistentStorageLocationService)ws.Services.GetService<IPersistentStorageLocationService> ();
- Assert.That (storageLocationService.TryGetStorageLocation (ws.CurrentSolution.Id), Is.Not.Null.Or.Empty);
+ try {
+ var storageLocationService = (MonoDevelopPersistentStorageLocationService)ws.Services.GetService<IPersistentStorageLocationService> ();
+ Assert.That (storageLocationService.TryGetStorageLocation (ws.CurrentSolution.Id), Is.Not.Null.Or.Empty);
+ } finally {
+ TypeSystemServiceTestExtensions.UnloadSolution (sol);
+ }
}
}
@@ -118,35 +125,202 @@ namespace MonoDevelop.Ide
using (Solution sol = (Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile))
using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) {
- var storageLocationService = (MonoDevelopPersistentStorageLocationService)ws.Services.GetService<IPersistentStorageLocationService> ();
- var storageLocation = System.IO.Path.Combine (
- storageLocationService.TryGetStorageLocation (ws.CurrentSolution.Id),
- "sqlite3",
- "storage.ide");
-
- if (System.IO.File.Exists (storageLocation))
- System.IO.File.Delete (storageLocation);
-
- var solutionSizeTracker = (IIncrementalAnalyzerProvider)Composition.CompositionManager.GetExportedValue<ISolutionSizeTracker> ();
-
- // This will return the tracker, since it's a singleton.
- var analyzer = solutionSizeTracker.CreateIncrementalAnalyzer (ws);
-
- // We need this hack because we can't guess when the work coordinator will run the incremental analyzers.
- await analyzer.NewSolutionSnapshotAsync (ws.CurrentSolution, CancellationToken.None);
-
- foreach (var projectFile in sol.GetAllProjects ().SelectMany (x => x.Files.Where (file => file.BuildAction == BuildAction.Compile))) {
- var projectId = ws.GetProjectId (projectFile.Project);
- var docId = ws.GetDocumentId (projectId, projectFile.FilePath);
- var doc = ws.GetDocument (docId);
- if (!doc.SupportsSyntaxTree)
- continue;
-
- await Microsoft.CodeAnalysis.FindSymbols.SyntaxTreeIndex.PrecalculateAsync (doc, CancellationToken.None);
+ try {
+ var storageLocationService = (MonoDevelopPersistentStorageLocationService)ws.Services.GetService<IPersistentStorageLocationService> ();
+ var storageLocation = System.IO.Path.Combine (
+ storageLocationService.TryGetStorageLocation (ws.CurrentSolution.Id),
+ "sqlite3",
+ "storage.ide");
+
+ if (System.IO.File.Exists (storageLocation))
+ System.IO.File.Delete (storageLocation);
+
+ var solutionSizeTracker = (IIncrementalAnalyzerProvider)Composition.CompositionManager.GetExportedValue<ISolutionSizeTracker> ();
+
+ // This will return the tracker, since it's a singleton.
+ var analyzer = solutionSizeTracker.CreateIncrementalAnalyzer (ws);
+
+ // We need this hack because we can't guess when the work coordinator will run the incremental analyzers.
+ await analyzer.NewSolutionSnapshotAsync (ws.CurrentSolution, CancellationToken.None);
+
+ foreach (var projectFile in sol.GetAllProjects ().SelectMany (x => x.Files.Where (file => file.BuildAction == BuildAction.Compile))) {
+ var projectId = ws.GetProjectId (projectFile.Project);
+ var docId = ws.GetDocumentId (projectId, projectFile.FilePath);
+ var doc = ws.GetDocument (docId);
+ if (!doc.SupportsSyntaxTree)
+ continue;
+
+ await Microsoft.CodeAnalysis.FindSymbols.SyntaxTreeIndex.PrecalculateAsync (doc, CancellationToken.None);
+ }
+
+ var fi = new System.IO.FileInfo (storageLocation);
+ Assert.That (fi.Length, Is.GreaterThan (0));
+ } finally {
+ TypeSystemServiceTestExtensions.UnloadSolution (sol);
}
+ }
+ }
- var fi = new System.IO.FileInfo (storageLocation);
- Assert.That (fi.Length, Is.GreaterThan (0));
+ [Test]
+ public async Task TestWorkspacePersistentStorageImplementation ()
+ {
+ string solFile = Util.GetSampleProject ("console-project", "ConsoleProject.sln");
+ var streamName1 = "PersistentService_Solution_WriteReadDifferentInstances1";
+ var streamName2 = "PersistentService_Solution_WriteReadDifferentInstances2";
+
+ using (Solution sol = (Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile))
+ using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) {
+ try {
+ var persistentStorageService = ws.Services.GetService<IPersistentStorageService> ();
+ Assert.That (persistentStorageService, Is.TypeOf (typeof (Microsoft.CodeAnalysis.SQLite.SQLitePersistentStorageService)));
+
+ if (!(persistentStorageService is Microsoft.CodeAnalysis.SQLite.SQLitePersistentStorageService sqlitePersistentStorageService))
+ return;
+
+ var solutionSizeTracker = (IIncrementalAnalyzerProvider)Composition.CompositionManager.GetExportedValue<ISolutionSizeTracker> ();
+ // This will return the tracker, since it's a singleton.
+ var analyzer = solutionSizeTracker.CreateIncrementalAnalyzer (ws);
+
+ // We need this hack because we can't guess when the work coordinator will run the incremental analyzers.
+ await analyzer.NewSolutionSnapshotAsync (ws.CurrentSolution, CancellationToken.None);
+
+ // Due to the nature of roslyn returning a new wrapper every time we request the storage, do a reflection check.
+ const System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;
+ var fieldInfo = sqlitePersistentStorageService.GetType ().BaseType.GetField ("_currentPersistentStorage", flags);
+
+ using (var persistentStorage = sqlitePersistentStorageService.GetStorage (ws.CurrentSolution, checkBranchId: false)) {
+ Assert.That (persistentStorage, Is.Not.TypeOf (typeof (NoOpPersistentStorage)));
+
+ Assert.True (await persistentStorage.WriteStreamAsync (streamName1, EncodeString ("MyString")));
+ Assert.True (await persistentStorage.WriteStreamAsync (streamName2, EncodeString ("MyString2")));
+ }
+
+ var initialFieldValue = fieldInfo.GetValue (sqlitePersistentStorageService);
+
+ using (var persistentStorage = sqlitePersistentStorageService.GetStorage (ws.CurrentSolution, checkBranchId: false)) {
+ Assert.That (persistentStorage, Is.Not.TypeOf (typeof (NoOpPersistentStorage)));
+ }
+
+ var secondFieldValue = fieldInfo.GetValue (sqlitePersistentStorageService);
+
+ Assert.AreSame (initialFieldValue, secondFieldValue);
+
+ using (var persistentStorage = sqlitePersistentStorageService.GetStorage (ws.CurrentSolution, checkBranchId: false)) {
+ Assert.AreEqual ("MyString", ReadStringToEnd (await persistentStorage.ReadStreamAsync (streamName1)));
+ Assert.AreEqual ("MyString2", ReadStringToEnd (await persistentStorage.ReadStreamAsync (streamName2)));
+ }
+
+ } finally {
+ TypeSystemServiceTestExtensions.UnloadSolution (sol);
+ }
+ }
+
+ Stream EncodeString (string text)
+ {
+ var bytes = Encoding.UTF8.GetBytes (text);
+ var stream = new MemoryStream (bytes);
+ return stream;
+ }
+
+ string ReadStringToEnd (Stream stream)
+ {
+ using (stream) {
+ var bytes = new byte [stream.Length];
+ int count = 0;
+ while (count < stream.Length) {
+ count = stream.Read (bytes, count, (int)stream.Length - count);
+ }
+
+ return Encoding.UTF8.GetString (bytes);
+ }
+ }
+ }
+
+ [Test]
+ public async Task TestStorageDataIsNotRecomputed ()
+ {
+ string solFile = Util.GetSampleProject ("console-project", "ConsoleProject.sln");
+
+ var checkSum1 = await RunTest (usedCache: false);
+ var checkSum2 = await RunTest (usedCache: true);
+
+ Assert.AreEqual (checkSum1, checkSum2);
+
+ async Task<Microsoft.CodeAnalysis.Checksum> RunTest (bool usedCache)
+ {
+ var initial = Logger.GetLogger ();
+
+ using (Solution sol = (Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile))
+ using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) {
+ try {
+ var persistentStorageService = ws.Services.GetService<IPersistentStorageService> ();
+ Assert.That (persistentStorageService, Is.TypeOf (typeof (Microsoft.CodeAnalysis.SQLite.SQLitePersistentStorageService)));
+
+ if (!(persistentStorageService is Microsoft.CodeAnalysis.SQLite.SQLitePersistentStorageService sqlitePersistentStorageService))
+ return null;
+
+ var solutionSizeTracker = (IIncrementalAnalyzerProvider)Composition.CompositionManager.GetExportedValue<ISolutionSizeTracker> ();
+ // This will return the tracker, since it's a singleton.
+ var analyzer = solutionSizeTracker.CreateIncrementalAnalyzer (ws);
+
+ // We need this hack because we can't guess when the work coordinator will run the incremental analyzers.
+ await analyzer.NewSolutionSnapshotAsync (ws.CurrentSolution, CancellationToken.None);
+
+ var storageLogger = new StorageCheckingLogger ();
+ var aggregateLogger = AggregateLogger.Create (initial, storageLogger);
+ Logger.SetLogger (aggregateLogger);
+
+ var provider = new SymbolTreeInfoIncrementalAnalyzerProvider ();
+ var cacheService = (Microsoft.CodeAnalysis.FindSymbols.SymbolTree.ISymbolTreeInfoCacheService)provider.CreateService (ws.Services);
+
+ var incrementalAnalyzer = provider.CreateIncrementalAnalyzer (ws);
+
+ var project = sol.GetAllProjects ().Single ();
+ var roslynProject = TypeSystemService.GetProject (project);
+
+ await incrementalAnalyzer.AnalyzeProjectAsync (roslynProject, default, default, CancellationToken.None);
+
+ Assert.That (storageLogger.QueriedCount, Is.GreaterThan (0));
+ if (usedCache) {
+ Assert.AreEqual (storageLogger.QueriedCount, storageLogger.UsedCacheCount);
+ } else
+ Assert.AreEqual (storageLogger.QueriedCount, storageLogger.CreatedCount);
+
+ Assert.IsNotNull (await cacheService.TryGetSourceSymbolTreeInfoAsync (roslynProject, CancellationToken.None));
+
+ return await Microsoft.CodeAnalysis.FindSymbols.SymbolTreeInfo.GetSourceSymbolsChecksumAsync (roslynProject, CancellationToken.None);
+ } finally {
+ Logger.SetLogger (initial);
+ TypeSystemServiceTestExtensions.UnloadSolution (sol);
+ }
+ }
+ }
+ }
+
+ class StorageCheckingLogger : ILogger
+ {
+ public int QueriedCount { get; private set; }
+ public int CreatedCount { get; private set; }
+ public int UsedCacheCount => QueriedCount - CreatedCount;
+
+ public bool IsEnabled (FunctionId functionId) => true;
+
+ public void Log (FunctionId functionId, LogMessage logMessage)
+ {
+ // nothing
+ }
+
+ public void LogBlockEnd (FunctionId functionId, LogMessage logMessage, int uniquePairId, int delta, CancellationToken cancellationToken)
+ {
+ // nothing
+ }
+
+ public void LogBlockStart (FunctionId functionId, LogMessage logMessage, int uniquePairId, CancellationToken cancellationToken)
+ {
+ if (functionId == FunctionId.SymbolTreeInfo_TryLoadOrCreate)
+ QueriedCount++;
+ else if (functionId == FunctionId.SymbolTreeInfo_Create)
+ CreatedCount++;
}
}
@@ -292,9 +466,9 @@ namespace MonoDevelop.Ide
newParsers.Add (projectionParser);
TypeSystemService.Parsers = newParsers;
- using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile)) {
- using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) {
-
+ using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile))
+ using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) {
+ try {
var source1 = new CancellationTokenSource ();
var source2 = new CancellationTokenSource ();
@@ -314,6 +488,8 @@ namespace MonoDevelop.Ide
Assert.IsNotNull (result2);
Assert.IsNull (result1);
+ } finally {
+ TypeSystemServiceTestExtensions.UnloadSolution (sol);
}
}
} finally {
diff --git a/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Core.Tests.csproj b/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Core.Tests.csproj
index 49f66ee13b..0dd4c0da4d 100644
--- a/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Core.Tests.csproj
+++ b/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Core.Tests.csproj
@@ -119,6 +119,7 @@
<Compile Include="MonoDevelop.Core\FileServiceEventQueueTests.cs" />
<Compile Include="MonoDevelop.Core\FileServiceEventStateMachineTests.cs" />
<Compile Include="MonoDevelop.Projects\AsyncCriticalSectionTests.cs" />
+ <Compile Include="MonoDevelop.Core\UserProfileTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\core\MonoDevelop.Core\MonoDevelop.Core.csproj">
diff --git a/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Core/UserProfileTests.cs b/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Core/UserProfileTests.cs
new file mode 100644
index 0000000000..8a92b9fe5d
--- /dev/null
+++ b/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Core/UserProfileTests.cs
@@ -0,0 +1,39 @@
+//
+// UserProfileTests.cs
+//
+// Author:
+// Marius Ungureanu <maungu@microsoft.com>
+//
+// Copyright (c) 2019 Microsoft Inc.
+//
+// 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 NUnit.Framework;
+namespace MonoDevelop.Core
+{
+ [TestFixture]
+ public class UserProfileTests
+ {
+ [Test]
+ public void TestCurrentVersionWillMigrate ()
+ {
+ Assert.That (UserProfile.ProfileVersions, Contains.Item (BuildInfo.CompatVersion));
+ }
+ }
+}
diff --git a/main/tests/StressTest/MonoDevelop.StressTest/IEditorTestScenario.cs b/main/tests/StressTest/MonoDevelop.StressTest/IEditorTestScenario.cs
new file mode 100644
index 0000000000..180512c019
--- /dev/null
+++ b/main/tests/StressTest/MonoDevelop.StressTest/IEditorTestScenario.cs
@@ -0,0 +1,16 @@
+using System;
+namespace MonoDevelop.StressTest
+{
+ public enum EditorTestRun
+ {
+ Legacy,
+ VSEditor,
+ Both,
+ Default = Legacy,
+ }
+
+ public interface IEditorTestScenario : ITestScenario
+ {
+ EditorTestRun EditorRunConfiguration { get; }
+ }
+}
diff --git a/main/tests/StressTest/MonoDevelop.StressTest/Profiler/LeakProcessor.cs b/main/tests/StressTest/MonoDevelop.StressTest/Profiler/LeakProcessor.cs
index 30c5cc5de6..fe7e720522 100644
--- a/main/tests/StressTest/MonoDevelop.StressTest/Profiler/LeakProcessor.cs
+++ b/main/tests/StressTest/MonoDevelop.StressTest/Profiler/LeakProcessor.cs
@@ -47,7 +47,7 @@ namespace MonoDevelop.StressTest
if (heapshot == null)
return;
- // TODO: Make this async.
+ // TODO: Make this async. Each heapshot will add time to the current test run.
var previousData = result.Iterations.LastOrDefault ();
var leakedObjects = DetectLeakedObjects (heapshot, isCleanup, previousData, iterationName);
diff --git a/main/tests/StressTest/MonoDevelop.StressTest/Profiler/TestScenarioLeakExtensions.cs b/main/tests/StressTest/MonoDevelop.StressTest/Profiler/TestScenarioLeakExtensions.cs
index 578a4c2fe8..4066e0d091 100644
--- a/main/tests/StressTest/MonoDevelop.StressTest/Profiler/TestScenarioLeakExtensions.cs
+++ b/main/tests/StressTest/MonoDevelop.StressTest/Profiler/TestScenarioLeakExtensions.cs
@@ -37,7 +37,7 @@ namespace MonoDevelop.StressTest
var attributes = member.GetCustomAttributes<NoLeakAttribute> (true).ToDictionary (x => x.TypeName, x => x);
- // TODO: Ensure that we don't leak, so add GtkWidgetResult results, as they can cause retention of UI widgets.
+ // Ensure that we don't leak, so add GtkWidgetResult results, as they can cause retention of UI widgets.
attributes.Add (autoTest, new NoLeakAttribute (autoTest));
return attributes;
diff --git a/main/tests/StressTest/MonoDevelop.StressTest/Scenarios/DefaultScenario.cs b/main/tests/StressTest/MonoDevelop.StressTest/Scenarios/DefaultScenario.cs
index aebfc6c729..af00f9f26d 100644
--- a/main/tests/StressTest/MonoDevelop.StressTest/Scenarios/DefaultScenario.cs
+++ b/main/tests/StressTest/MonoDevelop.StressTest/Scenarios/DefaultScenario.cs
@@ -34,7 +34,7 @@ using UserInterfaceTests;
namespace MonoDevelop.StressTest
{
[NoLeak(typeof (Projects.Solution))]
- public class DefaultScenario : ITestScenario
+ public class DefaultScenario : IEditorTestScenario
{
List<FilePath> filesToOpen;
@@ -64,6 +64,8 @@ namespace MonoDevelop.StressTest
bool firstRun = true;
[NoLeak ("MonoDevelop.SourceEditor.ExtensibleTextEditor")]
+ [NoLeak ("Microsoft.VisualStudio.Text.Editor.Implementation.CocoaTextViewControl")] // vs-editor-core part of the chain
+ [NoLeak ("MonoDevelop.TextEditor.CocoaTextViewContent")] // MD part of the chain.
public void Run ()
{
if (firstRun) {
@@ -109,5 +111,7 @@ namespace MonoDevelop.StressTest
// Close all documents.
WorkbenchExtensions.CloseAllOpenFiles ();
}
+
+ public EditorTestRun EditorRunConfiguration { get; } = EditorTestRun.Default;
}
}
diff --git a/main/tests/StressTest/MonoDevelop.StressTest/StressTestApp.cs b/main/tests/StressTest/MonoDevelop.StressTest/StressTestApp.cs
index 488c6824f6..4834ff3260 100644
--- a/main/tests/StressTest/MonoDevelop.StressTest/StressTestApp.cs
+++ b/main/tests/StressTest/MonoDevelop.StressTest/StressTestApp.cs
@@ -84,14 +84,47 @@ namespace MonoDevelop.StressTest
leakProcessor = new LeakProcessor (scenario, ProfilerOptions);
- ReportMemoryUsage (setupIteration);
+ ReportMemoryUsage ("Setup");
+ RunTestScenario ();
+
+ UserInterfaceTests.Ide.CloseAll (exit: false);
+ ReportMemoryUsage ("Cleanup");
+ }
+
+ void RunTestScenario ()
+ {
+ string suffix = string.Empty;
+ if (scenario is IEditorTestScenario editorTestScenario) {
+ var configuration = editorTestScenario.EditorRunConfiguration;
+ switch (configuration) {
+ case EditorTestRun.Legacy:
+ Properties.UseNewEditor = false;
+ suffix = "_Legacy";
+ break;
+ case EditorTestRun.VSEditor:
+ Properties.UseNewEditor = true;
+ suffix = "_VSEditor";
+ break;
+ case EditorTestRun.Both:
+ // Run once with legacy
+ Properties.UseNewEditor = false;
+ RunScenarioIterations ("_Legacy");
+
+ Properties.UseNewEditor = true;
+ suffix = "_VSEditor";
+ break;
+ }
+ }
+
+ RunScenarioIterations (suffix);
+ }
+
+ void RunScenarioIterations(string suffix)
+ {
for (int i = 0; i < Iterations; ++i) {
scenario.Run ();
- ReportMemoryUsage (i);
+ ReportMemoryUsage ($"Run_{i}_{suffix}");
}
-
- UserInterfaceTests.Ide.CloseAll (exit: false);
- ReportMemoryUsage (cleanupIteration);
}
bool StartWithProfiler (string profilePath, string logFile)
@@ -177,7 +210,7 @@ namespace MonoDevelop.StressTest
}
}
- void ReportMemoryUsage (int iteration)
+ void ReportMemoryUsage (string iterationName)
{
//Make sure IDE stops doing what it was doing
UserInterfaceTests.Ide.WaitForIdeIdle ();
@@ -191,15 +224,6 @@ namespace MonoDevelop.StressTest
var memoryStats = TestService.Session.MemoryStats;
- string iterationName;
- if (iteration == cleanupIteration) {
- iterationName = "Cleanup";
- } else if (iteration == setupIteration) {
- iterationName = "Setup";
- } else {
- iterationName = string.Format ("Run_{0}", iteration + 1);
- }
-
Console.WriteLine (iterationName);
Console.WriteLine (" NonPagedSystemMemory: " + memoryStats.NonPagedSystemMemory);
@@ -212,7 +236,7 @@ namespace MonoDevelop.StressTest
Console.WriteLine ();
- leakProcessor.Process (heapshot, iteration == cleanupIteration, iterationName, memoryStats);
+ leakProcessor.Process (heapshot, iterationName == "Cleanup", iterationName, memoryStats);
}
}
}
diff --git a/main/tests/StressTest/StressTest.csproj b/main/tests/StressTest/StressTest.csproj
index 8023693313..4db6a8945f 100644
--- a/main/tests/StressTest/StressTest.csproj
+++ b/main/tests/StressTest/StressTest.csproj
@@ -95,6 +95,8 @@
<Compile Include="MonoDevelop.StressTest\Profiler\LeakProcessor.cs" />
<Compile Include="MonoDevelop.StressTest\Profiler\TestScenarioLeakExtensions.cs" />
<Compile Include="MonoDevelop.StressTest\Profiler\GraphExtensions.cs" />
+ <Compile Include="MonoDevelop.StressTest\IEditorTestScenario.cs" />
+ <Compile Include="UserInterfaceTests\Properties.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="MonoDevelop.StressTest.Attributes\" />
diff --git a/main/tests/StressTest/UserInterfaceTests/Properties.cs b/main/tests/StressTest/UserInterfaceTests/Properties.cs
new file mode 100644
index 0000000000..62eea0c8c2
--- /dev/null
+++ b/main/tests/StressTest/UserInterfaceTests/Properties.cs
@@ -0,0 +1,15 @@
+using System;
+using UserInterfaceTests;
+
+namespace MonoDevelop.StressTest
+{
+ public static class Properties
+ {
+ const string useNewEditorProperty = "MonoDevelop.Ide.Editor.DefaultSourceEditorOptions.Instance.EnableNewEditor";
+
+ public static bool UseNewEditor {
+ get => TestService.Session.GetGlobalValue<bool> (useNewEditorProperty);
+ set => TestService.Session.SetGlobalValue (useNewEditorProperty, value);
+ }
+ }
+}
diff --git a/main/tests/StressTest/UserInterfaceTests/WorkbenchExtensions.cs b/main/tests/StressTest/UserInterfaceTests/WorkbenchExtensions.cs
index aa7ac36224..7cdb9217a3 100644
--- a/main/tests/StressTest/UserInterfaceTests/WorkbenchExtensions.cs
+++ b/main/tests/StressTest/UserInterfaceTests/WorkbenchExtensions.cs
@@ -69,7 +69,7 @@ namespace UserInterfaceTests
return isPass == Workbench.IsBuildSuccessful (timeoutInSecs);
}
- public static bool Debug (int timeoutSeconds = 20, int pollStepSecs = 5)
+ public static bool Debug (int timeoutSeconds = 20, int pollStepSecs = 1)
{
Session.ExecuteCommand ("MonoDevelop.Debugger.DebugCommands.Debug");
try {
diff --git a/main/tests/UserInterfaceTests/Ide.cs b/main/tests/UserInterfaceTests/Ide.cs
index 45f4d5dc67..ef60b49e90 100644
--- a/main/tests/UserInterfaceTests/Ide.cs
+++ b/main/tests/UserInterfaceTests/Ide.cs
@@ -71,17 +71,12 @@ namespace UserInterfaceTests
public static void WaitUntil (Func<bool> done, int timeout = 20000, int pollStep = 200, Func<string> timeoutMessage = null)
{
- do {
- if (done ())
- return;
- timeout -= pollStep;
- Thread.Sleep (pollStep);
- } while (timeout > 0);
-
- if (timeoutMessage != null) {
- throw new TimeoutException ("Timed out waiting for Function: " + done.Method.Name + " Message: " + timeoutMessage ());
- } else {
- throw new TimeoutException ("Timed out waiting for Function: " + done.Method.Name);
+ try {
+ PollTimer (timeout, pollStep, done);
+ } catch (TimeoutException) {
+ // Replace the exception with another one.
+ var suffix = timeoutMessage != null ? " Message: " + timeoutMessage () : string.Empty;
+ throw new TimeoutException ("Timed out waiting for Function: " + done.Method.Name + suffix);
}
}
@@ -122,7 +117,7 @@ namespace UserInterfaceTests
public readonly static Action EmptyAction = delegate { };
- static string[] waitForNuGetMessages = {
+ static readonly string[] waitForNuGetMessages = {
"Package updates are available.",
"Packages are up to date.",
"No updates found but warnings were reported.",
@@ -132,21 +127,21 @@ namespace UserInterfaceTests
"Packages updated with warnings."};
public readonly static Action WaitForPackageUpdate = delegate {
- WaitForStatusMessage (waitForNuGetMessages, timeoutInSecs: 180, pollStepInSecs: 5);
+ WaitForStatusMessage (waitForNuGetMessages, timeoutInSecs: 180, pollStepInSecs: 1);
};
public static void WaitForPackageUpdateExtra (List<string> otherMessages)
{
otherMessages.AddRange (waitForNuGetMessages);
- WaitForStatusMessage (otherMessages.ToArray (), timeoutInSecs: 180, pollStepInSecs: 5);
+ WaitForStatusMessage (otherMessages.ToArray (), timeoutInSecs: 180, pollStepInSecs: 1);
}
public readonly static Action WaitForSolutionCheckedOut = delegate {
- WaitForStatusMessage (new [] {"Solution checked out", "Solution Loaded."}, timeoutInSecs: 360, pollStepInSecs: 5);
+ WaitForStatusMessage (new [] {"Solution checked out", "Solution Loaded."}, timeoutInSecs: 360, pollStepInSecs: 1);
};
public readonly static Action WaitForSolutionLoaded = delegate {
- WaitForStatusMessage (new [] {"Project saved.", "Solution loaded."}, timeoutInSecs: 120, pollStepInSecs: 5);
+ WaitForStatusMessage (new [] {"Project saved.", "Solution loaded."}, timeoutInSecs: 120, pollStepInSecs: 1);
};
public static void WaitForStatusMessage (string[] statusMessage, int timeoutInSecs = 240, int pollStepInSecs = 1)
@@ -177,7 +172,7 @@ namespace UserInterfaceTests
timeoutMessage: () => "GetStatusMessage=" + Workbench.GetStatusMessage ());
}
- static readonly List<string> ignoreStatusMessgaes = new List<string> {
+ static readonly List<string> globalIgnoreStatusMessages = new List<string> {
"Saving...",
"Restoring packages for solution...",
"Restoring packages before update...",
@@ -186,46 +181,58 @@ namespace UserInterfaceTests
"Updating packages in project..."
};
- public static void WaitForIdeIdle (uint totalTimeoutInSecs = 100, uint idlePeriodInSecs = 10, string[] ignoreMessages = null)
+ public static void WaitForIdeIdle (uint totalTimeoutInSecs = 100, uint idlePeriodInSecs = 1, string[] ignoreMessages = null)
{
- uint retriesLeft = (uint)Math.Ceiling ((double)totalTimeoutInSecs/(double)idlePeriodInSecs);
- ManualResetEvent resetEvent = new ManualResetEvent (false);
+ var ignoreStatusMessages = globalIgnoreStatusMessages.ToList ();
if (ignoreMessages != null)
- ignoreStatusMessgaes.AddRange (ignoreMessages);
-
- var timer = new System.Timers.Timer {
- Interval = idlePeriodInSecs * 1000,
- AutoReset = true
- };
- bool didTimeout = false;
+ ignoreStatusMessages.AddRange (ignoreMessages);
var initialStatusMessage = Workbench.GetStatusMessage (waitForNonEmpty: false);
- timer.Elapsed += (sender, e) => {
- if (retriesLeft == 0) {
- didTimeout = true;
- resetEvent.Set ();
- }
-
+ PollTimer ((int)totalTimeoutInSecs * 1000, (int)idlePeriodInSecs * 1000, () => {
var finalStatusMessage = Workbench.GetStatusMessage (waitForNonEmpty: false);
- var isIdle = string.Equals (initialStatusMessage, finalStatusMessage) && !ignoreStatusMessgaes.Contains (finalStatusMessage);
+ var isIdle = string.Equals (initialStatusMessage, finalStatusMessage) && !ignoreStatusMessages.Contains (finalStatusMessage);
- if (!isIdle) {
- retriesLeft--;
+ if (!isIdle)
initialStatusMessage = finalStatusMessage;
- }
- if (isIdle) {
- resetEvent.Set ();
- }
- };
+ return isIdle;
+ });
+ }
- timer.Start ();
- resetEvent.WaitOne ();
- timer.Stop ();
- timer.AutoReset = false;
- timer.Dispose ();
+ static void PollTimer (int timeout, int interval, Func<bool> checkIsDone)
+ {
+ uint retriesLeft = (uint)Math.Ceiling ((double)timeout / interval);
+ var resetEvent = new ManualResetEvent (false);
- if (didTimeout)
- throw new TimeoutException ("Timeout waiting for IDE to be ready and idle");
+ var timer = new System.Timers.Timer {
+ Interval = interval,
+ AutoReset = true
+ };
+
+ using (timer)
+ using (resetEvent) {
+ bool didTimeout = false;
+
+ timer.Elapsed += (sender, e) => {
+ if (retriesLeft == 0) {
+ didTimeout = true;
+ resetEvent.Set ();
+ return;
+ }
+
+ bool done = checkIsDone ();
+ if (!done) {
+ retriesLeft--;
+ } else
+ resetEvent.Set ();
+ };
+
+ timer.Start ();
+ resetEvent.WaitOne ();
+ timer.Stop ();
+
+ if (didTimeout)
+ throw new TimeoutException ("Timeout waiting for IDE to be ready and idle");
+ }
}
}
diff --git a/main/tests/UserInterfaceTests/IdeQuery.cs b/main/tests/UserInterfaceTests/IdeQuery.cs
index dc1a4a6548..317b7f34e6 100644
--- a/main/tests/UserInterfaceTests/IdeQuery.cs
+++ b/main/tests/UserInterfaceTests/IdeQuery.cs
@@ -31,14 +31,6 @@ namespace UserInterfaceTests
{
public static class IdeQuery
{
- readonly static Func<AppQuery, AppQuery> _defaultWorkbench = c => c.Window ().Marked ("MonoDevelop.Ide.Gui.DefaultWorkbench");
- readonly static Func<AppQuery, AppQuery> _newFileDialog = c => c.Window ().Marked ("MonoDevelop.Ide.Projects.NewFileDialog");
- readonly static Func<AppQuery, AppQuery> _gitConfigurationDialog = c => c.Window ().Marked ("MonoDevelop.VersionControl.Git.GitConfigurationDialog");
- readonly static Func<AppQuery, AppQuery> _editRemoteDialog = c => c.Window ().Marked ("MonoDevelop.VersionControl.Git.EditRemoteDialog");
- readonly static Func<AppQuery, AppQuery> _editBranchDialog = c => c.Window ().Marked ("MonoDevelop.VersionControl.Git.EditBranchDialog");
- readonly static Func<AppQuery, AppQuery> _textArea = c => c.Window ().Children ().Marked ("Mono.TextEditor.TextArea");
- readonly static Func<AppQuery, AppQuery> _xamarinUpdate = c => c.Marked ("Visual Studio Update");
-
readonly static Func<AppQuery, AppQuery> _macRunButton = c => c.Marked ("MonoDevelop.MacIntegration.MainToolbar.RunButton");
public static Func<AppQuery, AppQuery> RunButton
@@ -50,54 +42,20 @@ namespace UserInterfaceTests
}
}
- public static Func<AppQuery, AppQuery> DefaultWorkbench
- {
- get {
- return _defaultWorkbench;
- }
- }
+ public static Func<AppQuery, AppQuery> DefaultWorkbench { get; } = c => c.Window ().Marked ("MonoDevelop.Ide.Gui.DefaultWorkbench");
- public static Func<AppQuery, AppQuery> NewFileDialog
- {
- get {
- return _newFileDialog;
- }
- }
+ public static Func<AppQuery, AppQuery> NewFileDialog { get; } = c => c.Window ().Marked ("MonoDevelop.Ide.Projects.NewFileDialog");
- public static Func<AppQuery, AppQuery> GitConfigurationDialog
- {
- get {
- return _gitConfigurationDialog;
- }
- }
+ public static Func<AppQuery, AppQuery> GitConfigurationDialog { get; } = c => c.Window ().Marked ("MonoDevelop.VersionControl.Git.GitConfigurationDialog");
- public static Func<AppQuery, AppQuery> EditRemoteDialog
- {
- get {
- return _editRemoteDialog;
- }
- }
+ public static Func<AppQuery, AppQuery> EditRemoteDialog { get; } = c => c.Window ().Marked ("MonoDevelop.VersionControl.Git.EditRemoteDialog");
- public static Func<AppQuery, AppQuery> EditBranchDialog
- {
- get {
- return _editBranchDialog;
- }
- }
+ public static Func<AppQuery, AppQuery> EditBranchDialog { get; } = c => c.Window ().Marked ("MonoDevelop.VersionControl.Git.EditBranchDialog");
- public static Func<AppQuery, AppQuery> TextArea
- {
- get {
- return _textArea;
- }
- }
+ // TODO: Implement this for the cocoa editor, as we aren't going through a TextArea.
+ public static Func<AppQuery, AppQuery> TextArea { get; } = c => c.Window ().Children ().Marked ("Mono.TextEditor.TextArea");
- public static Func<AppQuery, AppQuery> XamarinUpdate
- {
- get {
- return _xamarinUpdate;
- }
- }
+ public static Func<AppQuery, AppQuery> XamarinUpdate { get; } = c => c.Marked ("Visual Studio Update");
}
}
diff --git a/main/tests/UserInterfaceTests/Workbench.cs b/main/tests/UserInterfaceTests/Workbench.cs
index bae6f11a74..d59a6757ab 100644
--- a/main/tests/UserInterfaceTests/Workbench.cs
+++ b/main/tests/UserInterfaceTests/Workbench.cs
@@ -45,20 +45,22 @@ namespace UserInterfaceTests
public static string GetStatusMessage (int timeout = 20000, bool waitForNonEmpty = true)
{
if (Platform.IsMac) {
+ const string macStatusTextField = "MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.text";
if (waitForNonEmpty) {
Ide.WaitUntil (
- () => Session.GetGlobalValue<string> ("MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.text") != string.Empty,
+ () => Session.GetGlobalValue<string> (macStatusTextField) != string.Empty,
timeout
);
}
- return (string)Session.GetGlobalValue ("MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.text");
+ return (string)Session.GetGlobalValue (macStatusTextField);
}
if (waitForNonEmpty) {
+ const string gtkStatusMessageCount = "MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.messageQueue.Count";
Ide.WaitUntil (
- () => Session.GetGlobalValue<int> ("MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.messageQueue.Count") == 0,
+ () => Session.GetGlobalValue<int> (gtkStatusMessageCount) == 0,
timeout,
- timeoutMessage: ()=> "MessageQueue.Count="+Session.GetGlobalValue<int> ("MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.messageQueue.Count")
+ timeoutMessage: ()=> "MessageQueue.Count=" + Session.GetGlobalValue<int> (gtkStatusMessageCount)
);
}
return (string) Session.GetGlobalValue ("MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.renderArg.CurrentText");
@@ -85,7 +87,7 @@ namespace UserInterfaceTests
);
}
- // TODO:
+ throw new NotImplementedException ("Gtk backend not implemented");
}
public static bool IsBuildSuccessful (int timeoutInSecs)
@@ -115,7 +117,7 @@ namespace UserInterfaceTests
return isBuildSuccessful;
}
- public static bool Run (int timeoutSeconds = 20, int pollStepSecs = 5)
+ public static bool Run (int timeoutSeconds = 20, int pollStepSecs = 1)
{
Session.ExecuteCommand (ProjectCommands.Run);
try {
@@ -130,8 +132,7 @@ namespace UserInterfaceTests
public static void OpenWorkspace (string solutionPath, UITestBase testContext = null)
{
- if (testContext != null)
- testContext.ReproStep (string.Format ("Open solution path '{0}'", solutionPath));
+ testContext?.ReproStep (string.Format ("Open solution path '{0}'", solutionPath));
Action<string> takeScreenshot = GetScreenshotAction (testContext);
Session.GlobalInvoke ("MonoDevelop.Ide.IdeApp.Workspace.OpenWorkspaceItem", new FilePath (solutionPath), true);
Ide.WaitForIdeIdle ();
@@ -140,8 +141,7 @@ namespace UserInterfaceTests
public static void CloseWorkspace (UITestBase testContext = null)
{
- if (testContext != null)
- testContext.ReproStep ("Close current workspace");
+ testContext?.ReproStep ("Close current workspace");
Action<string> takeScreenshot = GetScreenshotAction (testContext);
takeScreenshot ("About-To-Close-Workspace");
Session.ExecuteCommand (FileCommands.CloseWorkspace);
@@ -150,8 +150,7 @@ namespace UserInterfaceTests
public static void CloseDocument (UITestBase testContext = null)
{
- if (testContext != null)
- testContext.ReproStep ("Close current workspace");
+ testContext?.ReproStep ("Close current workspace");
Action<string> takeScreenshot = GetScreenshotAction (testContext);
takeScreenshot ("About-To-Close-Workspace");
Session.ExecuteCommand (FileCommands.CloseFile);