зеркало из https://github.com/dotnet/razor.git
Allow LSP and cohosting to provide specialized methods to get a syntax tree for a C# document
This commit is contained in:
Родитель
e16582150b
Коммит
efceb90f2d
|
@ -5,10 +5,15 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.Razor.DocumentMapping;
|
||||
using Microsoft.CodeAnalysis.Razor.GoToDefinition;
|
||||
using Microsoft.CodeAnalysis.Razor.Logging;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
using Microsoft.CodeAnalysis.Razor.Workspaces;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.LanguageServer.Definition;
|
||||
|
@ -19,4 +24,9 @@ internal sealed class RazorComponentDefinitionService(
|
|||
ILoggerFactory loggerFactory)
|
||||
: AbstractRazorComponentDefinitionService(componentSearchEngine, documentMappingService, loggerFactory.GetOrCreateLogger<RazorComponentDefinitionService>())
|
||||
{
|
||||
protected override ValueTask<SyntaxTree> GetCSharpSyntaxTreeAsync(IDocumentSnapshot documentSnapshot, RazorCodeDocument codeDocument, CancellationToken cancellationToken)
|
||||
{
|
||||
var csharpText = codeDocument.GetCSharpSourceText();
|
||||
return new(CSharpSyntaxTree.ParseText(csharpText, cancellationToken: cancellationToken));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,9 +70,10 @@ internal abstract class AbstractRazorComponentDefinitionService(
|
|||
_logger.LogInformation($"Attempting to get definition from an attribute directly.");
|
||||
|
||||
var originCodeDocument = await documentSnapshot.GetGeneratedOutputAsync().ConfigureAwait(false);
|
||||
var syntaxTree = await GetCSharpSyntaxTreeAsync(documentSnapshot, originCodeDocument, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var range = await RazorComponentDefinitionHelpers
|
||||
.TryGetPropertyRangeAsync(originCodeDocument, attributeDescriptor.GetPropertyName(), _documentMappingService, _logger, cancellationToken)
|
||||
.TryGetPropertyRangeAsync(originCodeDocument, syntaxTree, attributeDescriptor.GetPropertyName(), _documentMappingService, _logger, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (range is not null)
|
||||
|
@ -87,4 +88,6 @@ internal abstract class AbstractRazorComponentDefinitionService(
|
|||
// at least then press F7 to go there.
|
||||
return VsLspFactory.DefaultRange;
|
||||
}
|
||||
|
||||
protected abstract ValueTask<SyntaxTree> GetCSharpSyntaxTreeAsync(IDocumentSnapshot documentSnapshot, RazorCodeDocument codeDocument, CancellationToken cancellationToken);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Razor.DocumentMapping;
|
||||
using Microsoft.CodeAnalysis.Razor.Logging;
|
||||
|
@ -131,12 +130,13 @@ internal static class RazorComponentDefinitionHelpers
|
|||
|
||||
public static async Task<LspRange?> TryGetPropertyRangeAsync(
|
||||
RazorCodeDocument codeDocument,
|
||||
SyntaxTree csharpSyntaxTree,
|
||||
string propertyName,
|
||||
IDocumentMappingService documentMappingService,
|
||||
ILogger logger,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// Parse the C# file and find the property that matches the name.
|
||||
// Process the C# tree and find the property that matches the name.
|
||||
// We don't worry about parameter attributes here for two main reasons:
|
||||
// 1. We don't have symbolic information, so the best we could do would be checking for any
|
||||
// attribute named Parameter, regardless of which namespace. It also means we would have
|
||||
|
@ -147,9 +147,8 @@ internal static class RazorComponentDefinitionHelpers
|
|||
// tag helper attribute. If they don't have the [Parameter] attribute then the Razor compiler
|
||||
// will error, but allowing them to Go To Def on that property regardless, actually helps
|
||||
// them fix the error.
|
||||
var csharpText = codeDocument.GetCSharpSourceText();
|
||||
var syntaxTree = CSharpSyntaxTree.ParseText(csharpText, cancellationToken: cancellationToken);
|
||||
var root = await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var root = await csharpSyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Since we know how the compiler generates the C# source we can be a little specific here, and avoid
|
||||
// long tree walks. If the compiler ever changes how they generate their code, the tests for this will break
|
||||
|
@ -169,6 +168,7 @@ internal static class RazorComponentDefinitionHelpers
|
|||
return null;
|
||||
}
|
||||
|
||||
var csharpText = codeDocument.GetCSharpSourceText();
|
||||
var range = csharpText.GetRange(property.Identifier.Span);
|
||||
if (documentMappingService.TryMapToHostDocumentRange(codeDocument.GetCSharpDocument(), range, out var originalRange))
|
||||
{
|
||||
|
|
|
@ -2,10 +2,17 @@
|
|||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||
|
||||
using System.Composition;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Razor.DocumentMapping;
|
||||
using Microsoft.CodeAnalysis.Razor.GoToDefinition;
|
||||
using Microsoft.CodeAnalysis.Razor.Logging;
|
||||
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
|
||||
using Microsoft.CodeAnalysis.Razor.Workspaces;
|
||||
using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Remote.Razor.GoToDefinition;
|
||||
|
||||
|
@ -14,7 +21,25 @@ namespace Microsoft.CodeAnalysis.Remote.Razor.GoToDefinition;
|
|||
internal sealed class RazorComponentDefinitionService(
|
||||
IRazorComponentSearchEngine componentSearchEngine,
|
||||
IDocumentMappingService documentMappingService,
|
||||
IFilePathService filePathService,
|
||||
ILoggerFactory loggerFactory)
|
||||
: AbstractRazorComponentDefinitionService(componentSearchEngine, documentMappingService, loggerFactory.GetOrCreateLogger<RazorComponentDefinitionService>())
|
||||
{
|
||||
private readonly IFilePathService _filePathService = filePathService;
|
||||
|
||||
protected override async ValueTask<SyntaxTree> GetCSharpSyntaxTreeAsync(IDocumentSnapshot documentSnapshot, RazorCodeDocument codeDocument, CancellationToken cancellationToken)
|
||||
{
|
||||
Debug.Assert(documentSnapshot is RemoteDocumentSnapshot, "This method only works on document snapshots created in the OOP process");
|
||||
|
||||
var remoteSnapshot = (RemoteDocumentSnapshot)documentSnapshot;
|
||||
var document = await remoteSnapshot.GetGeneratedDocumentAsync(_filePathService).ConfigureAwait(false);
|
||||
|
||||
if (document.TryGetSyntaxTree(out var syntaxTree))
|
||||
{
|
||||
return syntaxTree;
|
||||
}
|
||||
|
||||
var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
|
||||
return tree.AssumeNotNull();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT license. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.LanguageServer.Completion;
|
||||
using Microsoft.AspNetCore.Razor.Test.Common;
|
||||
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.Razor.GoToDefinition;
|
||||
using Microsoft.CodeAnalysis.Testing;
|
||||
using Microsoft.VisualStudio.LanguageServer.Protocol;
|
||||
|
@ -392,7 +394,10 @@ public class RazorComponentDefinitionHelpersTest(ITestOutputHelper testOutput) :
|
|||
|
||||
var documentMappingService = new LspDocumentMappingService(FilePathService, new TestDocumentContextFactory(), LoggerFactory);
|
||||
|
||||
var range = await RazorComponentDefinitionHelpers.TryGetPropertyRangeAsync(codeDocument, propertyName, documentMappingService, Logger, DisposalToken);
|
||||
var csharpText = codeDocument.GetCSharpSourceText();
|
||||
var syntaxTree = CSharpSyntaxTree.ParseText(csharpText);
|
||||
|
||||
var range = await RazorComponentDefinitionHelpers.TryGetPropertyRangeAsync(codeDocument, syntaxTree, propertyName, documentMappingService, Logger, DisposalToken);
|
||||
Assert.NotNull(range);
|
||||
Assert.Equal(expectedRange, range);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче