public RazorLSPSpanMappingService( LSPDocumentMappingProvider lspDocumentMappingProvider, LSPDocumentSnapshot documentSnapshot, ITextSnapshot textSnapshot) { if (lspDocumentMappingProvider is null) { throw new ArgumentNullException(nameof(lspDocumentMappingProvider)); } if (textSnapshot == null) { throw new ArgumentNullException(nameof(textSnapshot)); } if (documentSnapshot is null) { throw new ArgumentNullException(nameof(documentSnapshot)); } _lspDocumentMappingProvider = lspDocumentMappingProvider; _textSnapshot = textSnapshot; _documentSnapshot = documentSnapshot; }
// Internal for testing internal static ImmutableArray <RazorMappedSpanResult> GetMappedSpanResults( LSPDocumentSnapshot documentSnapshot, SourceText sourceTextRazor, RazorMapToDocumentRangesResponse mappedResult) { var results = ImmutableArray.CreateBuilder <RazorMappedSpanResult>(); if (mappedResult is null) { return(results.ToImmutable()); } foreach (var mappedRange in mappedResult.Ranges) { if (Extensions.RangeExtensions.IsUndefined(mappedRange)) { // Couldn't remap the range correctly. Add default placeholder to indicate to C# that there were issues. results.Add(new RazorMappedSpanResult()); continue; } var mappedSpan = mappedRange.AsTextSpan(sourceTextRazor); var linePositionSpan = sourceTextRazor.Lines.GetLinePositionSpan(mappedSpan); var filePath = documentSnapshot.Uri.LocalPath; results.Add(new RazorMappedSpanResult(filePath, linePositionSpan, mappedSpan)); } return(results.ToImmutable()); }
// Internal for testing public override void Changed(LSPDocumentSnapshot old, LSPDocumentSnapshot @new, VirtualDocumentSnapshot virtualOld, VirtualDocumentSnapshot virtualNew, LSPDocumentChangeKind kind) { // We need the below check to address a race condition between when a request is sent to the C# server // for a generated document and when the C# server receives a document/didOpen notification. This race // condition may occur when the Razor server finishes initializing before C# receives and processes the // document open request. // This workaround adds the Razor client name to the generated document so the C# server will recognize // it, despite the document not being formally opened. Note this is meant to only be a temporary // workaround until a longer-term solution is implemented in the future. if (kind == LSPDocumentChangeKind.Added && _dynamicFileInfoProvider is DefaultRazorDynamicFileInfoProvider defaultProvider) { defaultProvider.PromoteBackgroundDocument(@new.Uri, CSharpDocumentPropertiesService.Instance); } if (kind != LSPDocumentChangeKind.VirtualDocumentChanged) { return; } if (virtualNew is CSharpVirtualDocumentSnapshot) { var csharpContainer = new CSharpVirtualDocumentContainer(_lspDocumentMappingProvider, @new, virtualNew.Snapshot); _dynamicFileInfoProvider.UpdateLSPFileInfo(@new.Uri, csharpContainer); } }
public override LSPDocumentSnapshot UpdateVirtualDocument <TVirtualDocument>(IReadOnlyList <TextChange> changes, long hostDocumentVersion) { if (!TryGetVirtualDocument <TVirtualDocument>(out var virtualDocument)) { throw new InvalidOperationException($"Cannot update virtual document of type {typeof(TVirtualDocument)} because LSP document {Uri} does not contain a virtual document of that type."); } virtualDocument.Update(changes, hostDocumentVersion); _currentSnapshot = UpdateSnapshot(); return(CurrentSnapshot); }
public LSPDocumentChangeEventArgs( LSPDocumentSnapshot old, LSPDocumentSnapshot @new, VirtualDocumentSnapshot virtualOld, VirtualDocumentSnapshot virtualNew, LSPDocumentChangeKind kind) { Old = old; New = @new; VirtualOld = virtualOld; VirtualNew = virtualNew; Kind = kind; }
public override bool TryGetDocument(Uri uri, out LSPDocumentSnapshot lspDocumentSnapshot) { Debug.Assert(_joinableTaskContext.IsOnMainThread); if (!_documents.TryGetValue(uri, out var lspDocument)) { // This should never happen in practice but return `null` so our tests can validate lspDocumentSnapshot = null; return(false); } lspDocumentSnapshot = lspDocument.CurrentSnapshot; return(true); }
public CSharpDocumentExcerptService( IRazorSpanMappingService mappingService, LSPDocumentSnapshot documentSnapshot) { if (mappingService is null) { throw new ArgumentNullException(nameof(mappingService)); } if (documentSnapshot is null) { throw new ArgumentNullException(nameof(documentSnapshot)); } _mappingService = mappingService; _documentSnapshot = documentSnapshot; }
public async override Task <bool> TrySynchronizeVirtualDocumentAsync(LSPDocumentSnapshot document, VirtualDocumentSnapshot virtualDocument, CancellationToken cancellationToken) { if (document is null) { throw new ArgumentNullException(nameof(document)); } if (virtualDocument is null) { throw new ArgumentNullException(nameof(virtualDocument)); } if (!document.VirtualDocuments.Contains(virtualDocument)) { throw new InvalidOperationException("Virtual document snapshot must belong to the provided LSP document snapshot."); } if (document.Version == virtualDocument.HostDocumentSyncVersion) { // Already synchronized return(true); } var synchronizingContext = _synchronizingContexts.AddOrUpdate( virtualDocument.Uri, (uri) => new DocumentSynchronizingContext(virtualDocument, document.Version, _synchronizationTimeout, cancellationToken), (uri, existingContext) => { if (virtualDocument == existingContext.VirtualDocument && document.Version == existingContext.ExpectedHostDocumentVersion) { // Already contain a synchronizing context that represents this request and it's in-process of being calculated. return(existingContext); } // Cancel old request existingContext.SetSynchronized(false); return(new DocumentSynchronizingContext(virtualDocument, document.Version, _synchronizationTimeout, cancellationToken)); }); var result = await _joinableTaskFactory.RunAsync(() => synchronizingContext.OnSynchronizedAsync); _synchronizingContexts.TryRemove(virtualDocument.Uri, out _); return(result); }
public CSharpVirtualDocumentContainer(LSPDocumentMappingProvider lspDocumentMappingProvider, LSPDocumentSnapshot documentSnapshot, ITextSnapshot textSnapshot) { if (lspDocumentMappingProvider is null) { throw new ArgumentNullException(nameof(lspDocumentMappingProvider)); } if (textSnapshot is null) { throw new ArgumentNullException(nameof(textSnapshot)); } if (documentSnapshot is null) { throw new ArgumentNullException(nameof(documentSnapshot)); } _lspDocumentMappingProvider = lspDocumentMappingProvider; _textSnapshot = textSnapshot; _documentSnapshot = documentSnapshot; }
public void AddDocument(Uri uri, LSPDocumentSnapshot documentSnapshot) { _documents.Add(uri, documentSnapshot); Changed?.Invoke(this, null); }
public override bool TryGetDocument(Uri uri, out LSPDocumentSnapshot lspDocumentSnapshot) { return(_documents.TryGetValue(uri, out lspDocumentSnapshot)); }
public abstract Task <bool> TrySynchronizeVirtualDocumentAsync(LSPDocumentSnapshot document, VirtualDocumentSnapshot virtualDocument, CancellationToken cancellationToken);
private static void NotifyLSPDocumentAdded(LSPDocumentSnapshot lspDocument, DefaultLSPDocumentSynchronizer synchronizer) { var args = new LSPDocumentChangeEventArgs(old: null, @new: lspDocument, LSPDocumentChangeKind.Added); synchronizer.DocumentManager_Changed(sender: null, args); }
public static bool TryGetDocument(this LSPDocumentManager documentManager, string filePath, out LSPDocumentSnapshot lspDocumentSnapshot) { if (documentManager is null) { throw new ArgumentNullException(nameof(documentManager)); } if (filePath is null) { throw new ArgumentNullException(nameof(filePath)); } if (filePath.StartsWith("/", StringComparison.Ordinal) && RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { filePath = filePath.Substring(1); } var uri = new Uri(filePath, UriKind.Absolute); return(documentManager.TryGetDocument(uri, out lspDocumentSnapshot)); }
public LSPDocumentChangeEventArgs(LSPDocumentSnapshot old, LSPDocumentSnapshot @new, LSPDocumentChangeKind kind) : this(old, @new, virtualOld : null, virtualNew : null, kind) { }
public abstract bool TryGetDocument(Uri uri, out LSPDocumentSnapshot lspDocumentSnapshot);