Skip to content
This repository was archived by the owner on Oct 4, 2021. It is now read-only.

Commit 525f244

Browse files
KirillOsenkovmonojenkins
authored andcommitted
Implement Go To Definition for Razor
1 parent df7f3cd commit 525f244

File tree

3 files changed

+70
-13
lines changed

3 files changed

+70
-13
lines changed

main/src/addins/CSharpBinding/MonoDevelop.Ide.Completion.Presentation/MonoDevelopContainedDocument.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ public class MonoDevelopContainedDocument : IMonoDevelopHostDocument
5454
public IMonoDevelopContainedLanguageHost ContainedLanguageHost { get; private set; }
5555
private readonly HostType _hostType;
5656

57+
public IProjectionBuffer TopBuffer => DataBuffer;
58+
5759
// _workspace will only be set once the Workspace is available
5860
private Workspace _workspace;
5961

main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.RoslynServices/MonoDevelopDocumentNavigationService.cs

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Composition;
3+
using System.Linq;
34
using System.Threading;
45
using System.Threading.Tasks;
56
using Microsoft.CodeAnalysis;
@@ -9,7 +10,10 @@
910
using Microsoft.CodeAnalysis.Options;
1011
using Microsoft.CodeAnalysis.Text;
1112
using Microsoft.VisualStudio.Text;
13+
using Microsoft.VisualStudio.Text.Projection;
1214
using MonoDevelop.Core;
15+
using MonoDevelop.Ide.Composition;
16+
using MonoDevelop.Ide.Editor.Projection;
1317
using MonoDevelop.Ide.TypeSystem;
1418

