private Task <(DocumentSnapshot Snapshot, int Version)?> TryGetDocumentInfoAsync(string absolutePath, CancellationToken cancellationToken) { return(_projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync <(DocumentSnapshot Snapshot, int Version)?>(() => { if (_documentResolver.TryResolveDocument(absolutePath, out var documentSnapshot)) { if (_documentVersionCache.TryGetDocumentVersion(documentSnapshot, out var version)) { return (documentSnapshot, version.Value); } } return null; }, cancellationToken)); }
protected Task <DocumentSnapshotAndVersion?> TryGetDocumentSnapshotAndVersionAsync(string uri, CancellationToken cancellationToken) { return(_projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(() => { if (_documentResolver.TryResolveDocument(uri, out var documentSnapshot)) { if (_documentVersionCache.TryGetDocumentVersion(documentSnapshot, out var version)) { return new DocumentSnapshotAndVersion(documentSnapshot, version.Value); } } return null; }, cancellationToken)); }
public async override Task <CodeAction?> ResolveAsync( CSharpCodeActionParams csharpParams, CodeAction codeAction, CancellationToken cancellationToken) { if (csharpParams is null) { throw new ArgumentNullException(nameof(csharpParams)); } if (codeAction is null) { throw new ArgumentNullException(nameof(codeAction)); } cancellationToken.ThrowIfCancellationRequested(); var resolvedCodeAction = await ResolveCodeActionWithServerAsync(csharpParams.RazorFileUri, codeAction, cancellationToken).ConfigureAwait(false); if (resolvedCodeAction?.Edit?.DocumentChanges is null) { // Unable to resolve code action with server, return original code action return(codeAction); } if (resolvedCodeAction.Edit.DocumentChanges.Count() != 1) { // We don't yet support multi-document code actions, return original code action return(codeAction); } var documentChanged = resolvedCodeAction.Edit.DocumentChanges.First(); if (!documentChanged.IsTextDocumentEdit) { // Only Text Document Edit changes are supported currently, return original code action return(codeAction); } var addUsingTextEdit = documentChanged.TextDocumentEdit?.Edits.FirstOrDefault(); if (addUsingTextEdit is null) { // No text edit available return(codeAction); } if (!AddUsingsCodeActionProviderFactory.TryExtractNamespace(addUsingTextEdit.NewText, out var @namespace)) { // Invalid text edit, missing namespace return(codeAction); } var documentSnapshot = await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(() => { _documentResolver.TryResolveDocument(csharpParams.RazorFileUri.GetAbsoluteOrUNCPath(), out var documentSnapshot); return(documentSnapshot); }, cancellationToken).ConfigureAwait(false); if (documentSnapshot is null) { return(codeAction); } var text = await documentSnapshot.GetTextAsync().ConfigureAwait(false); if (text is null) { return(null); } var codeDocument = await documentSnapshot.GetGeneratedOutputAsync().ConfigureAwait(false); if (codeDocument.IsUnsupported()) { return(null); } var documentVersion = await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(() => { _documentVersionCache.TryGetDocumentVersion(documentSnapshot, out var version); return(version); }, cancellationToken).ConfigureAwait(false); var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier() { Uri = csharpParams.RazorFileUri, Version = documentVersion.Value }; var edit = AddUsingsCodeActionResolver.CreateAddUsingWorkspaceEdit(@namespace, codeDocument, codeDocumentIdentifier); resolvedCodeAction = resolvedCodeAction with { Edit = edit }; return(resolvedCodeAction); } }
public async override Task <CodeAction> ResolveAsync( CSharpCodeActionParams csharpParams, CodeAction codeAction, CancellationToken cancellationToken) { if (csharpParams is null) { throw new ArgumentNullException(nameof(csharpParams)); } if (codeAction is null) { throw new ArgumentNullException(nameof(codeAction)); } cancellationToken.ThrowIfCancellationRequested(); var resolvedCodeAction = await ResolveCodeActionWithServerAsync(codeAction, cancellationToken).ConfigureAwait(false); if (resolvedCodeAction.Edit?.DocumentChanges is null) { // Unable to resolve code action with server, return original code action return(codeAction); } if (resolvedCodeAction.Edit.DocumentChanges.Count() != 1) { // We don't yet support multi-document code actions, return original code action Debug.Fail($"Encountered an unsupported multi-document code action edit with ${codeAction.Title}."); return(codeAction); } var documentChanged = resolvedCodeAction.Edit.DocumentChanges.First(); if (!documentChanged.IsTextDocumentEdit) { // Only Text Document Edit changes are supported currently, return original code action return(codeAction); } var textEdit = documentChanged.TextDocumentEdit.Edits.FirstOrDefault(); if (textEdit is null) { // No text edit available return(codeAction); } var(documentSnapshot, documentVersion) = await Task.Factory.StartNew(() => { _documentResolver.TryResolveDocument(csharpParams.RazorFileUri.ToUri().GetAbsoluteOrUNCPath(), out var documentSnapshot); _documentVersionCache.TryGetDocumentVersion(documentSnapshot, out var version); return(documentSnapshot, version); }, cancellationToken, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler).ConfigureAwait(false); if (documentSnapshot is null) { return(codeAction); } var codeDocument = await documentSnapshot.GetGeneratedOutputAsync().ConfigureAwait(false); if (codeDocument.IsUnsupported()) { return(codeAction); } if (!_documentMappingService.TryMapFromProjectedDocumentRange(codeDocument, textEdit.Range, MappingBehavior.Inclusive, out var originalRange)) { // Text edit failed to map return(codeAction); } textEdit.Range = originalRange; var codeDocumentIdentifier = new VersionedTextDocumentIdentifier() { Uri = csharpParams.RazorFileUri, Version = documentVersion }; resolvedCodeAction.Edit = new WorkspaceEdit() { DocumentChanges = new[] { new WorkspaceEditDocumentChange( new TextDocumentEdit() { TextDocument = codeDocumentIdentifier, Edits = new[] { textEdit }, } ) } }; return(resolvedCodeAction); }
public async override Task <CodeAction> ResolveAsync( CSharpCodeActionParams csharpParams, CodeAction codeAction, CancellationToken cancellationToken) { if (csharpParams is null) { throw new ArgumentNullException(nameof(csharpParams)); } if (codeAction is null) { throw new ArgumentNullException(nameof(codeAction)); } var resolvedCodeAction = await ResolveCodeActionWithServerAsync(csharpParams.RazorFileUri, codeAction, cancellationToken).ConfigureAwait(false); if (resolvedCodeAction.Edit?.DocumentChanges is null) { // Unable to resolve code action with server, return original code action return(codeAction); } if (resolvedCodeAction.Edit.DocumentChanges.Count() != 1) { // We don't yet support multi-document code actions, return original code action return(codeAction); } cancellationToken.ThrowIfCancellationRequested(); var documentSnapshot = await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(() => { _documentResolver.TryResolveDocument(csharpParams.RazorFileUri.GetAbsoluteOrUNCPath(), out var documentSnapshot); return(documentSnapshot); }, cancellationToken).ConfigureAwait(false); if (documentSnapshot is null) { return(codeAction); } var documentChanged = resolvedCodeAction.Edit.DocumentChanges.First(); if (!documentChanged.IsTextDocumentEdit) { // Only Text Document Edit changes are supported currently, return original code action return(codeAction); } cancellationToken.ThrowIfCancellationRequested(); var csharpTextEdits = documentChanged.TextDocumentEdit.Edits.ToArray(); // Remaps the text edits from the generated C# to the razor file, // as well as applying appropriate formatting. var formattedEdits = await _razorFormattingService.ApplyFormattedEditsAsync( csharpParams.RazorFileUri, documentSnapshot, RazorLanguageKind.CSharp, csharpTextEdits, s_defaultFormattingOptions, cancellationToken, bypassValidationPasses : true); cancellationToken.ThrowIfCancellationRequested(); var documentVersion = await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(() => { _documentVersionCache.TryGetDocumentVersion(documentSnapshot, out var version); return(version); }, cancellationToken).ConfigureAwait(false); var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier() { Uri = csharpParams.RazorFileUri, Version = documentVersion.Value }; resolvedCodeAction = resolvedCodeAction with { Edit = new WorkspaceEdit() { DocumentChanges = new[] { new WorkspaceEditDocumentChange( new TextDocumentEdit() { TextDocument = codeDocumentIdentifier, Edits = formattedEdits, }) } } }; return(resolvedCodeAction); } }
public async Task <RazorDiagnosticsResponse> Handle(RazorDiagnosticsParams request, CancellationToken cancellationToken) { if (request is null) { throw new ArgumentNullException(nameof(request)); } _logger.LogInformation($"Received {request.Kind:G} diagnostic request for {request.RazorDocumentUri} with {request.Diagnostics.Length} diagnostics."); cancellationToken.ThrowIfCancellationRequested(); int?documentVersion = null; DocumentSnapshot documentSnapshot = null; await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(() => { _documentResolver.TryResolveDocument(request.RazorDocumentUri.GetAbsoluteOrUNCPath(), out documentSnapshot); Debug.Assert(documentSnapshot != null, "Failed to get the document snapshot, could not map to document ranges."); if (documentSnapshot is null || !_documentVersionCache.TryGetDocumentVersion(documentSnapshot, out documentVersion)) { documentVersion = null; } }, cancellationToken).ConfigureAwait(false); if (documentSnapshot is null) { _logger.LogInformation($"Failed to find document {request.RazorDocumentUri}."); return(new RazorDiagnosticsResponse() { Diagnostics = null, HostDocumentVersion = null }); } var codeDocument = await documentSnapshot.GetGeneratedOutputAsync().ConfigureAwait(false); if (codeDocument?.IsUnsupported() != false) { _logger.LogInformation("Unsupported code document."); return(new RazorDiagnosticsResponse() { Diagnostics = Array.Empty <OmniSharpVSDiagnostic>(), HostDocumentVersion = documentVersion }); } var sourceText = await documentSnapshot.GetTextAsync(); var unmappedDiagnostics = request.Diagnostics; var filteredDiagnostics = request.Kind == RazorLanguageKind.CSharp ? FilterCSharpDiagnostics(unmappedDiagnostics, codeDocument, sourceText) : FilterHTMLDiagnostics(unmappedDiagnostics, codeDocument, sourceText); if (!filteredDiagnostics.Any()) { _logger.LogInformation("No diagnostics remaining after filtering."); return(new RazorDiagnosticsResponse() { Diagnostics = Array.Empty <OmniSharpVSDiagnostic>(), HostDocumentVersion = documentVersion }); } _logger.LogInformation($"{filteredDiagnostics.Length}/{unmappedDiagnostics.Length} diagnostics remain after filtering."); var mappedDiagnostics = MapDiagnostics( request.Kind, filteredDiagnostics, codeDocument, sourceText); _logger.LogInformation($"Returning {mappedDiagnostics.Length} mapped diagnostics."); return(new RazorDiagnosticsResponse() { Diagnostics = mappedDiagnostics, HostDocumentVersion = documentVersion, }); }
public async override Task <CodeAction?> ResolveAsync( CSharpCodeActionParams csharpParams, CodeAction codeAction, CancellationToken cancellationToken) { if (csharpParams is null) { throw new ArgumentNullException(nameof(csharpParams)); } if (codeAction is null) { throw new ArgumentNullException(nameof(codeAction)); } cancellationToken.ThrowIfCancellationRequested(); if (!AddUsingsCodeActionProviderHelper.TryExtractNamespace(codeAction.Title, out var @namespace)) { // Invalid text edit, missing namespace return(codeAction); } var documentSnapshot = await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(() => { _documentResolver.TryResolveDocument(csharpParams.RazorFileUri.GetAbsoluteOrUNCPath(), out var documentSnapshot); return(documentSnapshot); }, cancellationToken).ConfigureAwait(false); if (documentSnapshot is null) { return(codeAction); } var text = await documentSnapshot.GetTextAsync().ConfigureAwait(false); if (text is null) { return(null); } var codeDocument = await documentSnapshot.GetGeneratedOutputAsync().ConfigureAwait(false); if (codeDocument.IsUnsupported()) { return(null); } var documentVersion = await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(() => { _documentVersionCache.TryGetDocumentVersion(documentSnapshot, out var version); return(version); }, cancellationToken).ConfigureAwait(false); var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier() { Uri = csharpParams.RazorFileUri, Version = documentVersion.Value }; var edit = AddUsingsCodeActionResolver.CreateAddUsingWorkspaceEdit(@namespace, codeDocument, codeDocumentIdentifier); codeAction = codeAction with { Edit = edit }; return(codeAction); } }