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/src
diff options
context:
space:
mode:
authorMatt Ward <ward.matt@gmail.com>2018-02-22 14:08:59 +0300
committerGitHub <noreply@github.com>2018-02-22 14:08:59 +0300
commitae72d9874e58db5aa4e75d00808ff4a42a35b9ac (patch)
tree54aee6d1e857d1c2f95b4f3539f81a5e1b48dff6 /main/src
parent0e6e5f5ce3306f64fa50361288da3d14235a994e (diff)
parent8582d83924f5aade53bdff0d09c54a980b318b35 (diff)
Merge pull request #3690 from mono/quality-telemetry-phase2
Quality telemetry - phase 2
Diffstat (limited to 'main/src')
-rw-r--r--main/src/addins/CSharpBinding/CSharpBinding.csproj3
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CSharpCompletionTextEditorExtension.cs2
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/GotoDefinition/GotoDefinitionService.cs16
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/Counters.cs69
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindBaseSymbolsHandler.cs38
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindDerivedSymbolsHandler.cs32
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindExtensionMethodsHandler.cs33
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindImplementingMembersHandler.cs40
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindMemberOverloadsHandler.cs34
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/FindReferencesHandler.cs11
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/GotoBaseDeclarationHandler.cs38
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/RefactoryCommands.cs2
-rw-r--r--main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeDebuggerSession.cs6
-rw-r--r--main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeBacktrace.cs29
-rw-r--r--main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeObjectSource.cs17
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj1
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Counters.cs36
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs75
-rw-r--r--main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs36
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj1
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/Counters.cs1
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/ExtensibleTextEditor.cs18
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/TextEditorKeyPressTimings.cs96
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/CompletionTextEditorExtension.cs32
24 files changed, 581 insertions, 85 deletions
diff --git a/main/src/addins/CSharpBinding/CSharpBinding.csproj b/main/src/addins/CSharpBinding/CSharpBinding.csproj
index 9f002f7d3d..ee7265d81a 100644
--- a/main/src/addins/CSharpBinding/CSharpBinding.csproj
+++ b/main/src/addins/CSharpBinding/CSharpBinding.csproj
@@ -1,4 +1,4 @@
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Import Project="..\..\..\MonoDevelop.props" />
<Import Project="$(ReferencesVSEditor)" />
<PropertyGroup>
@@ -397,6 +397,7 @@
<Compile Include="MonoDevelop.CSharp.Completion\CSharpCompletionData.cs" />
<Compile Include="MonoDevelop.CSharp.Completion\CompletionProvider\ProtocolMemberCompletionProvider.cs" />
<Compile Include="MonoDevelop.CSharp.Tooltips\QuickInfoProvider.cs" />
+ <Compile Include="MonoDevelop.CSharp.Navigation\Counters.cs" />
<Compile Include="MonoDevelop.CSharp.Project\CSharpLanguageVersionHelper.cs" />
</ItemGroup>
<ItemGroup>
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CSharpCompletionTextEditorExtension.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CSharpCompletionTextEditorExtension.cs
index 1e02c5843f..7f55dd6bea 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CSharpCompletionTextEditorExtension.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CSharpCompletionTextEditorExtension.cs
@@ -59,6 +59,8 @@ using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.VisualStudio.Platform;
+using Counters = MonoDevelop.Ide.Counters;
+
namespace MonoDevelop.CSharp.Completion
{
sealed class CSharpCompletionTextEditorExtension : CompletionTextEditorExtension, IDebuggerExpressionResolver
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/GotoDefinition/GotoDefinitionService.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/GotoDefinition/GotoDefinitionService.cs
index c25ac90c4d..62369290bf 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/GotoDefinition/GotoDefinitionService.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Features/GotoDefinition/GotoDefinitionService.cs
@@ -8,6 +8,7 @@ using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.CSharp;
+using MonoDevelop.CSharp.Navigation;
namespace ICSharpCode.NRefactory6.CSharp.Features.GotoDefinition
{
@@ -78,6 +79,21 @@ namespace ICSharpCode.NRefactory6.CSharp.Features.GotoDefinition
public static bool TryGoToDefinition (Document document, int position, CancellationToken cancellationToken)
{
+ var metadata = Counters.CreateNavigateToMetadata ("Declaration");
+
+ using (var timer = Counters.NavigateTo.BeginTiming (metadata)) {
+ try {
+ bool result = TryGoToDefinitionInternal (document, position, cancellationToken);
+ Counters.UpdateNavigateResult (metadata, result);
+ return result;
+ } finally {
+ Counters.UpdateUserCancellation (metadata, cancellationToken);
+ }
+ }
+ }
+
+ static bool TryGoToDefinitionInternal (Document document, int position, CancellationToken cancellationToken)
+ {
var symbol = FindSymbolAsync (document, position, cancellationToken).Result;
if (symbol != null) {
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/Counters.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/Counters.cs
new file mode 100644
index 0000000000..51dccb3cf8
--- /dev/null
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/Counters.cs
@@ -0,0 +1,69 @@
+//
+// Counters.cs
+//
+// Author:
+// Matt Ward <matt.ward@microsoft.com>
+//
+// Copyright (c) 2018 Microsoft
+//
+// 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.Collections.Generic;
+using System.Threading;
+using MonoDevelop.Core.Instrumentation;
+
+namespace MonoDevelop.CSharp.Navigation
+{
+ internal static class Counters
+ {
+ public static TimerCounter NavigateTo = InstrumentationService.CreateTimerCounter ("Navigate to", "Code Navigation", id: "CodeNavigation.NavigateTo");
+
+ public static IDictionary<string, string> CreateNavigateToMetadata (string navigationType)
+ {
+ var metadata = new Dictionary<string, string> ();
+ metadata ["Type"] = navigationType;
+ metadata ["Result"] = "Failure"; // Will be updated when navigation finishes.
+ return metadata;
+ }
+
+ public static void UpdateUserCancellation (IDictionary<string, string> metadata, CancellationToken cancellationToken)
+ {
+ if (cancellationToken.IsCancellationRequested) {
+ metadata ["Result"] = "UserCancel";
+ }
+ }
+
+ public static void UpdateNavigateResult (IDictionary<string, string> metadata, bool result)
+ {
+ metadata ["Result"] = result ? "Success" : "Failure";
+ }
+
+ /// <summary>
+ /// Distinguish between IDE errors and a failure due to the user selecting an invalid item.
+ /// Some navigation menus are enabled even if they are not valid. For example, right clicking
+ /// on a method and selecting Navigate - Extension Methods will find no class at the caret and
+ /// will not attempt to find any extension methods. Note that the CommandInfo is disabled for
+ /// the menu but this does not seem to have any affect presumably because the method is async.
+ /// </summary>
+ public static void UpdateUserFault (IDictionary<string, string> metadata)
+ {
+ metadata ["Result"] = "UserFault";
+ }
+ }
+}
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindBaseSymbolsHandler.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindBaseSymbolsHandler.cs
index d732aca199..7dceb59c9b 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindBaseSymbolsHandler.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindBaseSymbolsHandler.cs
@@ -25,28 +25,31 @@
// THE SOFTWARE.
using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
using MonoDevelop.Ide;
using MonoDevelop.Ide.FindInFiles;
using MonoDevelop.Ide.TypeSystem;
using MonoDevelop.Core;
+using MonoDevelop.Core.ProgressMonitoring;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Shared.Extensions;
using MonoDevelop.Components.Commands;
using MonoDevelop.Refactoring;
-using System.Threading.Tasks;
-using System.Collections.Generic;
using ICSharpCode.NRefactory6.CSharp;
namespace MonoDevelop.CSharp.Navigation
{
class FindBaseSymbolsHandler : CommandHandler
{
- void FindSymbols (ISymbol sym)
+ Task FindSymbols (ISymbol sym, CancellationTokenSource cancellationTokenSource)
{
if (sym == null)
- return;
- Task.Run (delegate {
- using (var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true)) {
+ return Task.FromResult (0);
+ return Task.Run (delegate {
+ var searchMonitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true);
+ using (var monitor = searchMonitor.WithCancellationSource (cancellationTokenSource)) {
var foundSymbol = sym.OverriddenMember ();
while (foundSymbol != null) {
foreach (var loc in foundSymbol.Locations) {
@@ -56,7 +59,7 @@ namespace MonoDevelop.CSharp.Navigation
if (loc.SourceTree == null)
continue;
- monitor.ReportResult (new MemberReference (foundSymbol, loc.SourceTree.FilePath, loc.SourceSpan.Start, loc.SourceSpan.Length));
+ searchMonitor.ReportResult (new MemberReference (foundSymbol, loc.SourceTree.FilePath, loc.SourceSpan.Start, loc.SourceSpan.Length));
}
foundSymbol = foundSymbol.OverriddenMember ();
}
@@ -81,11 +84,24 @@ namespace MonoDevelop.CSharp.Navigation
protected override async void Run ()
{
- var sym = await GetSymbolAtCaret (IdeApp.Workbench.ActiveDocument);
- if (sym != null)
- FindSymbols (sym);
- }
+ var metadata = Counters.CreateNavigateToMetadata ("BaseSymbols");
+ using (var timer = Counters.NavigateTo.BeginTiming (metadata)) {
+ var sym = await GetSymbolAtCaret (IdeApp.Workbench.ActiveDocument);
+ if (sym == null) {
+ Counters.UpdateUserFault (metadata);
+ return;
+ }
+ using (var source = new CancellationTokenSource ()) {
+ try {
+ await FindSymbols (sym, source);
+ Counters.UpdateNavigateResult (metadata, true);
+ } finally {
+ Counters.UpdateUserCancellation (metadata, source.Token);
+ }
+ }
+ }
+ }
}
}
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindDerivedSymbolsHandler.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindDerivedSymbolsHandler.cs
index 60dfe50938..ce81fb731d 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindDerivedSymbolsHandler.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindDerivedSymbolsHandler.cs
@@ -36,6 +36,7 @@ using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.Shared.Extensions;
using MonoDevelop.Components.Commands;
using MonoDevelop.Core;
+using MonoDevelop.Core.ProgressMonitoring;
using MonoDevelop.CSharp.Navigation;
using MonoDevelop.Ide;
using MonoDevelop.Ide.FindInFiles;
@@ -60,13 +61,14 @@ namespace MonoDevelop.CSharp.Refactoring
return symbol.IsVirtual || symbol.IsAbstract || symbol.IsOverride;
}
- public static void FindDerivedSymbols (ISymbol symbol)
+ static Task FindDerivedSymbols (ISymbol symbol, CancellationTokenSource cancellationTokenSource)
{
if (symbol == null)
- return;
+ return Task.FromResult (0);
var solution = IdeApp.Workbench.ActiveDocument?.AnalysisDocument?.Project?.Solution ?? TypeSystemService.Workspace.CurrentSolution;
- Task.Run (async delegate {
- using (var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true)) {
+ return Task.Run (async delegate {
+ var searchMonitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true);
+ using (var monitor = searchMonitor.WithCancellationSource (cancellationTokenSource)) {
IEnumerable<ISymbol> result;
try {
if (symbol.ContainingType != null && symbol.ContainingType.TypeKind == TypeKind.Interface) {
@@ -87,7 +89,7 @@ namespace MonoDevelop.CSharp.Refactoring
foreach (var foundSymbol in result) {
foreach (var loc in foundSymbol.Locations) {
monitor.CancellationToken.ThrowIfCancellationRequested ();
- monitor.ReportResult (new MemberReference (foundSymbol, loc.SourceTree.FilePath, loc.SourceSpan.Start, loc.SourceSpan.Length));
+ searchMonitor.ReportResult (new MemberReference (foundSymbol, loc.SourceTree.FilePath, loc.SourceSpan.Start, loc.SourceSpan.Length));
}
}
} catch (OperationCanceledException) {
@@ -120,9 +122,23 @@ namespace MonoDevelop.CSharp.Refactoring
protected override async void Run (object dataItem)
{
- var sym = await FindBaseSymbolsHandler.GetSymbolAtCaret (IdeApp.Workbench.ActiveDocument);
- if (sym != null)
- FindDerivedSymbols (sym);
+ var metadata = Navigation.Counters.CreateNavigateToMetadata ("DerivedSymbols");
+ using (var timer = Navigation.Counters.NavigateTo.BeginTiming (metadata)) {
+ var sym = await FindBaseSymbolsHandler.GetSymbolAtCaret (IdeApp.Workbench.ActiveDocument);
+ if (sym == null) {
+ Navigation.Counters.UpdateUserFault (metadata);
+ return;
+ }
+
+ using (var source = new CancellationTokenSource ()) {
+ try {
+ await FindDerivedSymbols (sym, source);
+ Navigation.Counters.UpdateNavigateResult (metadata, true);
+ } finally {
+ Navigation.Counters.UpdateUserCancellation (metadata, source.Token);
+ }
+ }
+ }
}
}
}
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindExtensionMethodsHandler.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindExtensionMethodsHandler.cs
index c7a5f0c5a9..99a0153fc3 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindExtensionMethodsHandler.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindExtensionMethodsHandler.cs
@@ -24,6 +24,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+using System.Linq;
+using System.Threading;
using MonoDevelop.Ide;
using MonoDevelop.Ide.FindInFiles;
using Microsoft.CodeAnalysis;
@@ -31,7 +33,6 @@ using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.Shared.Extensions;
using MonoDevelop.Components.Commands;
using MonoDevelop.Refactoring;
-using System.Linq;
using ICSharpCode.NRefactory6.CSharp;
namespace MonoDevelop.CSharp.Navigation
@@ -47,10 +48,24 @@ namespace MonoDevelop.CSharp.Navigation
protected async override void Run ()
{
- var doc = IdeApp.Workbench.ActiveDocument;
- var sym = await GetNamedTypeAtCaret (doc);
- if (sym != null)
- FindExtensionMethods (await doc.GetCompilationAsync (), sym);
+ var metadata = Counters.CreateNavigateToMetadata ("ExtensionMethods");
+ using (var timer = Counters.NavigateTo.BeginTiming (metadata)) {
+ var doc = IdeApp.Workbench.ActiveDocument;
+ var sym = await GetNamedTypeAtCaret (doc);
+ if (sym == null) {
+ Counters.UpdateUserFault (metadata);
+ return;
+ }
+
+ using (var source = new CancellationTokenSource ()) {
+ try {
+ FindExtensionMethods (await doc.GetCompilationAsync (), sym, source);
+ Counters.UpdateNavigateResult (metadata, true);
+ } finally {
+ Counters.UpdateUserCancellation (metadata, source.Token);
+ }
+ }
+ }
}
internal static async System.Threading.Tasks.Task<INamedTypeSymbol> GetNamedTypeAtCaret (Ide.Gui.Document doc)
@@ -62,12 +77,14 @@ namespace MonoDevelop.CSharp.Navigation
return sym as INamedTypeSymbol;
}
- void FindExtensionMethods (Compilation compilation, ISymbol sym)
+ void FindExtensionMethods (Compilation compilation, ISymbol sym, CancellationTokenSource cancellationTokenSource)
{
var symType = sym as ITypeSymbol;
if (symType == null)
return;
- using (var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true)) {
+
+ var searchMonitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true);
+ using (var monitor = searchMonitor.WithCancellationSource (cancellationTokenSource)) {
foreach (var type in compilation.Assembly.GlobalNamespace.GetAllTypes (monitor.CancellationToken)) {
if (!type.MightContainExtensionMethods)
continue;
@@ -79,7 +96,7 @@ namespace MonoDevelop.CSharp.Navigation
var reducedMethod = extMethod.ReduceExtensionMethod (symType);
if (reducedMethod != null) {
var loc = extMethod.Locations.First ();
- monitor.ReportResult (new MemberReference (extMethod, loc.SourceTree.FilePath, loc.SourceSpan.Start, loc.SourceSpan.Length));
+ searchMonitor.ReportResult (new MemberReference (extMethod, loc.SourceTree.FilePath, loc.SourceSpan.Start, loc.SourceSpan.Length));
}
}
}
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindImplementingMembersHandler.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindImplementingMembersHandler.cs
index c37c5a4362..9bc100b784 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindImplementingMembersHandler.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindImplementingMembersHandler.cs
@@ -24,15 +24,16 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
using MonoDevelop.Ide;
using MonoDevelop.Ide.FindInFiles;
using Microsoft.CodeAnalysis;
using MonoDevelop.Components.Commands;
using MonoDevelop.Refactoring;
-using System.Linq;
using ICSharpCode.NRefactory6.CSharp;
using Microsoft.CodeAnalysis.CSharp;
-using System.Threading.Tasks;
namespace MonoDevelop.CSharp.Navigation
{
@@ -47,10 +48,24 @@ namespace MonoDevelop.CSharp.Navigation
protected async override void Run ()
{
- var doc = IdeApp.Workbench.ActiveDocument;
- var sym = await GetNamedTypeAtCaret (doc);
- if (sym != null)
- FindImplementingSymbols (await doc.GetCompilationAsync (), sym);
+ var metadata = Counters.CreateNavigateToMetadata ("ImplementingMembers");
+ using (var timer = Counters.NavigateTo.BeginTiming (metadata)) {
+ var doc = IdeApp.Workbench.ActiveDocument;
+ var sym = await GetNamedTypeAtCaret (doc);
+ if (sym == null) {
+ Counters.UpdateUserFault (metadata);
+ return;
+ }
+
+ using (var source = new CancellationTokenSource ()) {
+ try {
+ await FindImplementingSymbols (await doc.GetCompilationAsync (), sym, source);
+ Counters.UpdateNavigateResult (metadata, true);
+ } finally {
+ Counters.UpdateUserCancellation (metadata, source.Token);
+ }
+ }
+ }
}
static async Task<RefactoringSymbolInfo> GetNamedTypeAtCaret (Ide.Gui.Document doc)
@@ -65,14 +80,15 @@ namespace MonoDevelop.CSharp.Navigation
return info;
}
- void FindImplementingSymbols (Compilation compilation, RefactoringSymbolInfo info)
+ Task FindImplementingSymbols (Compilation compilation, RefactoringSymbolInfo info, CancellationTokenSource cancellationTokenSource)
{
var interfaceType = info.Symbol as ITypeSymbol;
if (interfaceType == null)
- return;
+ return Task.FromResult (0);
- Task.Run (delegate {
- using (var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true)) {
+ return Task.Run (delegate {
+ var searchMonitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true);
+ using (var monitor = searchMonitor.WithCancellationSource (cancellationTokenSource)) {
var parentTypeNode = info.Node?.Parent?.Parent?.Parent;
if (parentTypeNode == null)
return;
@@ -86,7 +102,7 @@ namespace MonoDevelop.CSharp.Navigation
if (impl == null)
continue;
var loc = impl.Locations.First ();
- monitor.ReportResult (new MemberReference (impl, loc.SourceTree.FilePath, loc.SourceSpan.Start, loc.SourceSpan.Length));
+ searchMonitor.ReportResult (new MemberReference (impl, loc.SourceTree.FilePath, loc.SourceSpan.Start, loc.SourceSpan.Length));
}
foreach (var iFace in interfaceType.AllInterfaces) {
@@ -98,7 +114,7 @@ namespace MonoDevelop.CSharp.Navigation
if (impl == null)
continue;
var loc = impl.Locations.First ();
- monitor.ReportResult (new MemberReference (impl, loc.SourceTree.FilePath, loc.SourceSpan.Start, loc.SourceSpan.Length));
+ searchMonitor.ReportResult (new MemberReference (impl, loc.SourceTree.FilePath, loc.SourceSpan.Start, loc.SourceSpan.Length));
}
}
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindMemberOverloadsHandler.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindMemberOverloadsHandler.cs
index f88698e842..d02a2bc077 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindMemberOverloadsHandler.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Navigation/FindMemberOverloadsHandler.cs
@@ -25,6 +25,7 @@
// THE SOFTWARE.
using System.Linq;
+using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.Shared.Extensions;
@@ -53,9 +54,10 @@ namespace MonoDevelop.CSharp.Navigation
}
}
- public static void FindOverloads (ISymbol symbol)
+ public static void FindOverloads (ISymbol symbol, CancellationTokenSource cancellationTokenSource)
{
- using (var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true)) {
+ var searchMonitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true);
+ using (var monitor = searchMonitor.WithCancellationSource (cancellationTokenSource)) {
switch (symbol.Kind) {
case SymbolKind.Method:
foreach (var method in symbol.ContainingType.GetMembers (symbol.Name).OfType<IMethodSymbol> ()) {
@@ -63,7 +65,7 @@ namespace MonoDevelop.CSharp.Navigation
if (monitor.CancellationToken.IsCancellationRequested)
return;
- monitor.ReportResult (new MemberReference (method, loc.SourceTree.FilePath, loc.SourceSpan.Start, loc.SourceSpan.Length));
+ searchMonitor.ReportResult (new MemberReference (method, loc.SourceTree.FilePath, loc.SourceSpan.Start, loc.SourceSpan.Length));
}
}
break;
@@ -73,7 +75,7 @@ namespace MonoDevelop.CSharp.Navigation
if (monitor.CancellationToken.IsCancellationRequested)
return;
- monitor.ReportResult (new MemberReference (property, loc.SourceTree.FilePath, loc.SourceSpan.Start, loc.SourceSpan.Length));
+ searchMonitor.ReportResult (new MemberReference (property, loc.SourceTree.FilePath, loc.SourceSpan.Start, loc.SourceSpan.Length));
}
}
break;
@@ -100,10 +102,26 @@ namespace MonoDevelop.CSharp.Navigation
var doc = IdeApp.Workbench.ActiveDocument;
if (doc == null || doc.FileName == FilePath.Null)
return;
- var info = await RefactoringSymbolInfo.GetSymbolInfoAsync (doc, doc.Editor);
- var sym = info.Symbol ?? info.DeclaredSymbol;
- if (sym != null)
- FindOverloads (sym);
+
+ var metadata = Counters.CreateNavigateToMetadata ("MemberOverloads");
+ using (var timer = Counters.NavigateTo.BeginTiming (metadata)) {
+
+ var info = await RefactoringSymbolInfo.GetSymbolInfoAsync (doc, doc.Editor);
+ var sym = info.Symbol ?? info.DeclaredSymbol;
+ if (sym == null) {
+ Counters.UpdateUserFault (metadata);
+ return;
+ }
+
+ using (var source = new CancellationTokenSource ()) {
+ try {
+ FindOverloads (sym, source);
+ Counters.UpdateNavigateResult (metadata, true);
+ } finally {
+ Counters.UpdateUserCancellation (metadata, source.Token);
+ }
+ }
+ }
}
}
} \ No newline at end of file
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/FindReferencesHandler.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/FindReferencesHandler.cs
index 7d8044f33c..d8bb848bbd 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/FindReferencesHandler.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/FindReferencesHandler.cs
@@ -32,6 +32,7 @@ using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Shared.Extensions;
using MonoDevelop.Components.Commands;
using MonoDevelop.Core;
+using MonoDevelop.Core.Instrumentation;
using MonoDevelop.CSharp.Highlighting;
using MonoDevelop.Ide;
using MonoDevelop.Ide.FindInFiles;
@@ -49,7 +50,12 @@ namespace MonoDevelop.CSharp.Refactoring
if (workspace == null)
return;
Task.Run (async delegate {
+ ITimeTracker timer = null;
+ var metadata = MonoDevelop.Refactoring.Counters.CreateFindReferencesMetadata ();
+
try {
+ timer = MonoDevelop.Refactoring.Counters.FindReferences.BeginTiming (metadata);
+
var antiDuplicatesSet = new HashSet<SearchResult> (new SearchResultComparer ());
foreach (var loc in symbol.Locations) {
if (monitor.CancellationToken.IsCancellationRequested)
@@ -97,6 +103,7 @@ namespace MonoDevelop.CSharp.Refactoring
}
} catch (OperationCanceledException) {
} catch (Exception ex) {
+ MonoDevelop.Refactoring.Counters.SetFailure (metadata);
if (monitor != null)
monitor.ReportError ("Error finding references", ex);
else
@@ -104,6 +111,10 @@ namespace MonoDevelop.CSharp.Refactoring
} finally {
if (monitor != null)
monitor.Dispose ();
+ if (monitor.CancellationToken.IsCancellationRequested)
+ MonoDevelop.Refactoring.Counters.SetUserCancel (metadata);
+ if (timer != null)
+ timer.Dispose ();
}
});
}
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/GotoBaseDeclarationHandler.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/GotoBaseDeclarationHandler.cs
index fef916d350..c8f6651e22 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/GotoBaseDeclarationHandler.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/GotoBaseDeclarationHandler.cs
@@ -24,10 +24,11 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
-using Microsoft.CodeAnalysis;
-using MonoDevelop.Ide;
using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
using MonoDevelop.Core;
+using MonoDevelop.Ide;
using MonoDevelop.Refactoring;
namespace MonoDevelop.CSharp.Refactoring
@@ -74,37 +75,46 @@ namespace MonoDevelop.CSharp.Refactoring
return false;
}
- public static void GotoBase (MonoDevelop.Ide.Gui.Document doc, ISymbol symbol)
+ public static async Task GotoBase (MonoDevelop.Ide.Gui.Document doc, ISymbol symbol)
{
if (doc == null)
throw new ArgumentNullException ("doc");
if (symbol == null)
throw new ArgumentNullException ("symbol");
+
+ var metadata = Navigation.Counters.CreateNavigateToMetadata ("Base");
+ using (var timer = Navigation.Counters.NavigateTo.BeginTiming (metadata)) {
+ await GotoBaseInternal (doc, symbol);
+ Navigation.Counters.UpdateNavigateResult (metadata, true);
+ }
+ }
+
+ static Task GotoBaseInternal (MonoDevelop.Ide.Gui.Document doc, ISymbol symbol)
+ {
switch (symbol.Kind) {
case SymbolKind.NamedType:
- RefactoringService.RoslynJumpToDeclaration (((ITypeSymbol)symbol).BaseType, doc.Project);
- break;
+ return RefactoringService.RoslynJumpToDeclaration (((ITypeSymbol)symbol).BaseType, doc.Project);
case SymbolKind.Property:
var property = (IPropertySymbol)symbol;
if (property.OverriddenProperty != null)
- RefactoringService.RoslynJumpToDeclaration (property.OverriddenProperty, doc.Project);
+ return RefactoringService.RoslynJumpToDeclaration (property.OverriddenProperty, doc.Project);
else
- RefactoringService.RoslynJumpToDeclaration (property.ExplicitInterfaceImplementations.First (), doc.Project);
- break;
+ return RefactoringService.RoslynJumpToDeclaration (property.ExplicitInterfaceImplementations.First (), doc.Project);
case SymbolKind.Event:
var evt = (IEventSymbol)symbol;
if (evt.OverriddenEvent != null)
- RefactoringService.RoslynJumpToDeclaration (evt.OverriddenEvent, doc.Project);
+ return RefactoringService.RoslynJumpToDeclaration (evt.OverriddenEvent, doc.Project);
else
- RefactoringService.RoslynJumpToDeclaration (evt.ExplicitInterfaceImplementations.First (), doc.Project);
- break;
+ return RefactoringService.RoslynJumpToDeclaration (evt.ExplicitInterfaceImplementations.First (), doc.Project);
case SymbolKind.Method:
var method = (IMethodSymbol)symbol;
if (method.OverriddenMethod != null)
- RefactoringService.RoslynJumpToDeclaration (method.OverriddenMethod, doc.Project);
+ return RefactoringService.RoslynJumpToDeclaration (method.OverriddenMethod, doc.Project);
else
- RefactoringService.RoslynJumpToDeclaration (method.ExplicitInterfaceImplementations.First (), doc.Project);
- break;
+ return RefactoringService.RoslynJumpToDeclaration (method.ExplicitInterfaceImplementations.First (), doc.Project);
+ default:
+ // CanGotoBase should prevent this from happening.
+ throw new ArgumentException (string.Format ("Invalid symbol.Kind {0}", symbol.Kind));
}
}
}
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/RefactoryCommands.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/RefactoryCommands.cs
index dade41b30a..29136372b0 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/RefactoryCommands.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/RefactoryCommands.cs
@@ -111,7 +111,7 @@ namespace MonoDevelop.CSharp.Refactoring
if (info.DeclaredSymbol != null && GotoBaseDeclarationHandler.CanGotoBase (info.DeclaredSymbol)) {
- ainfo.Add (GotoBaseDeclarationHandler.GetDescription (info.DeclaredSymbol), new Action (() => GotoBaseDeclarationHandler.GotoBase (doc, info.DeclaredSymbol)));
+ ainfo.Add (GotoBaseDeclarationHandler.GetDescription (info.DeclaredSymbol), new Action (() => GotoBaseDeclarationHandler.GotoBase (doc, info.DeclaredSymbol).Ignore ()));
added = true;
}
diff --git a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeDebuggerSession.cs b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeDebuggerSession.cs
index 326f85209b..ecbfd73d9b 100644
--- a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeDebuggerSession.cs
+++ b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeDebuggerSession.cs
@@ -344,6 +344,12 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol
break;
}
break;
+ case "module":
+ var moduleEvent = (ModuleEvent)obj.Body;
+ if (moduleEvent.Reason == ModuleEvent.ReasonValue.New) {
+ OnAssemblyLoaded (moduleEvent.Module.Path);
+ }
+ break;
}
});
}
diff --git a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeBacktrace.cs b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeBacktrace.cs
index cde6228e62..d89f406cea 100644
--- a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeBacktrace.cs
+++ b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeBacktrace.cs
@@ -44,9 +44,12 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol
List<ObjectValue> results = new List<ObjectValue> ();
var scopeBody = vsCodeDebuggerSession.protocolClient.SendRequestSync (new ScopesRequest (frames [frameIndex].Id));
foreach (var variablesGroup in scopeBody.Scopes) {
- var varibles = vsCodeDebuggerSession.protocolClient.SendRequestSync (new VariablesRequest (variablesGroup.VariablesReference));
- foreach (var variable in varibles.Variables) {
- results.Add (VsCodeVariableToObjectValue (vsCodeDebuggerSession, variable.Name, variable.EvaluateName, variable.Type, variable.Value, variable.VariablesReference, variablesGroup.VariablesReference, frames [frameIndex].Id));
+ using (var timer = vsCodeDebuggerSession.EvaluationStats.StartTimer ()) {
+ var varibles = vsCodeDebuggerSession.protocolClient.SendRequestSync (new VariablesRequest (variablesGroup.VariablesReference));
+ foreach (var variable in varibles.Variables) {
+ results.Add (VsCodeVariableToObjectValue (vsCodeDebuggerSession, variable.Name, variable.EvaluateName, variable.Type, variable.Value, variable.VariablesReference, variablesGroup.VariablesReference, frames [frameIndex].Id));
+ }
+ timer.Success = true;
}
}
return results.ToArray ();
@@ -66,10 +69,13 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol
{
var results = new List<ObjectValue> ();
foreach (var expr in expressions) {
- var responseBody = vsCodeDebuggerSession.protocolClient.SendRequestSync (new EvaluateRequest (
- expr,
- frames [frameIndex].Id));
- results.Add (VsCodeVariableToObjectValue (vsCodeDebuggerSession, expr, expr, responseBody.Type, responseBody.Result, responseBody.VariablesReference, 0, frames [frameIndex].Id));
+ using (var timer = vsCodeDebuggerSession.EvaluationStats.StartTimer ()) {
+ var responseBody = vsCodeDebuggerSession.protocolClient.SendRequestSync (new EvaluateRequest (
+ expr,
+ frames [frameIndex].Id));
+ results.Add (VsCodeVariableToObjectValue (vsCodeDebuggerSession, expr, expr, responseBody.Type, responseBody.Result, responseBody.VariablesReference, 0, frames [frameIndex].Id));
+ timer.Success = true;
+ }
}
return results.ToArray ();
}
@@ -84,9 +90,12 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol
List<ObjectValue> results = new List<ObjectValue> ();
var scopeBody = vsCodeDebuggerSession.protocolClient.SendRequestSync (new ScopesRequest (frames [frameIndex].Id));
foreach (var variablesGroup in scopeBody.Scopes) {
- var varibles = vsCodeDebuggerSession.protocolClient.SendRequestSync (new VariablesRequest (variablesGroup.VariablesReference));
- foreach (var variable in varibles.Variables) {
- results.Add (ObjectValue.CreatePrimitive (null, new ObjectPath (variable.Name), variable.Type ?? "<unknown>", new EvaluationResult (variable.Value), ObjectValueFlags.None));
+ using (var timer = vsCodeDebuggerSession.EvaluationStats.StartTimer ()) {
+ var varibles = vsCodeDebuggerSession.protocolClient.SendRequestSync (new VariablesRequest (variablesGroup.VariablesReference));
+ foreach (var variable in varibles.Variables) {
+ results.Add (ObjectValue.CreatePrimitive (null, new ObjectPath (variable.Name), variable.Type ?? "<unknown>", new EvaluationResult (variable.Value), ObjectValueFlags.None));
+ }
+ timer.Success = true;
}
}
return results.ToArray ();
diff --git a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeObjectSource.cs b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeObjectSource.cs
index b6cfc55f76..02fd9fc481 100644
--- a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeObjectSource.cs
+++ b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeObjectSource.cs
@@ -41,10 +41,13 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol
if (variablesReference <= 0) {
objValChildren = new ObjectValue [0];
} else {
- var children = vsCodeDebuggerSession.protocolClient.SendRequestSync (new VariablesRequest (
- variablesReference
- )).Variables;
- objValChildren = children.Select (c => VSCodeDebuggerBacktrace.VsCodeVariableToObjectValue (vsCodeDebuggerSession, c.Name, c.EvaluateName, c.Type, c.Value, c.VariablesReference, variablesReference, frameId)).ToArray ();
+ using (var timer = vsCodeDebuggerSession.EvaluationStats.StartTimer ()) {
+ var children = vsCodeDebuggerSession.protocolClient.SendRequestSync (new VariablesRequest (
+ variablesReference
+ )).Variables;
+ objValChildren = children.Select (c => VSCodeDebuggerBacktrace.VsCodeVariableToObjectValue (vsCodeDebuggerSession, c.Name, c.EvaluateName, c.Type, c.Value, c.VariablesReference, variablesReference, frameId)).ToArray ();
+ timer.Success = true;
+ }
}
}
return objValChildren;
@@ -79,7 +82,11 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol
public object GetRawValue (ObjectPath path, EvaluationOptions options)
{
- var val = vsCodeDebuggerSession.protocolClient.SendRequestSync (new EvaluateRequest (evalName, frameId)).Result;
+ string val = null;
+ using (var timer = vsCodeDebuggerSession.EvaluationStats.StartTimer ()) {
+ val = vsCodeDebuggerSession.protocolClient.SendRequestSync (new EvaluateRequest (evalName, frameId)).Result;
+ timer.Success = true;
+ }
if (val.StartsWith ("\"", StringComparison.Ordinal))
if (options.ChunkRawStrings)
return new RawValueString (new RawString (val));
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj
index d4bb66be72..bdfe3f4405 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj
@@ -210,6 +210,7 @@
<Compile Include="MonoDevelop.Debugger\NoSourceView.cs" />
<Compile Include="MonoDevelop.Debugger\DebugSourceFilesOptionsPanel.cs" />
<Compile Include="MonoDevelop.Debugger\SolutionHasDebugSourceFilesCondition.cs" />
+ <Compile Include="MonoDevelop.Debugger\Counters.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="MonoDevelop.Debugger.addin.xml">
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Counters.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Counters.cs
new file mode 100644
index 0000000000..83c1330cc0
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Counters.cs
@@ -0,0 +1,36 @@
+//
+// Counters.cs
+//
+// Author:
+// Matt Ward <matt.ward@microsoft.com>
+//
+// Copyright (c) 2018 Microsoft
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using MonoDevelop.Core.Instrumentation;
+
+namespace MonoDevelop.Debugger
+{
+ static class Counters
+ {
+ public static Counter DebugSession = InstrumentationService.CreateCounter ("Debug Session", "Debugger", id: "Debugger.DebugSession");
+ public static Counter EvaluationStats = InstrumentationService.CreateCounter ("Evaluation Statistics", "Debugger", id: "Debugger.EvaluationStatistics");
+ }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs
index 1d3692426e..17f5b10fb9 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs
@@ -593,7 +593,6 @@ namespace MonoDevelop.Debugger
var session = debugger.CreateSession ();
var monitor = IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor (proc.Name);
var sessionManager = new SessionManager (session, monitor.Console, debugger);
- session.ExceptionHandler = ExceptionHandler;
SetupSession (sessionManager);
session.TargetExited += delegate {
monitor.Dispose ();
@@ -676,7 +675,6 @@ namespace MonoDevelop.Debugger
startInfo.CloseExternalConsoleOnExit = ((ExternalConsole)c).CloseOnDispose;
var session = factory.CreateSession ();
- session.ExceptionHandler = ExceptionHandler;
SessionManager sessionManager;
// When using an external console, create a new internal console which will be used
@@ -690,8 +688,10 @@ namespace MonoDevelop.Debugger
SetDebugLayout ();
try {
+ sessionManager.PrepareForRun ();
session.Run (startInfo, GetUserOptions ());
} catch {
+ sessionManager.SessionError = true;
Cleanup (sessionManager);
throw;
}
@@ -713,6 +713,8 @@ namespace MonoDevelop.Debugger
{
OperationConsole console;
IDisposable cancelRegistration;
+ System.Diagnostics.Stopwatch firstAssemblyLoadTimer;
+
public readonly DebuggerSession Session;
public readonly DebugAsyncOperation debugOperation;
public readonly DebuggerEngine Engine;
@@ -721,6 +723,8 @@ namespace MonoDevelop.Debugger
{
Engine = engine;
Session = session;
+ session.ExceptionHandler = ExceptionHandler;
+ session.AssemblyLoaded += OnAssemblyLoaded;
this.console = console;
cancelRegistration = console.CancellationToken.Register (Cancel);
debugOperation = new DebugAsyncOperation (session);
@@ -761,13 +765,80 @@ namespace MonoDevelop.Debugger
public void Dispose ()
{
+ UpdateDebugSessionCounter ();
+ UpdateEvaluationStatsCounter ();
+
console?.Dispose ();
console = null;
+ Session.AssemblyLoaded -= OnAssemblyLoaded;
Session.Dispose ();
debugOperation.Cleanup ();
cancelRegistration?.Dispose ();
cancelRegistration = null;
}
+
+ /// <summary>
+ /// Indicates whether the debug session failed to an exception or any debugger
+ /// operation failed and was reported to the user.
+ /// </summary>
+ public bool SessionError { get; set; }
+
+ void UpdateDebugSessionCounter ()
+ {
+ var metadata = new Dictionary<string, string> ();
+ metadata ["Success"] = (!SessionError).ToString ();
+ metadata ["DebuggerType"] = Engine.Id;
+
+ if (firstAssemblyLoadTimer != null) {
+ if (firstAssemblyLoadTimer.IsRunning) {
+ // No first assembly load event.
+ firstAssemblyLoadTimer.Stop ();
+ } else {
+ metadata ["AssemblyFirstLoadDuration"] = firstAssemblyLoadTimer.ElapsedMilliseconds.ToString ();
+ }
+ }
+
+ Counters.DebugSession.Inc (metadata);
+ }
+
+ void UpdateEvaluationStatsCounter ()
+ {
+ if (Session.EvaluationStats.TimingsCount == 0 && Session.EvaluationStats.FailureCount == 0) {
+ // No timings or failures recorded.
+ return;
+ }
+
+ var metadata = new Dictionary<string, string> ();
+ metadata ["DebuggerType"] = Engine.Id;
+ metadata ["AverageDuration"] = Session.EvaluationStats.AverageTime.ToString ();
+ metadata ["MaximumDuration"] = Session.EvaluationStats.MaxTime.ToString ();
+ metadata ["MinimumDuration"] = Session.EvaluationStats.MinTime.ToString ();
+ metadata ["FailureCount"] = Session.EvaluationStats.FailureCount.ToString ();
+ metadata ["SuccessCount"] = Session.EvaluationStats.TimingsCount.ToString ();
+
+ Counters.EvaluationStats.Inc (metadata);
+ }
+
+ bool ExceptionHandler (Exception ex)
+ {
+ SessionError = true;
+ return DebuggingService.ExceptionHandler (ex);
+ }
+
+ /// <summary>
+ /// Called just before DebugSession.Run is called.
+ /// </summary>
+ public void PrepareForRun ()
+ {
+ firstAssemblyLoadTimer = new System.Diagnostics.Stopwatch ();
+ firstAssemblyLoadTimer.Start ();
+ }
+
+ void OnAssemblyLoaded (object sender, AssemblyEventArgs e)
+ {
+ DebuggerSession.AssemblyLoaded -= OnAssemblyLoaded;
+ firstAssemblyLoadTimer?.Stop ();
+ }
}
static async void OnBusyStateChanged (object s, BusyStateEventArgs args)
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs
index ae9f1ec7c8..348d67093a 100644
--- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs
+++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs
@@ -242,16 +242,21 @@ namespace MonoDevelop.Refactoring
{
if (hintProject == null)
hintProject = IdeApp.Workbench.ActiveDocument?.Project;
+ ITimeTracker timer = null;
var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true);
try {
+ var metadata = Counters.CreateFindReferencesMetadata ();
+ timer = Counters.FindReferences.BeginTiming (metadata);
foreach (var provider in findReferencesProvider) {
try {
foreach (var result in await provider.FindReferences (documentIdString, hintProject, monitor.CancellationToken)) {
monitor.ReportResult (result);
}
} catch (OperationCanceledException) {
+ Counters.SetUserCancel (metadata);
return;
} catch (Exception ex) {
+ Counters.SetFailure (metadata);
if (monitor != null)
monitor.ReportError ("Error finding references", ex);
LoggingService.LogError ("Error finding references", ex);
@@ -261,6 +266,8 @@ namespace MonoDevelop.Refactoring
} finally {
if (monitor != null)
monitor.Dispose ();
+ if (timer != null)
+ timer.Dispose ();
}
}
@@ -268,16 +275,21 @@ namespace MonoDevelop.Refactoring
{
if (hintProject == null)
hintProject = IdeApp.Workbench.ActiveDocument?.Project;
+ ITimeTracker timer = null;
var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true);
try {
+ var metadata = Counters.CreateFindReferencesMetadata ();
+ timer = Counters.FindReferences.BeginTiming (metadata);
foreach (var provider in findReferencesProvider) {
try {
foreach (var result in await provider.FindAllReferences (documentIdString, hintProject, monitor.CancellationToken)) {
monitor.ReportResult (result);
}
} catch (OperationCanceledException) {
+ Counters.SetUserCancel (metadata);
return;
} catch (Exception ex) {
+ Counters.SetFailure (metadata);
if (monitor != null)
monitor.ReportError ("Error finding references", ex);
LoggingService.LogError ("Error finding references", ex);
@@ -287,6 +299,8 @@ namespace MonoDevelop.Refactoring
} finally {
if (monitor != null)
monitor.Dispose ();
+ if (timer != null)
+ timer.Dispose ();
}
}
@@ -308,4 +322,26 @@ namespace MonoDevelop.Refactoring
return false;
}
}
+
+ internal static class Counters
+ {
+ public static TimerCounter FindReferences = InstrumentationService.CreateTimerCounter ("Find references", "Code Navigation", id: "CodeNavigation.FindReferences");
+
+ public static IDictionary<string, string> CreateFindReferencesMetadata ()
+ {
+ var metadata = new Dictionary<string, string> ();
+ metadata ["Result"] = "Success";
+ return metadata;
+ }
+
+ public static void SetFailure (IDictionary<string, string> metadata)
+ {
+ metadata ["Result"] = "Failure";
+ }
+
+ public static void SetUserCancel (IDictionary<string, string> metadata)
+ {
+ metadata ["Result"] = "UserCancel";
+ }
+ }
}
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj
index 4a411f46ec..b42d4007d5 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj
@@ -286,6 +286,7 @@
<Compile Include="MonoDevelop.SourceEditor\TextMarker\LineSeparatorMarker.cs" />
<Compile Include="MonoDevelop.SourceEditor.QuickTasks\QuickTaskOverviewMode.IndicatorDrawingCache.cs" />
<Compile Include="MonoDevelop.SourceEditor.QuickTasks\QuickTaskOverviewMode.IdleUpdater.cs" />
+ <Compile Include="MonoDevelop.SourceEditor\TextEditorKeyPressTimings.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="gtk-gui\gui.stetic">
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/Counters.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/Counters.cs
index e55ef141ff..50d6f44d4b 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/Counters.cs
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/Counters.cs
@@ -34,5 +34,6 @@ namespace MonoDevelop.SourceEditor
public static Counter EditorsInMemory = InstrumentationService.CreateCounter ("Editors in Memory", "Text Editor");
public static Counter SourceViewsInMemory = InstrumentationService.CreateCounter ("Source Views in Memory", "Text Editor");
public static Counter LoadedEditors = InstrumentationService.CreateCounter ("Loaded Editors", "Text Editor");
+ public static Counter Typing = InstrumentationService.CreateCounter ("Typing", "Text Editor", id: "TextEditor.Typing");
}
}
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/ExtensibleTextEditor.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/ExtensibleTextEditor.cs
index b7c8198f08..e65d854542 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/ExtensibleTextEditor.cs
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/ExtensibleTextEditor.cs
@@ -56,6 +56,7 @@ namespace MonoDevelop.SourceEditor
class ExtensibleTextEditor : Mono.TextEditor.MonoTextEditor
{
internal object MemoryProbe = Counters.EditorsInMemory.CreateMemoryProbe ();
+ TextEditorKeyPressTimings keyPressTimings = new TextEditorKeyPressTimings ();
SourceEditorView view;
Adjustment cachedHAdjustment, cachedVAdjustment;
@@ -209,6 +210,12 @@ namespace MonoDevelop.SourceEditor
{
IsDestroyed = true;
UnregisterAdjustments ();
+
+ if (keyPressTimings != null) {
+ keyPressTimings.ReportTimings (view);
+ keyPressTimings = null;
+ }
+
view = null;
Document.SyntaxMode = null;
base.OnDestroyed ();
@@ -334,9 +341,18 @@ namespace MonoDevelop.SourceEditor
}
}
-
protected internal override bool OnIMProcessedKeyPressEvent (Gdk.Key key, uint ch, Gdk.ModifierType state)
{
+ try {
+ keyPressTimings.StartTimer ();
+ return OnIMProcessedKeyPressEventInternal (key, ch, state);
+ } finally {
+ keyPressTimings.EndTimer ();
+ }
+ }
+
+ bool OnIMProcessedKeyPressEventInternal (Gdk.Key key, uint ch, Gdk.ModifierType state)
+ {
bool result = true;
if (key == Gdk.Key.Escape) {
bool b = EditorExtension != null ? ExtensionKeyPress (key, ch, state) : base.OnIMProcessedKeyPressEvent (key, ch, state);
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/TextEditorKeyPressTimings.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/TextEditorKeyPressTimings.cs
new file mode 100644
index 0000000000..8dc879a2d4
--- /dev/null
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/TextEditorKeyPressTimings.cs
@@ -0,0 +1,96 @@
+//
+// TextEditorKeyPressTimings.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2017 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Diagnostics;
+using System.Collections.Generic;
+
+namespace MonoDevelop.SourceEditor
+{
+ class TextEditorKeyPressTimings
+ {
+ Stopwatch stopwatch = new Stopwatch ();
+
+ TimeSpan maxTime;
+ TimeSpan totalTime;
+ TimeSpan? firstTime;
+ int count;
+
+ public void StartTimer ()
+ {
+ stopwatch.Start ();
+ }
+
+ /// <summary>
+ /// Overhead to a key press of using StartTimer and EndTimer is normally less
+ /// than 0.001ms.
+ ///
+ /// Note that the first ever key press in the text editor this can add up to
+ /// ~0.1ms but this is small compared with the text editor key press itself
+ /// which can take ~800ms for the first ever key press in the text editor for
+ /// the current IDE session.
+ /// </summary>
+ public void EndTimer ()
+ {
+ stopwatch.Stop ();
+
+ var duration = stopwatch.Elapsed;
+ if (duration > maxTime) {
+ maxTime = duration;
+ }
+
+ if (!firstTime.HasValue) {
+ firstTime = duration;
+ }
+
+ totalTime += duration;
+ count++;
+
+ stopwatch.Reset ();
+ }
+
+ public void ReportTimings (SourceEditorView sourceEditorView)
+ {
+ if (count == 0) {
+ // No timings recorded.
+ return;
+ }
+
+ string extension = sourceEditorView.Document.FileName.Extension;
+
+ var metadata = new Dictionary<string, string> ();
+ if (!string.IsNullOrEmpty (extension))
+ metadata ["Extension"] = extension;
+
+ var average = totalTime.TotalMilliseconds / count;
+ metadata ["Average"] = average.ToString ();
+ metadata ["First"] = firstTime.Value.TotalMilliseconds.ToString ();
+ metadata ["Maximum"] = maxTime.TotalMilliseconds.ToString ();
+
+ Counters.Typing.Inc (metadata);
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/CompletionTextEditorExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/CompletionTextEditorExtension.cs
index 9eda1df61f..76d02a6bfa 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/CompletionTextEditorExtension.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/CompletionTextEditorExtension.cs
@@ -25,8 +25,8 @@
//
//
-
using System;
+using System.Collections.Generic;
using MonoDevelop.Projects;
using MonoDevelop.Ide.CodeCompletion;
using MonoDevelop.Components.Commands;
@@ -191,8 +191,11 @@ namespace MonoDevelop.Ide.Editor.Extension
completionTokenSrc = new CancellationTokenSource ();
var caretOffset = Editor.CaretOffset;
var token = completionTokenSrc.Token;
+
+ var metadata = new Dictionary<string, string> ();
+ metadata ["Result"] = "Success";
try {
- Counters.ProcessCodeCompletion.BeginTiming ();
+ Counters.ProcessCodeCompletion.BeginTiming (metadata);
var task = DoHandleCodeCompletionAsync (CurrentCompletionContext, new CompletionTriggerInfo (CompletionTriggerReason.CharTyped, descriptor.KeyChar), token);
if (task != null) {
// Show the completion window in two steps. The call to PrepareShowWindow creates the window but
@@ -225,6 +228,9 @@ namespace MonoDevelop.Ide.Editor.Extension
CurrentCompletionContext = null;
}
} finally {
+ if (token.IsCancellationRequested) {
+ metadata ["Result"] = "UserCancel";
+ }
Counters.ProcessCodeCompletion.EndTiming ();
}
}, Runtime.MainTaskScheduler);
@@ -233,10 +239,13 @@ namespace MonoDevelop.Ide.Editor.Extension
Counters.ProcessCodeCompletion.EndTiming ();
}
} catch (TaskCanceledException) {
+ metadata ["Result"] = "UserCancel";
Counters.ProcessCodeCompletion.EndTiming ();
} catch (AggregateException) {
+ metadata ["Result"] = "Failure";
Counters.ProcessCodeCompletion.EndTiming ();
} catch {
+ metadata ["Result"] = "Failure";
Counters.ProcessCodeCompletion.EndTiming ();
throw;
}
@@ -260,8 +269,11 @@ namespace MonoDevelop.Ide.Editor.Extension
completionTokenSrc = new CancellationTokenSource ();
var caretOffset = Editor.CaretOffset;
var token = completionTokenSrc.Token;
+
+ var metadata = new Dictionary<string, string> ();
+ metadata ["Result"] = "Success";
try {
- Counters.ProcessCodeCompletion.BeginTiming ();
+ Counters.ProcessCodeCompletion.BeginTiming (metadata);
var task = DoHandleCodeCompletionAsync (CurrentCompletionContext, new CompletionTriggerInfo (CompletionTriggerReason.BackspaceOrDeleteCommand, deleteOrBackspaceTriggerChar), token);
if (task != null) {
// Show the completion window in two steps. The call to PrepareShowWindow creates the window but
@@ -299,6 +311,9 @@ namespace MonoDevelop.Ide.Editor.Extension
CurrentCompletionContext = null;
}
} finally {
+ if (token.IsCancellationRequested) {
+ metadata ["Result"] = "UserCancel";
+ }
Counters.ProcessCodeCompletion.EndTiming ();
}
}, Runtime.MainTaskScheduler);
@@ -307,11 +322,14 @@ namespace MonoDevelop.Ide.Editor.Extension
}
} catch (TaskCanceledException) {
CurrentCompletionContext = null;
+ metadata ["Result"] = "UserCancel";
Counters.ProcessCodeCompletion.EndTiming ();
} catch (AggregateException) {
CurrentCompletionContext = null;
+ metadata ["Result"] = "Failure";
Counters.ProcessCodeCompletion.EndTiming ();
} catch {
+ metadata ["Result"] = "Failure";
Counters.ProcessCodeCompletion.EndTiming ();
throw;
}
@@ -429,8 +447,11 @@ namespace MonoDevelop.Ide.Editor.Extension
CurrentCompletionContext = CompletionWidget.CreateCodeCompletionContext (cpos);
CurrentCompletionContext.TriggerWordLength = wlen;
+
+ var metadata = new Dictionary<string, string> ();
+ metadata ["Result"] = "Success";
try {
- Counters.ProcessCodeCompletion.BeginTiming ();
+ Counters.ProcessCodeCompletion.BeginTiming (metadata);
completionList = await DoHandleCodeCompletionAsync (CurrentCompletionContext, new CompletionTriggerInfo (reason), token);
if (completionList != null && completionList.TriggerWordStart >= 0) {
CurrentCompletionContext.TriggerOffset = completionList.TriggerWordStart;
@@ -439,6 +460,9 @@ namespace MonoDevelop.Ide.Editor.Extension
if (completionList == null || !CompletionWindowManager.ShowWindow (this, (char)0, completionList, CompletionWidget, CurrentCompletionContext)) {
CurrentCompletionContext = null;
}
+ } catch (Exception) {
+ metadata ["Result"] = "Failure";
+ throw;
} finally {
Counters.ProcessCodeCompletion.EndTiming ();
}