Esempio n. 1
0
            static async Task AddTextDocumentEdits <T>(
                ArrayBuilder <TextDocumentEdit> textDocumentEdits,
                ApplyChangesOperation applyChangesOperation,
                Solution solution,
                IEnumerable <DocumentId> changedDocuments,
                Func <DocumentId, T?> getNewDocumentFunc,
                Func <DocumentId, T?> getOldDocumentFunc,
                CancellationToken cancellationToken)
                where T : TextDocument
            {
                foreach (var docId in changedDocuments)
                {
                    var newDoc = getNewDocumentFunc(docId);
                    var oldDoc = getOldDocumentFunc(docId);

                    Contract.ThrowIfNull(oldDoc);
                    Contract.ThrowIfNull(newDoc);

                    var oldText = await oldDoc.GetTextAsync(cancellationToken).ConfigureAwait(false);

                    var newText = await newDoc.GetTextAsync(cancellationToken).ConfigureAwait(false);

                    var textChanges = newText.GetTextChanges(oldText);

                    var edits = textChanges.Select(tc => ProtocolConversions.TextChangeToTextEdit(tc, oldText)).ToArray();
                    var documentIdentifier = new VersionedTextDocumentIdentifier {
                        Uri = newDoc.GetURI()
                    };
                    textDocumentEdits.Add(new TextDocumentEdit {
                        TextDocument = documentIdentifier, Edits = edits.ToArray()
                    });
                }
            }
Esempio n. 2
0
        protected async Task <LSP.TextEdit[]?> GetTextEditsAsync(
            RequestContext context,
            LSP.FormattingOptions options,
            CancellationToken cancellationToken,
            LSP.Range?range = null)
        {
            var document = context.Document;

            if (document == null)
            {
                return(null);
            }

            var edits = new ArrayBuilder <LSP.TextEdit>();

            var formattingService = document.Project.LanguageServices.GetRequiredService <IFormattingInteractionService>();
            var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            TextSpan?textSpan = null;

            if (range != null)
            {
                textSpan = ProtocolConversions.RangeToTextSpan(range, text);
            }

            // We should use the options passed in by LSP instead of the document's options.
            var documentOptions = await ProtocolConversions.FormattingOptionsToDocumentOptionsAsync(
                options, document, cancellationToken).ConfigureAwait(false);

            var textChanges = await GetFormattingChangesAsync(formattingService, document, textSpan, documentOptions, cancellationToken).ConfigureAwait(false);

            edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text)));

            return(edits.ToArrayAndFree());
        }
Esempio n. 3
0
        public override async Task <TextEdit[]> HandleRequestAsync(DocumentOnTypeFormattingParams request, RequestContext context, CancellationToken cancellationToken)
        {
            var edits = new ArrayBuilder <TextEdit>();

            if (string.IsNullOrEmpty(request.Character))
            {
                return(edits.ToArrayAndFree());
            }

            var document          = context.Document;
            var formattingService = document?.Project.LanguageServices.GetService <IXamlFormattingService>();

            if (document != null && formattingService != null)
            {
                var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);

                var options = new XamlFormattingOptions {
                    InsertSpaces = request.Options.InsertSpaces, TabSize = request.Options.TabSize, OtherOptions = request.Options.OtherOptions
                };
                var textChanges = await formattingService.GetFormattingChangesAsync(document, options, request.Character[0], position, cancellationToken).ConfigureAwait(false);

                if (textChanges != null)
                {
                    var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

                    edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text)));
                }
            }

            return(edits.ToArrayAndFree());
        }
        public async Task <TextEdit[]> HandleRequestAsync(DocumentOnTypeFormattingParams request, RequestContext context, CancellationToken cancellationToken)
        {
            var edits    = new ArrayBuilder <TextEdit>();
            var document = context.Document;

            if (document != null)
            {
                var formattingService = document.Project.LanguageServices.GetRequiredService <IEditorFormattingService>();
                var position          = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);

                if (string.IsNullOrEmpty(request.Character))
                {
                    return(edits.ToArrayAndFree());
                }

                IList <TextChange>?textChanges;
                if (SyntaxFacts.IsNewLine(request.Character[0]))
                {
                    textChanges = await GetFormattingChangesOnReturnAsync(formattingService, document, position, cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    textChanges = await GetFormattingChangesAsync(formattingService, document, request.Character[0], position, cancellationToken).ConfigureAwait(false);
                }

                var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

                if (textChanges != null)
                {
                    edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text)));
                }
            }

            return(edits.ToArrayAndFree());
        }
