lookup C# symbol in razor

This commit is contained in:
Matt Parker
2025-10-11 15:50:47 +10:00
parent 5667c3e846
commit 9e75f6d22a
2 changed files with 55 additions and 3 deletions

View File

@@ -479,6 +479,35 @@ public static class RoslynAnalysis
public static async Task<ISymbol?> LookupSymbol(SharpIdeFile fileModel, LinePosition linePosition)
{
await _solutionLoadedTcs.Task;
var symbol = fileModel.IsRazorFile ? await LookupSymbolInRazor(fileModel, linePosition) : await LookupSymbolInCs(fileModel, linePosition);
return symbol;
}
private static async Task<ISymbol?> LookupSymbolInRazor(SharpIdeFile fileModel, LinePosition linePosition, CancellationToken cancellationToken = default)
{
var sharpIdeProjectModel = ((IChildSharpIdeNode) fileModel).GetNearestProjectNode()!;
var project = _workspace!.CurrentSolution.Projects.Single(s => s.FilePath == sharpIdeProjectModel!.FilePath);
var additionalDocument = project.AdditionalDocuments.Single(s => s.FilePath == fileModel.Path);
var razorProjectSnapshot = _snapshotManager!.GetSnapshot(project);
var documentSnapshot = razorProjectSnapshot.GetDocument(additionalDocument);
var razorCodeDocument = await razorProjectSnapshot.GetRequiredCodeDocumentAsync(documentSnapshot, cancellationToken);
var razorCSharpDocument = razorCodeDocument.GetRequiredCSharpDocument();
var generatedDocument = await razorProjectSnapshot.GetRequiredGeneratedDocumentAsync(documentSnapshot, cancellationToken);
var generatedDocSyntaxRoot = await generatedDocument.GetSyntaxRootAsync(cancellationToken);
var razorText = await additionalDocument.GetTextAsync(cancellationToken);
var mappedPosition = MapRazorLinePositionToGeneratedCSharpAbsolutePosition(razorCSharpDocument, razorText, linePosition);
var semanticModelAsync = await generatedDocument.GetSemanticModelAsync(cancellationToken);
var symbol = GetSymbolAtPosition(semanticModelAsync!, generatedDocSyntaxRoot!, mappedPosition!.Value);
return symbol;
}
private static async Task<ISymbol?> LookupSymbolInCs(SharpIdeFile fileModel, LinePosition linePosition)
{
var project = _workspace!.CurrentSolution.Projects.Single(s => s.FilePath == ((IChildSharpIdeNode)fileModel).GetNearestProjectNode()!.FilePath);
var document = project.Documents.Single(s => s.FilePath == fileModel.Path);
Guard.Against.Null(document, nameof(document));
@@ -487,9 +516,13 @@ public static class RoslynAnalysis
var semanticModel = await document.GetSemanticModelAsync();
Guard.Against.Null(semanticModel, nameof(semanticModel));
var syntaxRoot = await document.GetSyntaxRootAsync();
var node = syntaxRoot!.FindToken(position).Parent!;
var symbol = semanticModel.GetSymbolInfo(node).Symbol ?? semanticModel.GetDeclaredSymbol(node);
return GetSymbolAtPosition(semanticModel, syntaxRoot!, position);
}
private static ISymbol? GetSymbolAtPosition(SemanticModel semanticModel, SyntaxNode root, int position)
{
var node = root.FindToken(position).Parent!;
var symbol = semanticModel.GetSymbolInfo(node).Symbol ?? semanticModel.GetDeclaredSymbol(node);
if (symbol is null)
{
Console.WriteLine("No symbol found at position");
@@ -500,6 +533,25 @@ public static class RoslynAnalysis
return symbol;
}
private static int? MapRazorLinePositionToGeneratedCSharpAbsolutePosition(RazorCSharpDocument razorCSharpDocument, SourceText razorText, LinePosition razorLinePosition)
{
var mappings = razorCSharpDocument.SourceMappings;
var razorOffset = razorText.Lines.GetPosition(razorLinePosition);
foreach (var mapping in mappings)
{
var span = mapping.OriginalSpan;
if (razorOffset >= span.AbsoluteIndex && razorOffset < span.AbsoluteIndex + span.Length)
{
// Calculate offset within the mapping
var offsetInMapping = razorOffset - span.AbsoluteIndex;
// Map to generated C# position
return mapping.GeneratedSpan.AbsoluteIndex + offsetInMapping;
}
}
return null;
}
public static void UpdateDocument(SharpIdeFile fileModel, string newContent)
{
Guard.Against.Null(fileModel, nameof(fileModel));

View File

@@ -23,7 +23,6 @@ public static class SymbolInfoComponents
label.Pop();
label.AddText(" ");
label.AddStaticModifier(methodSymbol);
label.AddText(" ");
label.AddMethodReturnType(methodSymbol);
label.AddText(" ");
label.AddMethodName(methodSymbol);
@@ -61,6 +60,7 @@ public static class SymbolInfoComponents
label.PushColor(CachedColors.KeywordBlue);
label.AddText("static");
label.Pop();
label.AddText(" ");
}
}