Example #1
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
                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 documentInfo = await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync <(DocumentSnapshot, int)?>(() =>
            {
                if (_documentResolver.TryResolveDocument(csharpParams.RazorFileUri.ToUri().GetAbsoluteOrUNCPath(), out var documentSnapshot))
                {
                    if (_documentVersionCache.TryGetDocumentVersion(documentSnapshot, out var version))
                    {
                        return(documentSnapshot, version.Value);
                    }
                }

                return(null);
            }, cancellationToken).ConfigureAwait(false);

            if (documentInfo is null)
            {
                return(codeAction);
            }

            var(documentSnapshot, documentVersion) = documentInfo.Value;

            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 = textEdit with {
                Range = originalRange
            };

            var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier()
            {
                Uri     = csharpParams.RazorFileUri,
                Version = documentVersion
            };

            resolvedCodeAction = resolvedCodeAction with
            {
                Edit = new WorkspaceEdit()
                {
                    DocumentChanges = new[] {
                        new WorkspaceEditDocumentChange(
                            new TextDocumentEdit()
                        {
                            TextDocument = codeDocumentIdentifier,
                            Edits        = new[] { textEdit },
                        })
                    }
                },
            };

            return(resolvedCodeAction);
        }
    }