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));
        }
示例#2
0
        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));
        }
示例#3
0
        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,
            });
        }
示例#7
0
        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);
        }
    }