diff options
author | Sandy Armstrong <sandy@xamarin.com> | 2019-11-15 00:15:52 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-11-15 00:15:52 +0300 |
commit | e41879316497b22fe9ec78bd32855af3176f4b16 (patch) | |
tree | 63fcd30ab2a1470402e0d6fc52005267f3e60484 /main | |
parent | 5b2d98fb733294d4dfd0b1b398aa4f628ac84e22 (diff) | |
parent | 2dcee0fead11b287a3169bd95194652893ecfb7c (diff) |
Merge pull request #9308 from mono/backport-pr-9307-to-release-8.4
[release-8.4] Implement Go To Definition for Razor
Diffstat (limited to 'main')
3 files changed, 67 insertions, 14 deletions
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.Ide.Completion.Presentation/MonoDevelopContainedDocument.cs b/main/src/addins/CSharpBinding/MonoDevelop.Ide.Completion.Presentation/MonoDevelopContainedDocument.cs index c014428ff0..4c0af01875 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.Ide.Completion.Presentation/MonoDevelopContainedDocument.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.Ide.Completion.Presentation/MonoDevelopContainedDocument.cs @@ -54,6 +54,8 @@ namespace MonoDevelop.Ide.Completion.Presentation public IMonoDevelopContainedLanguageHost ContainedLanguageHost { get; private set; } private readonly HostType _hostType; + public IProjectionBuffer TopBuffer => DataBuffer; + // _workspace will only be set once the Workspace is available private Workspace _workspace;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.RoslynServices/MonoDevelopDocumentNavigationService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.RoslynServices/MonoDevelopDocumentNavigationService.cs index 26935aef59..39c9cdbe9b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.RoslynServices/MonoDevelopDocumentNavigationService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.RoslynServices/MonoDevelopDocumentNavigationService.cs @@ -1,7 +1,7 @@ using System; using System.Composition; +using System.Linq; using System.Threading; -using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; @@ -9,6 +9,7 @@ using Microsoft.CodeAnalysis.Navigation; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Projection; using MonoDevelop.Core; using MonoDevelop.Ide.TypeSystem; @@ -19,11 +20,14 @@ namespace MonoDevelop.Ide.RoslynServices { private readonly IDocumentNavigationService _singleton; + [Import] + public IBufferGraphFactoryService BufferGraphFactoryService { get; set; } + [ImportingConstructor] [Obsolete (MefConstruction.ImportingConstructorMessage, error: true)] private VisualStudioDocumentNavigationServiceFactory () { - _singleton = new MonoDevelopDocumentNavigationService (); + _singleton = new MonoDevelopDocumentNavigationService (this); } public IWorkspaceService CreateService (HostWorkspaceServices workspaceServices) @@ -34,6 +38,13 @@ namespace MonoDevelop.Ide.RoslynServices class MonoDevelopDocumentNavigationService : IDocumentNavigationService { + private VisualStudioDocumentNavigationServiceFactory factory; + + public MonoDevelopDocumentNavigationService (VisualStudioDocumentNavigationServiceFactory visualStudioDocumentNavigationServiceFactory) + { + this.factory = visualStudioDocumentNavigationServiceFactory; + } + public bool CanNavigateToSpan (Workspace workspace, DocumentId documentId, TextSpan textSpan) { // Navigation should not change the context of linked files and Shared Projects. @@ -99,13 +110,12 @@ namespace MonoDevelop.Ide.RoslynServices Runtime.AssertMainThread (); - var document = OpenDocument (workspace, documentId, options); + var document = workspace.CurrentSolution.GetDocument (documentId); if (document == null) { return false; } var text = document.GetTextSynchronously (CancellationToken.None); - var textBuffer = text.Container.GetTextBuffer (); var boundedTextSpan = GetSpanWithinDocumentBounds (textSpan, text.Length); if (boundedTextSpan != textSpan) { @@ -127,7 +137,7 @@ namespace MonoDevelop.Ide.RoslynServices Runtime.AssertMainThread (); - var document = OpenDocument (workspace, documentId, options); + var document = workspace.CurrentSolution.GetDocument (documentId); if (document == null) { return false; } @@ -149,7 +159,7 @@ namespace MonoDevelop.Ide.RoslynServices Runtime.AssertMainThread (); - var document = OpenDocument (workspace, documentId, options); + var document = workspace.CurrentSolution.GetDocument (documentId); if (document == null) { return false; } @@ -222,13 +232,41 @@ namespace MonoDevelop.Ide.RoslynServices private bool NavigateTo (Document document, TextSpan span) { + string filePath = document.FilePath; + filePath = GetActualFilePathToOpen (filePath); var proj = (document.Project.Solution.Workspace as MonoDevelopWorkspace)?.GetMonoProject (document.Project); - var task = IdeApp.Workbench.OpenDocument (new Gui.FileOpenInformation (document.FilePath, proj) { + var task = IdeApp.Workbench.OpenDocument (new Gui.FileOpenInformation (filePath, proj) { Offset = span.Start }); return true; } + /// <summary> + /// Razor: Strip the .g.cs since we want to open the corresponding .cshtml or .razor document. + /// + /// In Visual Studio for Windows the underlying C# buffer is added to the workspace with the + /// .cshtml or .razor extension (without the .g.cs) part, so they don't have to worry about + /// this. In our case we have an assumption somewhere that all C# documents in the workspace + /// have the .cs extension, so we're adding the .g.cs part that we need to strip here. + /// + /// This is not great to hardcode application-specific logic here, but we don't anticipate + /// more scenarios where we want to open a different file than requested, so it doesn't + /// warrant an extension point at this time. + /// </summary> + string GetActualFilePathToOpen (string filePath) + { + if (filePath == null) { + return null; + } + + if (filePath.EndsWith (".cshtml.g.cs", StringComparison.OrdinalIgnoreCase) || + filePath.EndsWith (".razor.g.cs", StringComparison.OrdinalIgnoreCase)) { + filePath = filePath.Substring (0, filePath.Length - ".g.cs".Length); + } + + return filePath; + } + private bool IsSecondaryBuffer (Workspace workspace, Document document) { var containedDocument = MonoDevelopHostDocumentRegistration.FromDocument (document); @@ -239,7 +277,7 @@ namespace MonoDevelop.Ide.RoslynServices return true; } - public static bool TryMapSpanFromSecondaryBufferToPrimaryBuffer (TextSpan spanInSecondaryBuffer, Microsoft.CodeAnalysis.Workspace workspace, Document document, out TextSpan spanInPrimaryBuffer) + public bool TryMapSpanFromSecondaryBufferToPrimaryBuffer (TextSpan spanInSecondaryBuffer, Microsoft.CodeAnalysis.Workspace workspace, Document document, out TextSpan spanInPrimaryBuffer) { spanInPrimaryBuffer = default; @@ -247,15 +285,25 @@ namespace MonoDevelop.Ide.RoslynServices if (containedDocument == null) { return false; } - throw new NotImplementedException (); - //var bufferCoordinator = containedDocument.BufferCoordinator; - //var primary = new VsTextSpan [1]; - //var hresult = bufferCoordinator.MapSecondaryToPrimarySpan (spanInSecondaryBuffer, primary); + var projectionBuffer = containedDocument.TopBuffer; + + var bufferGraph = factory.BufferGraphFactoryService.CreateBufferGraph (projectionBuffer); - //spanInPrimaryBuffer = primary [0]; + if (document.TryGetText(out var sourceText) && sourceText.Container.TryGetTextBuffer() is ITextBuffer languageBuffer) { + var secondarySnapshot = languageBuffer.CurrentSnapshot; + var snapshotSpanInSecondaryBuffer = new SnapshotSpan (secondarySnapshot, new Span (spanInSecondaryBuffer.Start, spanInSecondaryBuffer.Length)); + var topBufferSnapshotSpan = bufferGraph.MapUpToSnapshot ( + snapshotSpanInSecondaryBuffer, + SpanTrackingMode.EdgeExclusive, + projectionBuffer.CurrentSnapshot).FirstOrDefault(); + if (topBufferSnapshotSpan != default) { + spanInPrimaryBuffer = new TextSpan (topBufferSnapshotSpan.Start, topBufferSnapshotSpan.Length); + return true; + } + } - //return ErrorHandler.Succeeded (hresult); + return false; } private bool CanMapFromSecondaryBufferToPrimaryBuffer (Workspace workspace, Document document, TextSpan spanInSecondaryBuffer) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/IMonoDevelopHostDocument.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/IMonoDevelopHostDocument.cs index 05c71b9d95..3a188492c5 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/IMonoDevelopHostDocument.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/IMonoDevelopHostDocument.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Projection; namespace MonoDevelop.Ide.TypeSystem
{
@@ -15,6 +16,8 @@ namespace MonoDevelop.Ide.TypeSystem /// Updates the text of the document.
/// </summary>
void UpdateText (SourceText newText);
+ + IProjectionBuffer TopBuffer { get; } }
static class MonoDevelopHostDocumentRegistration
|