Esempio n. 5
0
        protected async Task <LSP.TextEdit[]> GetTextEditsAsync(LSP.TextDocumentIdentifier documentIdentifier, LSP.FormattingOptions formattingOptions, RequestContext context, CancellationToken cancellationToken, LSP.Range?range = null)
        {
            using var _ = ArrayBuilder <LSP.TextEdit> .GetInstance(out var edits);

            var document          = context.Document;
            var formattingService = document?.Project.LanguageServices.GetService <IXamlFormattingService>();

            if (document != null && formattingService != null)
            {
                var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

                TextSpan?textSpan = null;
                if (range != null)
                {
                    textSpan = ProtocolConversions.RangeToTextSpan(range, text);
                }

                var options = new XamlFormattingOptions {
                    InsertSpaces = formattingOptions.InsertSpaces, TabSize = formattingOptions.TabSize, OtherOptions = formattingOptions.OtherOptions
                };
                var textChanges = await formattingService.GetFormattingChangesAsync(document, options, textSpan, cancellationToken).ConfigureAwait(false);

                edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text)));
            }

            return(edits.ToArray());
        }
        protected static async Task <LSP.TextEdit[]?> GetTextEditsAsync(
            RequestContext context,
            LSP.FormattingOptions options,
            IGlobalOptionService globalOptions,
            CancellationToken cancellationToken,
            LSP.Range?range = null)
        {
            var document = context.Document;

            if (document == null)
            {
                return(null);
            }

            var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var rangeSpan      = (range != null) ? ProtocolConversions.RangeToTextSpan(range, text) : new TextSpan(0, root.FullSpan.Length);
            var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, rangeSpan);

            // We should use the options passed in by LSP instead of the document's options.
            var formattingOptions = await ProtocolConversions.GetFormattingOptionsAsync(options, document, globalOptions, cancellationToken).ConfigureAwait(false);

            var services    = document.Project.Solution.Services;
            var textChanges = Formatter.GetFormattedTextChanges(root, SpecializedCollections.SingletonEnumerable(formattingSpan), services, formattingOptions, rules: null, cancellationToken);

            var edits = new ArrayBuilder <LSP.TextEdit>();

            edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text)));
            return(edits.ToArrayAndFree());
        }
Esempio n. 7
0
        public async Task <WorkspaceEdit> HandleRequestAsync(Solution solution, RenameParams request, ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
        {
            WorkspaceEdit workspaceEdit = null;
            var           document      = solution.GetDocumentFromURI(request.TextDocument.Uri);

            if (document != null)
            {
                var renameService = document.Project.LanguageServices.GetService <IEditorInlineRenameService>();
                var position      = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);

                var renameInfo = await renameService.GetRenameInfoAsync(document, position, cancellationToken).ConfigureAwait(false);

                if (!renameInfo.CanRename)
                {
                    return(workspaceEdit);
                }

                var renameLocationSet = await renameInfo.FindRenameLocationsAsync(solution.Workspace.Options, cancellationToken).ConfigureAwait(false);

                var renameReplacementInfo = await renameLocationSet.GetReplacementsAsync(request.NewName, solution.Workspace.Options, cancellationToken).ConfigureAwait(false);

                var newSolution      = renameReplacementInfo.NewSolution;
                var solutionChanges  = newSolution.GetChanges(solution);
                var changedDocuments = solutionChanges
                                       .GetProjectChanges()
                                       .SelectMany(p => p.GetChangedDocuments(onlyGetDocumentsWithTextChanges: true));

                var documentEdits = new ArrayBuilder <TextDocumentEdit>();
                foreach (var docId in changedDocuments)
                {
                    var oldDoc = solution.GetDocument(docId);
                    var newDoc = newSolution.GetDocument(docId);

                    var textChanges = await newDoc.GetTextChangesAsync(oldDoc, cancellationToken).ConfigureAwait(false);

                    var oldText = await oldDoc.GetTextAsync(cancellationToken).ConfigureAwait(false);

                    var textDocumentEdit = new TextDocumentEdit
                    {
                        TextDocument = new VersionedTextDocumentIdentifier {
                            Uri = newDoc.GetURI()
                        },
                        Edits = textChanges.Select(tc => ProtocolConversions.TextChangeToTextEdit(tc, oldText)).ToArray()
                    };
                    documentEdits.Add(textDocumentEdit);
                }

                workspaceEdit = new WorkspaceEdit {
                    DocumentChanges = documentEdits.ToArrayAndFree()
                };
            }

            return(workspaceEdit);
        }