1519
namespace MonoDevelop.Ide.RoslynServices
@@ -19,11 +23,14 @@ internal sealed class VisualStudioDocumentNavigationServiceFactory : IWorkspaceS
1923
{
2024
private readonly IDocumentNavigationService _singleton;
2125

26+
[Import]
27+
public IBufferGraphFactoryService BufferGraphFactoryService { get; set; }
28+
2229
[ImportingConstructor]
2330
[Obsolete (MefConstruction.ImportingConstructorMessage, error: true)]
2431
private VisualStudioDocumentNavigationServiceFactory ()
2532
{
26-
_singleton = new MonoDevelopDocumentNavigationService ();
33+
_singleton = new MonoDevelopDocumentNavigationService (this);
2734
}
2835

2936
public IWorkspaceService CreateService (HostWorkspaceServices workspaceServices)
@@ -34,6 +41,13 @@ public IWorkspaceService CreateService (HostWorkspaceServices workspaceServices)
3441

3542
class MonoDevelopDocumentNavigationService : IDocumentNavigationService
3643
{
44+
private VisualStudioDocumentNavigationServiceFactory factory;
45+
46+
public MonoDevelopDocumentNavigationService (VisualStudioDocumentNavigationServiceFactory visualStudioDocumentNavigationServiceFactory)
47+
{
48+
this.factory = visualStudioDocumentNavigationServiceFactory;
49+
}
50+
3751
public bool CanNavigateToSpan (Workspace workspace, DocumentId documentId, TextSpan textSpan)
3852
{
3953
// Navigation should not change the context of linked files and Shared Projects.
@@ -99,7 +113,7 @@ public bool TryNavigateToSpan (Workspace workspace, DocumentId documentId, TextS
99113

100114
Runtime.AssertMainThread ();
101115

102-
var document = OpenDocument (workspace, documentId, options);
116+
var document = workspace.CurrentSolution.GetDocument (documentId);
103117
if (document == null) {
104118
return false;
105119
}
@@ -127,7 +141,7 @@ public bool TryNavigateToLineAndOffset (Workspace workspace, DocumentId document
127141

128142
Runtime.AssertMainThread ();
129143

130-
var document = OpenDocument (workspace, documentId, options);
144+
var document = workspace.CurrentSolution.GetDocument (documentId);
131145
if (document == null) {
132146
return false;
133147
}
@@ -149,7 +163,7 @@ public bool TryNavigateToPosition (Workspace workspace, DocumentId documentId, i
149163

150164
Runtime.AssertMainThread ();
151165

152-
var document = OpenDocument (workspace, documentId, options);
166+
var document = workspace.CurrentSolution.GetDocument (documentId);
153167
if (document == null) {
154168
return false;
155169
}
@@ -222,13 +236,41 @@ private static Document OpenDocument (Workspace workspace, DocumentId documentId
222236

223237
private bool NavigateTo (Document document, TextSpan span)
224238
{
239+
string filePath = document.FilePath;
240+
filePath = GetActualFilePathToOpen (filePath);
225241
var proj = (document.Project.Solution.Workspace as MonoDevelopWorkspace)?.GetMonoProject (document.Project);
226-
var task = IdeApp.Workbench.OpenDocument (new Gui.FileOpenInformation (document.FilePath, proj) {
242+
var task = IdeApp.Workbench.OpenDocument (new Gui.FileOpenInformation (filePath, proj) {
227243
Offset = span.Start
228244
});
229245
return true;
230246
}
231247

248+
/// <summary>
249+
/// Razor: Strip the .g.cs since we want to open the corresponding .cshtml or .razor document.
250+
///
251+
/// In Visual Studio for Windows the underlying C# buffer is added to the workspace with the
252+
/// .cshtml or .razor extension (without the .g.cs) part, so they don't have to worry about
253+
/// this. In our case we have an assumption somewhere that all C# documents in the workspace
254+
/// have the .cs extension, so we're adding the .g.cs part that we need to strip here.
255+
///
256+
/// This is not great to hardcode application-specific logic here, but we don't anticipate
257+
/// more scenarios where we want to open a different file than requested, so it doesn't
258+
/// warrant an extension point at this time.
259+
/// </summary>
260+
string GetActualFilePathToOpen (string filePath)
261+
{
262+
if (filePath == null) {
263+
return null;
264+
}
265+
266+
if (filePath.EndsWith (".cshtml.g.cs", StringComparison.OrdinalIgnoreCase) ||
267+
filePath.EndsWith (".razor.g.cs", StringComparison.OrdinalIgnoreCase)) {
268+
filePath = filePath.Substring (0, filePath.Length - ".g.cs".Length);
269+
}
270+
271+
return filePath;
272+
}
273+
232274
private bool IsSecondaryBuffer (Workspace workspace, Document document)
233275
{
234276
var containedDocument = MonoDevelopHostDocumentRegistration.FromDocument (document);
@@ -239,23 +281,33 @@ private bool IsSecondaryBuffer (Workspace workspace, Document document)
239281
return true;
240282
}
241283

242-
public static bool TryMapSpanFromSecondaryBufferToPrimaryBuffer (TextSpan spanInSecondaryBuffer, Microsoft.CodeAnalysis.Workspace workspace, Document document, out TextSpan spanInPrimaryBuffer)
284+
public bool TryMapSpanFromSecondaryBufferToPrimaryBuffer (TextSpan spanInSecondaryBuffer, Microsoft.CodeAnalysis.Workspace workspace, Document document, out TextSpan spanInPrimaryBuffer)
243285
{
244286
spanInPrimaryBuffer = default;
245287

246288
var containedDocument = MonoDevelopHostDocumentRegistration.FromDocument (document);
247289
if (containedDocument == null) {
248290
return false;
249291
}
250-
throw new NotImplementedException ();
251-
//var bufferCoordinator = containedDocument.BufferCoordinator;
252292

253-
//var primary = new VsTextSpan [1];
254-
//var hresult = bufferCoordinator.MapSecondaryToPrimarySpan (spanInSecondaryBuffer, primary);
293+
var projectionBuffer = containedDocument.TopBuffer;
294+
295+
var bufferGraph = factory.BufferGraphFactoryService.CreateBufferGraph (projectionBuffer);
255296

256-
//spanInPrimaryBuffer = primary [0];
297+
if (document.TryGetText(out var sourceText) && sourceText.Container.TryGetTextBuffer() is ITextBuffer languageBuffer) {
298+
var secondarySnapshot = languageBuffer.CurrentSnapshot;
299+
var snapshotSpanInSecondaryBuffer = new SnapshotSpan (secondarySnapshot, new Span (spanInSecondaryBuffer.Start, spanInSecondaryBuffer.Length));
300+
var topBufferSnapshotSpan = bufferGraph.MapUpToSnapshot (
301+
snapshotSpanInSecondaryBuffer,
302+
SpanTrackingMode.EdgeExclusive,
303+
projectionBuffer.CurrentSnapshot).FirstOrDefault();
304+
if (topBufferSnapshotSpan != default) {
305+
spanInPrimaryBuffer = new TextSpan (topBufferSnapshotSpan.Start, topBufferSnapshotSpan.Length);
306+
return true;
307+
}
308+
}
257309

258-
//return ErrorHandler.Succeeded (hresult);
310+
return false;
259311
}
260312

261313
private bool CanMapFromSecondaryBufferToPrimaryBuffer (Workspace workspace, Document document, TextSpan spanInSecondaryBuffer)

main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/IMonoDevelopHostDocument.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
using Microsoft.CodeAnalysis;
77
using Microsoft.CodeAnalysis.Text;
88
using Microsoft.VisualStudio.Text;
9-
9+
using Microsoft.VisualStudio.Text.Projection;
10+
1011
namespace MonoDevelop.Ide.TypeSystem
1112
{
1213
interface IMonoDevelopHostDocument
@@ -15,6 +16,8 @@ interface IMonoDevelopHostDocument
1516
/// Updates the text of the document.
1617
/// </summary>
1718
void UpdateText (SourceText newText);
19+
20+
IProjectionBuffer TopBuffer { get; }
1821
}
1922

2023
static class MonoDevelopHostDocumentRegistration

0 commit comments

Comments
 (0)