Inject file path service into the document snapshot

This commit is contained in:
David Wengier 2024-08-21 09:49:42 +10:00
Родитель 7d5b2060c6
Коммит 53fec86c28
11 изменённых файлов: 29 добавлений и 41 удалений

Просмотреть файл

@ -11,7 +11,6 @@ using Microsoft.CodeAnalysis.Razor.DocumentMapping;
using Microsoft.CodeAnalysis.Razor.Protocol;
using Microsoft.CodeAnalysis.Razor.Protocol.DocumentHighlight;
using Microsoft.CodeAnalysis.Razor.Remote;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Text;
using static Microsoft.VisualStudio.LanguageServer.Protocol.VsLspExtensions;
@ -29,7 +28,6 @@ internal sealed partial class RemoteDocumentHighlightService(in ServiceArgs args
}
private readonly IDocumentMappingService _documentMappingService = args.ExportProvider.GetExportedValue<IDocumentMappingService>();
private readonly IFilePathService _filePathService = args.ExportProvider.GetExportedValue<IFilePathService>();
public ValueTask<Response> GetHighlightsAsync(
RazorPinnedSolutionInfoWrapper solutionInfo,
@ -68,7 +66,7 @@ internal sealed partial class RemoteDocumentHighlightService(in ServiceArgs args
var csharpDocument = codeDocument.GetCSharpDocument();
if (_documentMappingService.TryMapToGeneratedDocumentPosition(csharpDocument, index, out var mappedPosition, out _))
{
var generatedDocument = await context.Snapshot.GetGeneratedDocumentAsync(_filePathService).ConfigureAwait(false);
var generatedDocument = await context.Snapshot.GetGeneratedDocumentAsync().ConfigureAwait(false);
var highlights = await DocumentHighlights.GetHighlightsAsync(generatedDocument, mappedPosition, cancellationToken).ConfigureAwait(false);

Просмотреть файл

@ -9,7 +9,6 @@ using Microsoft.CodeAnalysis.ExternalAccess.Razor;
using Microsoft.CodeAnalysis.Razor.FoldingRanges;
using Microsoft.CodeAnalysis.Razor.Protocol.Folding;
using Microsoft.CodeAnalysis.Razor.Remote;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using ExternalHandlers = Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers;
@ -25,7 +24,6 @@ internal sealed class RemoteFoldingRangeService(in ServiceArgs args) : RazorDocu
}
private readonly IFoldingRangeService _foldingRangeService = args.ExportProvider.GetExportedValue<IFoldingRangeService>();
private readonly IFilePathService _filePathService = args.ExportProvider.GetExportedValue<IFilePathService>();
public ValueTask<ImmutableArray<RemoteFoldingRange>> GetFoldingRangesAsync(
RazorPinnedSolutionInfoWrapper solutionInfo,
@ -43,7 +41,7 @@ internal sealed class RemoteFoldingRangeService(in ServiceArgs args) : RazorDocu
ImmutableArray<RemoteFoldingRange> htmlRanges,
CancellationToken cancellationToken)
{
var generatedDocument = await context.Snapshot.GetGeneratedDocumentAsync(_filePathService).ConfigureAwait(false);
var generatedDocument = await context.Snapshot.GetGeneratedDocumentAsync().ConfigureAwait(false);
var csharpRanges = await ExternalHandlers.FoldingRanges.GetFoldingRangesAsync(generatedDocument, cancellationToken).ConfigureAwait(false);

Просмотреть файл

@ -20,18 +20,15 @@ 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, 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);
var document = await remoteSnapshot.GetGeneratedDocumentAsync().ConfigureAwait(false);
if (document.TryGetSyntaxTree(out var syntaxTree))
{

Просмотреть файл

@ -10,7 +10,6 @@ using Microsoft.CodeAnalysis.Razor.DocumentMapping;
using Microsoft.CodeAnalysis.Razor.GoToDefinition;
using Microsoft.CodeAnalysis.Razor.Protocol;
using Microsoft.CodeAnalysis.Razor.Remote;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Remote.Razor.DocumentMapping;
using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Text;
@ -33,7 +32,6 @@ internal sealed class RemoteGoToDefinitionService(in ServiceArgs args) : RazorDo
}
private readonly IRazorComponentDefinitionService _componentDefinitionService = args.ExportProvider.GetExportedValue<IRazorComponentDefinitionService>();
private readonly IFilePathService _filePathService = args.ExportProvider.GetExportedValue<IFilePathService>();
protected override IDocumentPositionInfoStrategy DocumentPositionInfoStrategy => PreferAttributeNameDocumentPositionInfoStrategy.Instance;
@ -96,7 +94,7 @@ internal sealed class RemoteGoToDefinitionService(in ServiceArgs args) : RazorDo
}
// Finally, call into C#.
var generatedDocument = await context.Snapshot.GetGeneratedDocumentAsync(_filePathService).ConfigureAwait(false);
var generatedDocument = await context.Snapshot.GetGeneratedDocumentAsync().ConfigureAwait(false);
var locations = await ExternalHandlers.GoToDefinition
.GetDefinitionsAsync(
@ -121,7 +119,7 @@ internal sealed class RemoteGoToDefinitionService(in ServiceArgs args) : RazorDo
var (uri, range) = location;
var (mappedDocumentUri, mappedRange) = await DocumentMappingService
.MapToHostDocumentUriAndRangeAsync((RemoteDocumentSnapshot)context.Snapshot, uri, range.ToLinePositionSpan(), cancellationToken)
.MapToHostDocumentUriAndRangeAsync(context.Snapshot, uri, range.ToLinePositionSpan(), cancellationToken)
.ConfigureAwait(false);
var mappedLocation = RoslynLspFactory.CreateLocation(mappedDocumentUri, mappedRange);

Просмотреть файл

@ -26,8 +26,6 @@ internal sealed partial class RemoteInlayHintService(in ServiceArgs args) : Razo
=> new RemoteInlayHintService(in args);
}
private readonly IFilePathService _filePathService = args.ExportProvider.GetExportedValue<IFilePathService>();
public ValueTask<InlayHint[]?> GetInlayHintsAsync(JsonSerializableRazorPinnedSolutionInfoWrapper solutionInfo, JsonSerializableDocumentId razorDocumentId, InlayHintParams inlayHintParams, bool displayAllOverride, CancellationToken cancellationToken)
=> RunServiceAsync(
solutionInfo,
@ -52,7 +50,7 @@ internal sealed partial class RemoteInlayHintService(in ServiceArgs args) : Razo
return null;
}
var generatedDocument = await context.Snapshot.GetGeneratedDocumentAsync(_filePathService).ConfigureAwait(false);
var generatedDocument = await context.Snapshot.GetGeneratedDocumentAsync().ConfigureAwait(false);
var textDocument = inlayHintParams.TextDocument.WithUri(generatedDocument.CreateUri());
var range = projectedLinePositionSpan.ToRange();
@ -106,7 +104,7 @@ internal sealed partial class RemoteInlayHintService(in ServiceArgs args) : Razo
private async ValueTask<InlayHint> ResolveInlayHintAsync(RemoteDocumentContext context, InlayHint inlayHint, CancellationToken cancellationToken)
{
var generatedDocument = await context.Snapshot.GetGeneratedDocumentAsync(_filePathService).ConfigureAwait(false);
var generatedDocument = await context.Snapshot.GetGeneratedDocumentAsync().ConfigureAwait(false);
return await InlayHints.ResolveInlayHintAsync(generatedDocument, inlayHint, cancellationToken).ConfigureAwait(false);
}

Просмотреть файл

@ -4,26 +4,28 @@
using System;
using System.Composition;
using System.Runtime.CompilerServices;
using Microsoft.CodeAnalysis.Razor.Workspaces;
namespace Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem;
[Export(typeof(DocumentSnapshotFactory)), Shared]
[method: ImportingConstructor]
internal class DocumentSnapshotFactory(Lazy<ProjectSnapshotFactory> projectSnapshotFactory)
internal class DocumentSnapshotFactory(Lazy<ProjectSnapshotFactory> projectSnapshotFactory, IFilePathService filePathService)
{
private static readonly ConditionalWeakTable<TextDocument, RemoteDocumentSnapshot> _documentSnapshots = new();
private static readonly ConditionalWeakTable<TextDocument, RemoteDocumentSnapshot> s_documentSnapshots = new();
private readonly Lazy<ProjectSnapshotFactory> _projectSnapshotFactory = projectSnapshotFactory;
private readonly IFilePathService _filePathService = filePathService;
public RemoteDocumentSnapshot GetOrCreate(TextDocument textDocument)
{
lock (_documentSnapshots)
lock (s_documentSnapshots)
{
if (!_documentSnapshots.TryGetValue(textDocument, out var documentSnapshot))
if (!s_documentSnapshots.TryGetValue(textDocument, out var documentSnapshot))
{
var projectSnapshot = _projectSnapshotFactory.Value.GetOrCreate(textDocument.Project);
documentSnapshot = new RemoteDocumentSnapshot(textDocument, projectSnapshot);
_documentSnapshots.Add(textDocument, documentSnapshot);
documentSnapshot = new RemoteDocumentSnapshot(textDocument, projectSnapshot, _filePathService);
s_documentSnapshots.Add(textDocument, documentSnapshot);
}
return documentSnapshot;

Просмотреть файл

@ -11,19 +11,19 @@ namespace Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem;
[method: ImportingConstructor]
internal class ProjectSnapshotFactory(DocumentSnapshotFactory documentSnapshotFactory, ITelemetryReporter telemetryReporter)
{
private static readonly ConditionalWeakTable<Project, RemoteProjectSnapshot> _projectSnapshots = new();
private static readonly ConditionalWeakTable<Project, RemoteProjectSnapshot> s_projectSnapshots = new();
private readonly DocumentSnapshotFactory _documentSnapshotFactory = documentSnapshotFactory;
private readonly ITelemetryReporter _telemetryReporter = telemetryReporter;
public RemoteProjectSnapshot GetOrCreate(Project project)
{
lock (_projectSnapshots)
lock (s_projectSnapshots)
{
if (!_projectSnapshots.TryGetValue(project, out var projectSnapshot))
if (!s_projectSnapshots.TryGetValue(project, out var projectSnapshot))
{
projectSnapshot = new RemoteProjectSnapshot(project, _documentSnapshotFactory, _telemetryReporter);
_projectSnapshots.Add(project, projectSnapshot);
s_projectSnapshots.Add(project, projectSnapshot);
}
return projectSnapshot;

Просмотреть файл

@ -13,10 +13,11 @@ using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem;
internal class RemoteDocumentSnapshot(TextDocument textDocument, RemoteProjectSnapshot projectSnapshot) : IDocumentSnapshot
internal class RemoteDocumentSnapshot(TextDocument textDocument, RemoteProjectSnapshot projectSnapshot, IFilePathService filePathService) : IDocumentSnapshot
{
private readonly TextDocument _textDocument = textDocument;
private readonly RemoteProjectSnapshot _projectSnapshot = projectSnapshot;
private readonly IFilePathService _filePathService = filePathService;
// TODO: Delete this field when the source generator is hooked up
private Document? _generatedDocument;
@ -80,7 +81,7 @@ internal class RemoteDocumentSnapshot(TextDocument textDocument, RemoteProjectSn
var id = _textDocument.Id;
var newDocument = _textDocument.Project.Solution.WithAdditionalDocumentText(id, text).GetAdditionalDocument(id).AssumeNotNull();
return new RemoteDocumentSnapshot(newDocument, _projectSnapshot);
return new RemoteDocumentSnapshot(newDocument, _projectSnapshot, _filePathService);
}
public bool TryGetGeneratedOutput([NotNullWhen(true)] out RazorCodeDocument? result)
@ -89,23 +90,23 @@ internal class RemoteDocumentSnapshot(TextDocument textDocument, RemoteProjectSn
return result is not null;
}
public async Task<Document> GetGeneratedDocumentAsync(IFilePathService filePathService)
public async Task<Document> GetGeneratedDocumentAsync()
{
if (_generatedDocument is Document generatedDocument)
{
return generatedDocument;
}
generatedDocument = await HACK_GenerateDocumentAsync(filePathService).ConfigureAwait(false);
generatedDocument = await HACK_GenerateDocumentAsync().ConfigureAwait(false);
return InterlockedOperations.Initialize(ref _generatedDocument, generatedDocument);
}
private async Task<Document> HACK_GenerateDocumentAsync(IFilePathService filePathService)
private async Task<Document> HACK_GenerateDocumentAsync()
{
// TODO: A real implementation needs to get the SourceGeneratedDocument from the solution
var solution = TextDocument.Project.Solution;
var generatedFilePath = filePathService.GetRazorCSharpFilePath(Project.Key, FilePath.AssumeNotNull());
var generatedFilePath = _filePathService.GetRazorCSharpFilePath(Project.Key, FilePath.AssumeNotNull());
var projectId = TextDocument.Project.Id;
var generatedDocumentId = solution.GetDocumentIdsWithFilePath(generatedFilePath).First(d => d.ProjectId == projectId);
var generatedDocument = solution.GetRequiredDocument(generatedDocumentId);

Просмотреть файл

@ -25,7 +25,6 @@ internal sealed class RemoteRenameService(in ServiceArgs args) : RazorDocumentSe
}
private readonly IRenameService _renameService = args.ExportProvider.GetExportedValue<IRenameService>();
private readonly IFilePathService _filePathService = args.ExportProvider.GetExportedValue<IFilePathService>();
private readonly IEditMappingService _editMappingService = args.ExportProvider.GetExportedValue<IEditMappingService>();
public ValueTask<RemoteResponse<WorkspaceEdit?>> GetRenameEditAsync(
@ -53,7 +52,7 @@ internal sealed class RemoteRenameService(in ServiceArgs args) : RazorDocumentSe
return NoFurtherHandling;
}
var generatedDocument = await context.Snapshot.GetGeneratedDocumentAsync(_filePathService).ConfigureAwait(false);
var generatedDocument = await context.Snapshot.GetGeneratedDocumentAsync().ConfigureAwait(false);
var razorEdit = await _renameService.TryGetRazorRenameEditsAsync(context, positionInfo, newName, cancellationToken).ConfigureAwait(false);
if (razorEdit is not null)

Просмотреть файл

@ -31,7 +31,7 @@ internal class RemoteCSharpSemanticTokensProvider(IFilePathService filePathServi
// We have a razor document, lets find the generated C# document
Debug.Assert(documentContext is RemoteDocumentContext, "This method only works on document snapshots created in the OOP process");
var snapshot = (RemoteDocumentSnapshot)documentContext.Snapshot;
var generatedDocument = await snapshot.GetGeneratedDocumentAsync(_filePathService).ConfigureAwait(false);
var generatedDocument = await snapshot.GetGeneratedDocumentAsync().ConfigureAwait(false);
var data = await SemanticTokensRange.GetSemanticTokensAsync(
generatedDocument,

Просмотреть файл

@ -6,7 +6,6 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis.ExternalAccess.Razor;
using Microsoft.CodeAnalysis.Razor.Remote;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Text;
using Roslyn.LanguageServer.Protocol;
@ -23,8 +22,6 @@ internal sealed class RemoteSignatureHelpService(in ServiceArgs args) : RazorDoc
=> new RemoteSignatureHelpService(in args);
}
private readonly IFilePathService _filePathService = args.ExportProvider.GetExportedValue<IFilePathService>();
public ValueTask<LspSignatureHelp?> GetSignatureHelpAsync(JsonSerializableRazorPinnedSolutionInfoWrapper solutionInfo, JsonSerializableDocumentId documentId, Position position, CancellationToken cancellationToken)
=> RunServiceAsync(
solutionInfo,
@ -38,7 +35,7 @@ internal sealed class RemoteSignatureHelpService(in ServiceArgs args) : RazorDoc
var linePosition = new LinePosition(position.Line, position.Character);
var absoluteIndex = codeDocument.Source.Text.GetRequiredAbsoluteIndex(linePosition);
var generatedDocument = await context.Snapshot.GetGeneratedDocumentAsync(_filePathService).ConfigureAwait(false);
var generatedDocument = await context.Snapshot.GetGeneratedDocumentAsync().ConfigureAwait(false);
if (DocumentMappingService.TryMapToGeneratedDocumentPosition(codeDocument.GetCSharpDocument(), absoluteIndex, out var mappedPosition, out _))
{