Esempio n. 8
0
        public override async Task <TextEdit[]?> HandleRequestAsync(
            DocumentOnTypeFormattingParams request,
            RequestContext context,
            CancellationToken cancellationToken)
        {
            var document = context.Document;

            if (document == null)
            {
                return(null);
            }

            var edits = new ArrayBuilder <TextEdit>();

            var formattingService = document.Project.LanguageServices.GetRequiredService <IFormattingInteractionService>();
            var position          = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);

            if (string.IsNullOrEmpty(request.Character))
            {
                return(edits.ToArrayAndFree());
            }

            // We should use the options passed in by LSP instead of the document's options.
            var documentOptions = await ProtocolConversions.FormattingOptionsToDocumentOptionsAsync(
                request.Options, document, cancellationToken).ConfigureAwait(false);

            IList <TextChange>?textChanges;

            if (SyntaxFacts.IsNewLine(request.Character[0]))
            {
                textChanges = await GetFormattingChangesOnReturnAsync(
                    formattingService, document, position, documentOptions, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                textChanges = await GetFormattingChangesAsync(
                    formattingService, document, request.Character[0], position, documentOptions, cancellationToken).ConfigureAwait(false);
            }

            var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            if (textChanges != null)
            {
                edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text)));
            }

            return(edits.ToArrayAndFree());
        }
        public async Task <TextEdit[]?> HandleRequestAsync(
            DocumentOnTypeFormattingParams request,
            RequestContext context,
            CancellationToken cancellationToken)
        {
            var document = context.Document;

            if (document == null)
            {
                return(null);
            }

            var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);

            if (string.IsNullOrEmpty(request.Character) || SyntaxFacts.IsNewLine(request.Character[0]))
            {
                return(Array.Empty <TextEdit>());
            }

            var formattingService = document.Project.LanguageServices.GetRequiredService <ISyntaxFormattingService>();
            var documentSyntax    = await ParsedDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false);

            if (!formattingService.ShouldFormatOnTypedCharacter(documentSyntax, request.Character[0], position, cancellationToken))
            {
                return(Array.Empty <TextEdit>());
            }

            // We should use the options passed in by LSP instead of the document's options.
            var formattingOptions = await ProtocolConversions.GetFormattingOptionsAsync(request.Options, document, _globalOptions, cancellationToken).ConfigureAwait(false);

            var indentationOptions = new IndentationOptions(formattingOptions)
            {
                AutoFormattingOptions = _globalOptions.GetAutoFormattingOptions(document.Project.Language)
            };

            var textChanges = formattingService.GetFormattingChangesOnTypedCharacter(documentSyntax, position, indentationOptions, cancellationToken);

            if (textChanges.IsEmpty)
            {
                return(Array.Empty <TextEdit>());
            }

            var edits = new ArrayBuilder <TextEdit>();

            edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, documentSyntax.Text)));
            return(edits.ToArrayAndFree());
        }
        protected async Task <LSP.TextEdit[]> GetTextEditsAsync(RequestContext context, CancellationToken cancellationToken, LSP.Range?range = null)
        {
            var edits    = new ArrayBuilder <LSP.TextEdit>();
            var document = context.Document;

            if (document != null)
            {
                var formattingService = document.Project.LanguageServices.GetRequiredService <IEditorFormattingService>();
                var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

                TextSpan?textSpan = null;
                if (range != null)
                {
                    textSpan = ProtocolConversions.RangeToTextSpan(range, text);
                }

                var textChanges = await GetFormattingChangesAsync(formattingService, document, textSpan, cancellationToken).ConfigureAwait(false);

                edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text)));
            }

            return(edits.ToArrayAndFree());
        }
