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:
authorMike Krüger <mkrueger@xamarin.com>2017-08-08 16:00:39 +0300
committerMike Krüger <mkrueger@xamarin.com>2017-08-08 16:00:39 +0300
commitd4d90f0f327092511d885ea80c66be92be92f950 (patch)
treecfeeff941d6c4645e59f0e4cde0b572bc1cbc32f /main/src
parent0748166561d4eca6d80ab5d7d24f5566c6ab5aea (diff)
[TextEditor] Implemented code lens subsystem & show references lenses.master-codelens
It's the rosyln code lens service driving the first code lens.
Diffstat (limited to 'main/src')
-rw-r--r--main/src/addins/CSharpBinding/CSharpBinding.addin.xml5
-rw-r--r--main/src/addins/CSharpBinding/CSharpBinding.csproj1
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/CSharpCodeLensProvider.cs131
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj1
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs5
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/TextMarker/CodeLensMarker.cs93
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/CodeLensTextEditorExtension.cs204
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextLineMarker.cs8
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextMarkerFactory.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj1
11 files changed, 455 insertions, 0 deletions
diff --git a/main/src/addins/CSharpBinding/CSharpBinding.addin.xml b/main/src/addins/CSharpBinding/CSharpBinding.addin.xml
index 75a1ce00fa..139cb9b8ea 100644
--- a/main/src/addins/CSharpBinding/CSharpBinding.addin.xml
+++ b/main/src/addins/CSharpBinding/CSharpBinding.addin.xml
@@ -343,4 +343,9 @@
<Extension path = "/MonoDevelop/Ide/AutoInsertBracketHandler">
<Class class="MonoDevelop.CSharp.Features.AutoInsertBracket.CSharpAutoInsertBracketHandler" insertbefore="Default"/>
</Extension>
+
+ <Extension path = "/MonoDevelop/Ide/CodeLensProvider">
+ <CodeLens class="MonoDevelop.CSharp.Refactoring.CSharpCodeLensProvider" mimeType="text/x-csharp"/>
+ </Extension>
+
</ExtensionModel>
diff --git a/main/src/addins/CSharpBinding/CSharpBinding.csproj b/main/src/addins/CSharpBinding/CSharpBinding.csproj
index 2a2746c11d..1adfa743db 100644
--- a/main/src/addins/CSharpBinding/CSharpBinding.csproj
+++ b/main/src/addins/CSharpBinding/CSharpBinding.csproj
@@ -424,6 +424,7 @@
<Compile Include="MonoDevelop.CSharp.Features\GotoDefinition\GotoDefinitionHelpers.cs" />
<Compile Include="MonoDevelop.CSharp.Features\GotoDefinition\GotoDefinitionService.cs" />
<Compile Include="Util\PortingExtensions.cs" />
+ <Compile Include="MonoDevelop.CSharp.Refactoring\CSharpCodeLensProvider.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Makefile.am" />
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/CSharpCodeLensProvider.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/CSharpCodeLensProvider.cs
new file mode 100644
index 0000000000..0c820ff72f
--- /dev/null
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/CSharpCodeLensProvider.cs
@@ -0,0 +1,131 @@
+//
+// CSharpCodeLensProvider.cs
+//
+// Author:
+// Mike Krüger <mikkrg@microsoft.com>
+//
+// Copyright (c) 2017 Microsoft Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Ide.Editor.Extension;
+using MonoDevelop.Ide.TypeSystem;
+using Microsoft.CodeAnalysis.CodeLens;
+using Microsoft.CodeAnalysis;
+using System.Linq;
+using Xwt;
+using Cairo;
+using MonoDevelop.Ide.Editor.Highlighting;
+using MonoDevelop.Components;
+using MonoDevelop.Core;
+using MonoDevelop.Ide.Fonts;
+
+namespace MonoDevelop.CSharp.Refactoring
+{
+ class CSharpCodeLens : CodeLens
+ {
+ readonly ICodeLensDisplayInfoService displayService;
+ readonly ICodeLensReferencesService referencesService;
+ readonly ISymbol symbol;
+ readonly SyntaxNode displayNode;
+ readonly Solution solution;
+ readonly DocumentId id;
+
+ public override Core.Text.TextSegment CodeLensSpan {
+ get {
+ return new Core.Text.TextSegment (displayNode.Span.Start, displayNode.Span.Length);
+ }
+ }
+
+ public CSharpCodeLens (Solution solution, DocumentId id, ICodeLensDisplayInfoService displayService, ICodeLensReferencesService referencesService, ISymbol symbol, SyntaxNode displayNode)
+ {
+ this.id = id;
+ this.solution = solution;
+ this.displayService = displayService;
+ this.referencesService = referencesService;
+ this.symbol = symbol;
+ this.displayNode = displayNode;
+ }
+
+ Size size;
+ ReferenceCount count;
+ public override Size Size => size;
+
+ public async Task Update (CancellationToken token)
+ {
+ count = await referencesService.GetReferenceCountAsync (solution, id, displayNode, 1000, token);
+ }
+
+ public override void Draw (CodeLansDrawingParameters drawingParameters)
+ {
+ var p = drawingParameters as GtkCodeLansDrawingParameters;
+ if (count == null || p == null)
+ return;
+ p.Context.Save ();
+ var theme = p.Editor.Options.GetEditorTheme ();
+ theme.TryGetColor (EditorThemeColors.FoldLine, out Components.HslColor color);
+ p.Context.SetSourceColor (color);
+ p.Context.Translate (p.X, p.Y);
+ p.Layout.FontDescription = FontService.SansFont;
+ string text;
+ if (count.IsCapped) {
+ text = GettextCatalog.GetString (">{0} references", count.Count);
+ } else {
+ text = GettextCatalog.GetString ("{0} references", count.Count);
+ }
+ p.Layout.SetMarkup ("<span size='small'>" + text + "</span>");
+ p.Context.ShowLayout (p.Layout);
+ p.Context.Restore ();
+ p.Layout.GetPixelSize (out int pw, out int ph);
+ size = new Size (pw, ph);
+ }
+ }
+
+ class CSharpCodeLensProvider : CodeLensProvider
+ {
+ public override async Task<IEnumerable<CodeLens>> GetLenses (TextEditor editor, DocumentContext ctx, CancellationToken token)
+ {
+ var languageService = ctx.RoslynWorkspace.Services.GetLanguageServices (LanguageNames.CSharp);
+ if (languageService == null)
+ return Enumerable.Empty<CodeLens> ();
+ var displayService = languageService.GetService<ICodeLensDisplayInfoService> ();
+ var referencesService = ctx.RoslynWorkspace.Services.GetService<ICodeLensReferencesService> ();
+ if (displayService == null || referencesService == null)
+ return Enumerable.Empty<CodeLens> ();
+ var model = await ctx.AnalysisDocument.GetSemanticModelAsync (token).ConfigureAwait (false);
+ var root = await model.SyntaxTree.GetRootAsync (token).ConfigureAwait (false);
+ var result = new List<CodeLens> ();
+ foreach (var node in model.SyntaxTree.GetRoot ().DescendantNodesAndSelf ()) {
+ var symbol = model.GetDeclaredSymbol (node);
+ if (symbol == null || symbol.Kind == SymbolKind.Namespace)
+ continue;
+ var displayNode = displayService.GetDisplayNode (node);
+ var newLens = new CSharpCodeLens (ctx.AnalysisDocument.Project.Solution, ctx.AnalysisDocument.Id, displayService, referencesService, symbol, displayNode);
+ await newLens.Update (token);
+ result.Add (newLens);
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj
index 5f8755a9d5..2dd9437c9b 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj
@@ -284,6 +284,7 @@
<Compile Include="Mono.TextEditor.Theatrics\SmartScrolledWindow.cs" />
<Compile Include="Mono.TextEditor.Theatrics\Stage.cs" />
<None Include="packages.config" />
+ <Compile Include="MonoDevelop.SourceEditor\TextMarker\CodeLensMarker.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="gtk-gui\gui.stetic">
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs
index 91db517e37..5955135c60 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs
@@ -3496,6 +3496,11 @@ namespace MonoDevelop.SourceEditor
return new MessageBubbleTextMarker (messageBubbleCache);
}
+ ICodeLensMarker ITextMarkerFactory.CreateCodeLensMarker (TextEditor editor)
+ {
+ return new CodeLensMarker ();
+ }
+
IGenericTextSegmentMarker ITextMarkerFactory.CreateGenericTextSegmentMarker (MonoDevelop.Ide.Editor.TextEditor editor, TextSegmentMarkerEffect effect, int offset, int length)
{
switch (effect) {
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/TextMarker/CodeLensMarker.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/TextMarker/CodeLensMarker.cs
new file mode 100644
index 0000000000..a77afdd9e1
--- /dev/null
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/TextMarker/CodeLensMarker.cs
@@ -0,0 +1,93 @@
+//
+// CodeLensMarker.cs
+//
+// Author:
+// Mike Krüger <mikkrg@microsoft.com>
+//
+// Copyright (c) 2017 Microsoft Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Linq;
+using Mono.TextEditor;
+using Mono.TextEditor.Highlighting;
+using MonoDevelop.SourceEditor.Wrappers;
+using MonoDevelop.Components;
+using MonoDevelop.Debugger;
+using MonoDevelop.Ide.Editor;
+using Xwt.Drawing;
+using System.Collections.Generic;
+using MonoDevelop.Ide.Editor.Highlighting;
+using MonoDevelop.Ide.Editor.Extension;
+
+namespace MonoDevelop.SourceEditor
+{
+ class CodeLensMarker : TextLineMarker, IExtendingTextLineMarker, ICodeLensMarker
+ {
+ public bool IsSpaceAbove => true;
+
+ public IDocumentLine Line => LineSegment;
+
+ public void Draw(MonoTextEditor editor, Cairo.Context g, int lineNr, Cairo.Rectangle lineArea)
+ {
+ double x = lineArea.X;
+ double y = lineArea.Y - editor.LineHeight;
+ var line = editor.GetLine (lineNr);
+ if (line == null)
+ return;
+ var lineLayout = editor.TextViewMargin.GetLayout (line);
+ if (lineLayout == null)
+ return;
+ var indent = line.GetIndentation (editor.Document);
+ lineLayout.GetCursorPos (indent.Length, out Pango.Rectangle strong_pos, out Pango.Rectangle weak_pos);
+ x += strong_pos.X / Pango.Scale.PangoScale;
+ using (var layout = new Pango.Layout (editor.PangoContext)) {
+ foreach (var codeLens in codeLenses) {
+ var param = new GtkCodeLansDrawingParameters (Ide.IdeApp.Workbench.ActiveDocument.Editor, lineNr, new Xwt.Rectangle (lineArea.X, lineArea.Y, lineArea.Width, lineArea.Height), x, y, layout, g);
+ codeLens.Draw (param);
+ x += codeLens.Size.Width + 4;
+ }
+ }
+ if (lineLayout.IsUncached)
+ lineLayout.Dispose ();
+ }
+
+ public double GetLineHeight(MonoTextEditor editor) => editor.LineHeight * 2;
+
+ #region ICodeLensMarker implementation
+ readonly List<CodeLens> codeLenses = new List<CodeLens>();
+
+ public int CodeLensCount => codeLenses.Count;
+
+ public void AddLens(CodeLens lens)
+ {
+ if (lens == null)
+ throw new ArgumentNullException(nameof(lens));
+ codeLenses.Add(lens);
+ }
+
+ public void RemoveLens(CodeLens lens)
+ {
+ if (lens == null)
+ throw new ArgumentNullException(nameof(lens));
+ codeLenses.Remove(lens);
+ }
+ #endregion
+ }
+}
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 b716716444..617f97a492 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml
@@ -238,6 +238,10 @@
<ExtensionNode name = "Assembly" type = "MonoDevelop.Core.AddIns.AssemblyExtensionNode" />
</ExtensionPoint>
+ <ExtensionPoint path = "/MonoDevelop/Ide/CodeLensProvider" name = "Code lens provider">
+ <Description>Algorithm for providing code lenses in a file.</Description>
+ <ExtensionNode name="CodeLens" type="MonoDevelop.Ide.Extensions.MimeTypeExtensionNode"/>
+ </ExtensionPoint>
<!-- Extensions -->
<Extension path = "/MonoDevelop/Core/Applications">
@@ -320,6 +324,7 @@
<Class class = "MonoDevelop.Ide.Editor.TextMate.TextMateFoldingTextEditorExtension" />
<Class class = "MonoDevelop.Ide.Editor.TextMate.TextMateIndentationTextEditorExtension" />
<Class class = "MonoDevelop.Ide.Editor.TextMate.TextMateCompletionTextEditorExtension" />
+ <Class class = "MonoDevelop.Ide.Editor.Extension.CodeLensTextEditorExtension" />
<Class id="FinalStep" class = "MonoDevelop.Ide.Editor.Extension.TextEditorExtensionMarker" />
</Extension>
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/CodeLensTextEditorExtension.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/CodeLensTextEditorExtension.cs
new file mode 100644
index 0000000000..113071f296
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/CodeLensTextEditorExtension.cs
@@ -0,0 +1,204 @@
+//
+// AbstractCodeLensExtension.cs
+//
+// Author:
+// Mike Krüger <mikkrg@microsoft.com>
+//
+// Copyright (c) 2017 Microsoft Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using MonoDevelop.Ide.Gui.Content;
+using System.Collections.Generic;
+using System.Linq;
+using MonoDevelop.Ide.FindInFiles;
+using System.Threading;
+using System.Threading.Tasks;
+using MonoDevelop.Core;
+using System.Diagnostics.CodeAnalysis;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Core.Text;
+using System.Collections.Immutable;
+using Mono.Addins;
+using MonoDevelop.Ide.Extensions;
+using MonoDevelop.Ide.TypeSystem;
+using Cairo;
+
+namespace MonoDevelop.Ide.Editor.Extension
+{
+ public sealed class GtkCodeLansDrawingParameters : CodeLansDrawingParameters
+ {
+ public Pango.Layout Layout { get; private set; }
+ public Context Context { get; private set; }
+
+ public GtkCodeLansDrawingParameters (TextEditor editor, int lineNr, Xwt.Rectangle lineArea, double x, double y, Pango.Layout layout, Context context) : base (editor, lineNr, lineArea, x, y)
+ {
+ Layout = layout;
+ Context = context;
+ }
+ }
+
+ public abstract class CodeLansDrawingParameters
+ {
+ public TextEditor Editor { get; private set; }
+ public int LineNr { get; private set; }
+ public Xwt.Rectangle LineArea { get; private set; }
+
+ public double X { get; private set; }
+ public double Y { get; private set; }
+
+ public CodeLansDrawingParameters (TextEditor editor, int lineNr, Xwt.Rectangle lineArea, double x, double y)
+ {
+ Editor = editor;
+ LineNr = lineNr;
+ LineArea = lineArea;
+ X = x;
+ Y = y;
+ }
+ }
+
+ public abstract class CodeLens
+ {
+ public abstract TextSegment CodeLensSpan { get; }
+
+ public abstract void Draw (CodeLansDrawingParameters drawingParameters);
+
+ public abstract Xwt.Size Size { get; }
+ }
+
+ public abstract class CodeLensProvider
+ {
+ internal string MimeType { get; set; }
+
+ public abstract Task<IEnumerable<CodeLens>> GetLenses (TextEditor editor, DocumentContext ctx, CancellationToken token);
+ }
+
+ class CodeLensTextEditorExtension : TextEditorExtension
+ {
+ CancellationTokenSource src = new CancellationTokenSource ();
+ bool isDisposed;
+ static List<CodeLensProvider> codeLensProviders = new List<CodeLensProvider> ();
+
+ static CodeLensTextEditorExtension ()
+ {
+ AddinManager.AddExtensionNodeHandler ("/MonoDevelop/Ide/CodeLensProvider", delegate (object sender, ExtensionNodeEventArgs args) {
+ var node = (MimeTypeExtensionNode)args.ExtensionNode;
+ switch (args.Change) {
+ case ExtensionChange.Add:
+ var matcher = (CodeLensProvider)node.CreateInstance ();
+ matcher.MimeType = node.MimeType;
+ codeLensProviders.Add (matcher);
+ break;
+ case ExtensionChange.Remove:
+ var toRemove = codeLensProviders.FirstOrDefault (m => m.MimeType == node.MimeType);
+ if (toRemove != null)
+ codeLensProviders.Remove (toRemove);
+ break;
+ }
+ });
+ }
+
+ protected override void Initialize ()
+ {
+ DocumentContext.DocumentParsed += DocumentContext_DocumentParsed;
+ }
+
+ public override void Dispose ()
+ {
+ if (isDisposed)
+ return;
+ isDisposed = true;
+ CancelDocumentParsedUpdate ();
+ DocumentContext.DocumentParsed -= DocumentContext_DocumentParsed;
+ base.Dispose ();
+ }
+
+ void CancelDocumentParsedUpdate ()
+ {
+ src.Cancel ();
+ src = new CancellationTokenSource ();
+ }
+
+ void DocumentContext_DocumentParsed (object sender, EventArgs e)
+ {
+ CancelDocumentParsedUpdate ();
+ var token = src.Token;
+ var parsedDocument = DocumentContext.ParsedDocument;
+ if (!isDisposed)
+ UpdateLenses (token);
+ }
+
+ List<ICodeLensMarker> codeLensMarkers = new List<ICodeLensMarker> ();
+ struct CodeLensCacheItem
+ {
+ public ICodeLensMarker Marker { get; set; }
+ public CodeLens Lens { get; set; }
+
+ public CodeLensCacheItem (ICodeLensMarker marker, CodeLens lens)
+ {
+ Marker = marker;
+ Lens = lens;
+ }
+ }
+
+ Dictionary<CodeLensProvider, List<CodeLensCacheItem>> lensCache = new Dictionary<CodeLensProvider, List<CodeLensCacheItem>> ();
+
+ async void UpdateLenses (CancellationToken token = default (CancellationToken))
+ {
+ foreach (var provider in codeLensProviders) {
+ var lenses = await provider.GetLenses (Editor, DocumentContext, token).ConfigureAwait (false);
+ await Runtime.RunInMainThread (delegate {
+ if (lensCache.TryGetValue (provider, out List<CodeLensCacheItem> cache)) {
+ lensCache.Remove (provider);
+ foreach (var item in cache)
+ item.Marker.RemoveLens (item.Lens);
+ }
+
+ var newCache = new List<CodeLensCacheItem> ();
+ foreach (var lens in lenses) {
+ var line = Editor.GetLineByOffset (lens.CodeLensSpan.Offset);
+ var codeLensMarker = Editor.GetLineMarkers (line).OfType<ICodeLensMarker> ().FirstOrDefault ();
+ if (codeLensMarker == null) {
+ codeLensMarker = Editor.TextMarkerFactory.CreateCodeLensMarker (Editor);
+ Editor.AddMarker (line, codeLensMarker);
+ codeLensMarkers.Add (codeLensMarker);
+ }
+ codeLensMarker.AddLens (lens);
+ newCache.Add (new CodeLensCacheItem (codeLensMarker, lens));
+ }
+ lensCache.Add (provider, newCache);
+ });
+ }
+
+ await Runtime.RunInMainThread (delegate {
+ RemoveUnusedCodeLensMarkers ();
+ });
+ }
+
+ void RemoveUnusedCodeLensMarkers ()
+ {
+ foreach (var marker in codeLensMarkers.ToArray ()) {
+ if (marker.CodeLensCount == 0) {
+ Editor.RemoveMarker (marker);
+ codeLensMarkers.Remove (marker);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextLineMarker.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextLineMarker.cs
index 982033e951..34a51d5efe 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextLineMarker.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/ITextLineMarker.cs
@@ -77,4 +77,12 @@ namespace MonoDevelop.Ide.Editor
void AddTask (MonoDevelop.Ide.Tasks.TaskListEntry task);
}
+
+ public interface ICodeLensMarker : ITextLineMarker
+ {
+ int CodeLensCount { get; }
+
+ void AddLens (MonoDevelop.Ide.Editor.Extension.CodeLens lens);
+ void RemoveLens (MonoDevelop.Ide.Editor.Extension.CodeLens lens);
+ }
} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextMarkerFactory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextMarkerFactory.cs
index 95900bc1d4..1581b639a4 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextMarkerFactory.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextMarkerFactory.cs
@@ -44,6 +44,7 @@ namespace MonoDevelop.Ide.Editor
ITextLineMarker CreateAsmLineMarker (TextEditor editor);
IUnitTestMarker CreateUnitTestMarker (TextEditor editor, UnitTestMarkerHost host, UnitTestLocation unitTestLocation);
IMessageBubbleLineMarker CreateMessageBubbleLineMarker (TextEditor editor);
+ ICodeLensMarker CreateCodeLensMarker (TextEditor editor);
#endregion
#region Segment marker
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
index 9a8a810544..a7e558474b 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
@@ -9460,6 +9460,7 @@
<Compile Include="MonoDevelop.Ide.Projects\LanguageCellRenderer.cs" />
<Compile Include="MonoDevelop.Components\RestartPanel.cs" />
<Compile Include="MonoDevelop.Ide.Gui.OptionPanels\DotNetCompileTargetSelector.cs" />
+ <Compile Include="MonoDevelop.Ide.Editor.Extension\CodeLensTextEditorExtension.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Makefile.am" />