Esempio n. 11
0
        protected async Task <LSP.TextEdit[]> GetTextEdits(Solution solution, Uri documentUri, bool keepThreadContext, CancellationToken cancellationToken, LSP.Range range = null)
        {
            var edits    = new ArrayBuilder <LSP.TextEdit>();
            var document = solution.GetDocumentFromURI(documentUri);

            if (document != null)
            {
                var formattingService = document.Project.LanguageServices.GetService <IEditorFormattingService>();
                var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(keepThreadContext);

                TextSpan?textSpan = null;
                if (range != null)
                {
                    textSpan = ProtocolConversions.RangeToTextSpan(range, text);
                }

                var textChanges = await formattingService.GetFormattingChangesAsync(document, textSpan, cancellationToken).ConfigureAwait(keepThreadContext);

                edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text)));
            }

            return(edits.ToArrayAndFree());
        }
Esempio n. 12
0
        public async Task <TextEdit[]> HandleRequestAsync(Solution solution, DocumentOnTypeFormattingParams request, ClientCapabilities clientCapabilities,
                                                          CancellationToken cancellationToken, bool keepThreadContext = false)
        {
            var edits    = new ArrayBuilder <TextEdit>();
            var document = solution.GetDocumentFromURI(request.TextDocument.Uri);

            if (document != null)
            {
                var formattingService = document.Project.LanguageServices.GetService <IEditorFormattingService>();
                var position          = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(keepThreadContext);

                if (string.IsNullOrEmpty(request.Character))
                {
                    return(edits.ToArrayAndFree());
                }

                IList <TextChange> textChanges;
                if (SyntaxFacts.IsNewLine(request.Character[0]))
                {
                    textChanges = await formattingService.GetFormattingChangesOnReturnAsync(document, position, cancellationToken).ConfigureAwait(keepThreadContext);
                }
                else
                {
                    textChanges = await formattingService.GetFormattingChangesAsync(document, request.Character[0], position, cancellationToken).ConfigureAwait(keepThreadContext);
                }

                var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(keepThreadContext);

                if (textChanges != null)
                {
                    edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text)));
                }
            }

            return(edits.ToArrayAndFree());
        }
Esempio n. 13
0
        public override async Task <WorkspaceEdit?> HandleRequestAsync(RenameParams request, RequestContext context, CancellationToken cancellationToken)
        {
            WorkspaceEdit?workspaceEdit = null;
            var           document      = SolutionProvider.GetDocument(request.TextDocument, context.ClientName);

            if (document != null)
            {
                var oldSolution   = document.Project.Solution;
                var renameService = document.Project.LanguageServices.GetRequiredService <IEditorInlineRenameService>();
                var position      = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);

                var renameInfo = await renameService.GetRenameInfoAsync(document, position, cancellationToken).ConfigureAwait(false);

                if (!renameInfo.CanRename)
                {
                    return(workspaceEdit);
                }

                var renameLocationSet = await renameInfo.FindRenameLocationsAsync(oldSolution.Workspace.Options, cancellationToken).ConfigureAwait(false);

                var renameReplacementInfo = await renameLocationSet.GetReplacementsAsync(request.NewName, oldSolution.Workspace.Options, cancellationToken).ConfigureAwait(false);

                var renamedSolution = renameReplacementInfo.NewSolution;
                var solutionChanges = renamedSolution.GetChanges(oldSolution);

                // Linked files can correspond to multiple roslyn documents each with changes.  Merge the changes in the linked files so that all linked documents have the same text.
                // Then we can just take the text changes from the first document to avoid returning duplicate edits.
                renamedSolution = await renamedSolution.WithMergedLinkedFileChangesAsync(oldSolution, solutionChanges, cancellationToken : cancellationToken).ConfigureAwait(false);

                solutionChanges = renamedSolution.GetChanges(oldSolution);
                var changedDocuments = solutionChanges
                                       .GetProjectChanges()
                                       .SelectMany(p => p.GetChangedDocuments(onlyGetDocumentsWithTextChanges: true))
                                       .GroupBy(docId => renamedSolution.GetRequiredDocument(docId).FilePath, StringComparer.OrdinalIgnoreCase).Select(group => group.First());

                using var _ = ArrayBuilder <TextDocumentEdit> .GetInstance(out var documentEdits);

                foreach (var docId in changedDocuments)
                {
                    var oldDoc = oldSolution.GetRequiredDocument(docId);
                    var newDoc = renamedSolution.GetRequiredDocument(docId);

                    var textChanges = await newDoc.GetTextChangesAsync(oldDoc, cancellationToken).ConfigureAwait(false);

                    var oldText = await oldDoc.GetTextAsync(cancellationToken).ConfigureAwait(false);

                    var textDocumentEdit = new TextDocumentEdit
                    {
                        TextDocument = new VersionedTextDocumentIdentifier {
                            Uri = newDoc.GetURI()
                        },
                        Edits = textChanges.Select(tc => ProtocolConversions.TextChangeToTextEdit(tc, oldText)).ToArray()
                    };
                    documentEdits.Add(textDocumentEdit);
                }

                workspaceEdit = new WorkspaceEdit {
                    DocumentChanges = documentEdits.ToArray()
                };
            }

            return(workspaceEdit);
        }
Esempio n. 14
0
        public async Task <WorkspaceEdit> HandleAsync(RenameParams request, RequestContext <Solution> requestContext, CancellationToken cancellationToken)
        {
            var           solution      = requestContext.Context;
            WorkspaceEdit workspaceEdit = null;
            var           document      = solution.GetDocumentFromURI(request.TextDocument.Uri);

            if (document != null)
            {
                var renameService = document.Project.LanguageServices.GetService <IEditorInlineRenameService>();
                var position      = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);

                // We need to be on the UI thread to call GetRenameInfo which computes the rename locations.
                // This is because Roslyn reads the readonly regions of the buffer to compute the locations in the document.
                // This is typically quick. It's marked configureawait(false) so that the bulk of the rename operation can happen
                // in background threads.
                await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

                var renameInfo = await renameService.GetRenameInfoAsync(document, position, cancellationToken).ConfigureAwait(false);

                if (!renameInfo.CanRename)
                {
                    return(workspaceEdit);
                }

                var renameLocationSet = await renameInfo.FindRenameLocationsAsync(solution.Workspace.Options, cancellationToken).ConfigureAwait(false);

                var renameReplacementInfo = await renameLocationSet.GetReplacementsAsync(request.NewName, solution.Workspace.Options, cancellationToken).ConfigureAwait(false);

                var newSolution      = renameReplacementInfo.NewSolution;
                var solutionChanges  = newSolution.GetChanges(solution);
                var changedDocuments = solutionChanges
                                       .GetProjectChanges()
                                       .SelectMany(p => p.GetChangedDocuments(onlyGetDocumentsWithTextChanges: true));

                var documentEdits = new ArrayBuilder <TextDocumentEdit>();
                foreach (var docId in changedDocuments)
                {
                    var oldDoc = solution.GetDocument(docId);
                    var newDoc = newSolution.GetDocument(docId);

                    var textChanges = await newDoc.GetTextChangesAsync(oldDoc, cancellationToken).ConfigureAwait(false);

                    var oldText = await oldDoc.GetTextAsync(cancellationToken).ConfigureAwait(false);

                    var textDocumentEdit = new TextDocumentEdit
                    {
                        TextDocument = new VersionedTextDocumentIdentifier {
                            Uri = newDoc.GetURI()
                        },
                        Edits = textChanges.Select(tc => ProtocolConversions.TextChangeToTextEdit(tc, oldText)).ToArray()
                    };
                    documentEdits.Add(textDocumentEdit);
                }

                workspaceEdit = new WorkspaceEdit {
                    DocumentChanges = documentEdits.ToArrayAndFree()
                };
            }

            return(workspaceEdit);
        }