public Task <WorkspaceEdit> RenameAsync(RenameParams renameParams, CancellationToken cancellationToken) { if (renameParams is null) { throw new ArgumentNullException(nameof(renameParams)); } return(ExecuteRequestAsync <RenameParams, WorkspaceEdit>(Methods.TextDocumentRenameName, renameParams, _clientCapabilities, cancellationToken)); }
/// <summary> /// Changes public identifier of a file. /// </summary> /// <param name="parameters">Operation parameters.</param> /// <returns></returns> public RenameResult Rename(RenameParams parameters) { string uri = m_api.ApiUrlImgUpV.Action("rename").BuildUrl(); using (HttpWebResponse response = m_api.Call(HttpMethod.POST, uri, parameters.ToParamsDictionary(), null)) { return(RenameResult.Parse(response)); } }
public void TestRenameParamsCheck() { var p = new RenameParams("", ""); Assert.Throws <ArgumentException>(p.Check, "Should require FromPublicId"); p.FromPublicId = "FromPublicId"; Assert.Throws <ArgumentException>(p.Check, "Should require ToPublicId"); }
public Task <WorkspaceEdit> Handle(RenameParams request, CancellationToken cancellationToken) { return(Task.Run(() => { var link = GetLink(_languageServer, request.TextDocument.Uri.ToUri(), request.Position); if (link == null) { return new WorkspaceEdit(); } var grouped = link.Group(); var documentChanges = new List <WorkspaceEditDocumentChange>(); foreach (var group in grouped) { List <TextEdit> edits = new List <TextEdit>(); foreach (var renameRange in group.Links) { edits.Add(new TextEdit() { NewText = request.NewName, Range = renameRange }); } var document = _languageServer.DocumentHandler.TextDocumentFromUri(group.Uri)?.AsItem(); // document will be null if the editor doesn't have the document of the group opened. if (document == null) { ImportedScript importedScript = _languageServer.FileGetter.GetImportedFile(group.Uri); document = new TextDocumentItem() { Uri = group.Uri, Text = importedScript.Content, LanguageId = "ostw" }; } WorkspaceEditDocumentChange edit = new WorkspaceEditDocumentChange(new TextDocumentEdit() { Edits = edits.ToArray(), TextDocument = new OptionalVersionedTextDocumentIdentifier() { Version = document.Version, Uri = document.Uri } }); documentChanges.Add(edit); } return new WorkspaceEdit() { DocumentChanges = documentChanges }; })); }
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); }
public async Task Handle_Rename_MultipleFileUsages() { // Arrange var request = new RenameParams { TextDocument = new TextDocumentIdentifier { Uri = new Uri("file:///c:/Second/Component3.razor") }, Position = new Position(1, 1), NewName = "Component5" }; // Act var result = await _endpoint.Handle(request, CancellationToken.None); // Assert Assert.NotNull(result); Assert.Equal(4, result.DocumentChanges.Count()); var renameChange = result.DocumentChanges.ElementAt(0); Assert.True(renameChange.IsRenameFile); Assert.Equal("file:///c:/Second/Component3.razor", renameChange.RenameFile.OldUri); Assert.Equal("file:///c:/Second/Component5.razor", renameChange.RenameFile.NewUri); var editChange1 = result.DocumentChanges.ElementAt(1); Assert.True(editChange1.IsTextDocumentEdit); Assert.Equal("file:///c:/Second/Component3.razor", editChange1.TextDocumentEdit.TextDocument.Uri.ToString()); Assert.Collection( editChange1.TextDocumentEdit.Edits, edit => { Assert.Equal("Component5", edit.NewText); Assert.Equal(1, edit.Range.Start.Line); Assert.Equal(1, edit.Range.Start.Character); Assert.Equal(1, edit.Range.End.Line); Assert.Equal(11, edit.Range.End.Character); }, edit => { Assert.Equal("Component5", edit.NewText); Assert.Equal(1, edit.Range.Start.Line); Assert.Equal(14, edit.Range.Start.Character); Assert.Equal(1, edit.Range.End.Line); Assert.Equal(24, edit.Range.End.Character); }); var editChange2 = result.DocumentChanges.ElementAt(2); Assert.True(editChange2.IsTextDocumentEdit); Assert.Equal("file:///c:/Second/Component4.razor", editChange2.TextDocumentEdit.TextDocument.Uri.ToString()); Assert.Equal(2, editChange2.TextDocumentEdit.Edits.Count()); }
public void Run(string testfile, int lineInEditor, int colInEditor, string newText = "newText") { Client.TextDocument.DidOpen(testfile, "dfy"); RenameParams p = new RenameParams() { NewName = newText, Position = new Position(lineInEditor - 1, colInEditor - 1), TextDocument = new TextDocumentIdentifier(new Uri(testfile)) }; var response = Client.SendRequest <WorkspaceEdit>("textDocument/rename", p, CancellationSource.Token); result = response.Result; }
public async System.Threading.Tasks.Task <WorkspaceEdit> TextDocumentRenameName(JToken arg) { if (trace) { System.Console.Error.WriteLine("<-- TextDocumentRename"); System.Console.Error.WriteLine(arg.ToString()); } RenameParams request = arg.ToObject <RenameParams>(); Document document = CheckDoc(request.TextDocument.Uri); Position position = request.Position; int line = position.Line; int character = position.Character; int index = LanguageServer.Module.GetIndex(line, character, document); if (trace) { System.Console.Error.WriteLine("position index = " + index); (int, int)back = LanguageServer.Module.GetLineColumn(index, document); System.Console.Error.WriteLine("back to l,c = " + back.Item1 + "," + back.Item2); } string new_name = request.NewName; Dictionary <string, LanguageServer.TextEdit[]> changes = LanguageServer.Module.Rename(index, new_name, document); WorkspaceEdit edit = new WorkspaceEdit(); int count = 0; Dictionary <string, Microsoft.VisualStudio.LanguageServer.Protocol.TextEdit[]> edit_changes_array = new Dictionary <string, Microsoft.VisualStudio.LanguageServer.Protocol.TextEdit[]>(); foreach (KeyValuePair <string, LanguageServer.TextEdit[]> pair in changes) { string doc = pair.Key; Uri uri = new Uri(doc); LanguageServer.TextEdit[] val = pair.Value; List <Microsoft.VisualStudio.LanguageServer.Protocol.TextEdit> new_list = new List <Microsoft.VisualStudio.LanguageServer.Protocol.TextEdit>(); foreach (LanguageServer.TextEdit v in val) { Microsoft.VisualStudio.LanguageServer.Protocol.TextEdit new_edit = new Microsoft.VisualStudio.LanguageServer.Protocol.TextEdit { Range = new Microsoft.VisualStudio.LanguageServer.Protocol.Range() }; (int, int)lcs = LanguageServer.Module.GetLineColumn(v.range.Start.Value, document); (int, int)lce = LanguageServer.Module.GetLineColumn(v.range.End.Value, document); new_edit.Range.Start = new Position(lcs.Item1, lcs.Item2); new_edit.Range.End = new Position(lce.Item1, lce.Item2); new_edit.NewText = v.NewText; new_list.Add(new_edit); count++; } edit_changes_array.Add(uri.ToString(), new_list.ToArray()); } edit.Changes = edit_changes_array; return(edit); }
public async Task <WorkspaceEdit?> HandleRequestAsync(RenameParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; Contract.ThrowIfNull(document); 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(null); } var options = new SymbolRenameOptions( RenameOverloads: false, RenameInStrings: false, RenameInComments: false, RenameFile: false); var renameLocationSet = await renameInfo.FindRenameLocationsAsync(options, cancellationToken).ConfigureAwait(false); var renameReplacementInfo = await renameLocationSet.GetReplacementsAsync(request.NewName, 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()); var textDiffService = renamedSolution.Services.GetRequiredService <IDocumentTextDifferencingService>(); var documentEdits = await ProtocolConversions.ChangedDocumentsToTextDocumentEditsAsync(changedDocuments, renamedSolution.GetRequiredDocument, oldSolution.GetRequiredDocument, textDiffService, cancellationToken).ConfigureAwait(false); return(new WorkspaceEdit { DocumentChanges = documentEdits }); }
public void SimpleTest(string expected) { var model = new RenameParams { NewName = "new name", Position = new Position(1, 2), TextDocument = new TextDocumentIdentifier(new Uri("file:///abc/123.cs")) }; var result = Fixture.SerializeObject(model); result.Should().Be(expected); var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject <RenameParams>(expected); deresult.Should().BeEquivalentTo(model); }
public async Task Handle_Rename_DifferentDirectories() { // Arrange var request = new RenameParams { TextDocument = new TextDocumentIdentifier { Uri = new Uri("file:///c:/Dir1/Directory1.razor") }, Position = new Position(1, 1), NewName = "TestComponent" }; // Act var result = await _endpoint.Handle(request, CancellationToken.None); // Assert Assert.NotNull(result); Assert.Equal(2, result.DocumentChanges.Count()); var renameChange = result.DocumentChanges.ElementAt(0); Assert.True(renameChange.IsRenameFile); Assert.Equal("file:///c:/Dir2/Directory2.razor", renameChange.RenameFile.OldUri); Assert.Equal("file:///c:/Dir2/TestComponent.razor", renameChange.RenameFile.NewUri); var editChange = result.DocumentChanges.ElementAt(1); Assert.True(editChange.IsTextDocumentEdit); Assert.Equal("file:///c:/Dir1/Directory1.razor", editChange.TextDocumentEdit.TextDocument.Uri.ToString()); Assert.Collection( editChange.TextDocumentEdit.Edits, edit => { Assert.Equal("TestComponent", edit.NewText); Assert.Equal(1, edit.Range.Start.Line); Assert.Equal(1, edit.Range.Start.Character); Assert.Equal(1, edit.Range.End.Line); Assert.Equal(11, edit.Range.End.Character); }, edit => { Assert.Equal("TestComponent", edit.NewText); Assert.Equal(1, edit.Range.Start.Line); Assert.Equal(14, edit.Range.Start.Character); Assert.Equal(1, edit.Range.End.Line); Assert.Equal(24, edit.Range.End.Character); }); }
public async Task <WorkspaceEdit> Handle(RenameParams request, CancellationToken cancellationToken) { try { var scriptFile = _projectManager.GetScriptForFilePath(request.TextDocument.Uri.ToFilePath()); if (scriptFile == null) { return(null); } var identifier = scriptFile.Node.GetDescendantNodeOfTypeAtPosition <IdentifierNode>(request.Position.ToPosition()); if (identifier == null) { return(null); } var symbol = identifier.GetDeclaredOrReferencedSymbol(); if (symbol == null) { return(null); } var referencingNodes = await symbol.FindReferences(cancellationToken); var referencingNodeEdits = referencingNodes.Select(node => new KeyValuePair <Uri, TextEdit>( PathUtilities.ToFileUri(node.GetScriptFile().FilePath), new TextEdit() { NewText = request.NewName, Range = node.Range.ToRange() })); var referencingNodeEditDictionary = referencingNodeEdits.GroupBy(k => k.Key).ToDictionary(k => k.Key, k => k.Select(v => v.Value)); return(new WorkspaceEdit() { Changes = referencingNodeEditDictionary }); } catch (Exception e) { _logger.LogWarning(e, "Error while handling request."); } return(null); }
public async Task Handle_Rename_WithNamespaceDirective() { // Arrange var request = new RenameParams { TextDocument = new TextDocumentIdentifier { Uri = new Uri("file:///c:/First/Component1.razor") }, Position = new Position(2, 1), NewName = "Component5" }; // Act var result = await _endpoint.Handle(request, CancellationToken.None); // Assert Assert.NotNull(result); Assert.Equal(2, result.DocumentChanges.Count()); var renameChange = result.DocumentChanges.ElementAt(0); Assert.True(renameChange.IsRenameFile); Assert.Equal("file:///c:/First/Component2.razor", renameChange.RenameFile.OldUri); Assert.Equal("file:///c:/First/Component5.razor", renameChange.RenameFile.NewUri); var editChange = result.DocumentChanges.ElementAt(1); Assert.True(editChange.IsTextDocumentEdit); Assert.Equal("file:///c:/First/Component1.razor", editChange.TextDocumentEdit.TextDocument.Uri.ToString()); Assert.Equal(2, editChange.TextDocumentEdit.Edits.Count()); var editChangeEdit1 = editChange.TextDocumentEdit.Edits.ElementAt(0); Assert.Equal("Component5", editChangeEdit1.NewText); Assert.Equal(2, editChangeEdit1.Range.Start.Line); Assert.Equal(1, editChangeEdit1.Range.Start.Character); Assert.Equal(2, editChangeEdit1.Range.End.Line); Assert.Equal(11, editChangeEdit1.Range.End.Character); var editChangeEdit2 = editChange.TextDocumentEdit.Edits.ElementAt(1); Assert.Equal("Component5", editChangeEdit2.NewText); Assert.Equal(2, editChangeEdit2.Range.Start.Line); Assert.Equal(14, editChangeEdit2.Range.Start.Character); Assert.Equal(2, editChangeEdit2.Range.End.Line); Assert.Equal(24, editChangeEdit2.Range.End.Character); }
public async Task HandleRequestAsync_CSharpProjection_RemapsWorkspaceEdit() { // Arrange var called = false; var expectedEdit = new WorkspaceEdit(); var documentManager = new TestDocumentManager(); documentManager.AddDocument(Uri, Mock.Of <LSPDocumentSnapshot>()); var requestInvoker = GetRequestInvoker <RenameParams, WorkspaceEdit>( new WorkspaceEdit(), (method, serverContentType, renameParams, ct) => { Assert.Equal(Methods.TextDocumentRenameName, method); Assert.Equal(RazorLSPConstants.CSharpContentTypeName, serverContentType); called = true; }); var projectionProvider = GetProjectionProvider(new ProjectionResult() { LanguageKind = RazorLanguageKind.CSharp }); var documentMappingProvider = GetDocumentMappingProvider(expectedEdit); var renameHandler = new RenameHandler(requestInvoker, documentManager, projectionProvider, documentMappingProvider); var renameRequest = new RenameParams() { Position = new Position(0, 1), NewName = "NewName", TextDocument = new TextDocumentIdentifier() { Uri = Uri }, }; // Act var result = await renameHandler.HandleRequestAsync(renameRequest, new ClientCapabilities(), CancellationToken.None).ConfigureAwait(false); // Assert Assert.True(called); Assert.Equal(expectedEdit, result); // Actual remapping behavior is tested in LSPDocumentMappingProvider tests. }
public async Task Handle_Rename_OnComponentNameTrailingEdge_ReturnsResult() { // Arrange var request = new RenameParams { TextDocument = new TextDocumentIdentifier { Uri = new Uri("file:///c:/Second/ComponentWithParam.razor") }, Position = new Position(1, 10), NewName = "Test2" }; // Act var result = await _endpoint.Handle(request, CancellationToken.None); // Assert Assert.NotNull(result); }
public override async Task <WorkspaceEdit> Handle(RenameParams request, CancellationToken cancellationToken) { var link = GetLink(request.TextDocument.Uri, request.Position); if (link == null) { return(new WorkspaceEdit()); } var grouped = link.Group(); var documentChanges = new List <WorkspaceEditDocumentChange>(); foreach (var group in grouped) { List <TextEdit> edits = new List <TextEdit>(); foreach (var renameRange in group.Links) { edits.Add(new TextEdit() { NewText = request.NewName, Range = renameRange.ToLsRange() }); } var document = _languageServer.DocumentHandler.TextDocumentFromUri(group.Uri); WorkspaceEditDocumentChange edit = new WorkspaceEditDocumentChange(new TextDocumentEdit() { Edits = edits.ToArray(), TextDocument = new VersionedTextDocumentIdentifier() { Version = document.Version, Uri = document.Uri } }); documentChanges.Add(edit); } return(new WorkspaceEdit() { DocumentChanges = documentChanges }); }
public override Task <WorkspaceEdit?> Handle(RenameParams request, CancellationToken cancellationToken) { var result = this.symbolResolver.ResolveSymbol(request.TextDocument.Uri, request.Position); if (result == null || !(result.Symbol is DeclaredSymbol)) { // result is not a symbol or it's a built-in symbol that was not declared by the user (namespaces, functions, for example) // symbols that are not declared by the user cannot be renamed return(Task.FromResult <WorkspaceEdit?>(null)); } var textEdits = result.Context.Compilation.GetEntrypointSemanticModel() .FindReferences(result.Symbol) .Select(GetIdentifier) .Where(identifierSyntax => identifierSyntax != null && identifierSyntax.IsValid) .Select(identifierSyntax => new TextEdit { Range = identifierSyntax !.ToRange(result.Context.LineStarts), NewText = request.NewName });
public async Task <WorkspaceEdit> Handle(RenameParams request, CancellationToken cancellationToken) { _log.LogInformation(string.Format(Resources.LoggingMessages.request_handle, _method)); try { var manager = _workspaceManager.GetFileRepository(request.TextDocument.Uri).SymbolTableManager; var line = (int)request.Position.Line + 1; var col = (int)request.Position.Character + 1; var uri = request.TextDocument.Uri; var newName = request.NewName; IRenameProvider provider = new RenameProvider(manager); return(await Task.Run(() => RunAndEvaulate(provider, newName, uri, line, col), cancellationToken)); } catch (Exception e) { HandleError(string.Format(Resources.LoggingMessages.request_error, _method), e); return(null); } }
public async Task Handle_Rename_FileManipulationNotSupported_ReturnsNull() { // Arrange var languageServerFeatureOptions = Mock.Of <LanguageServerFeatureOptions>(options => options.SupportsFileManipulation == false, MockBehavior.Strict); var endpoint = CreateEndpoint(languageServerFeatureOptions); var request = new RenameParams { TextDocument = new TextDocumentIdentifier { Uri = new Uri("file:///c:/First/Component1.razor") }, Position = new Position(2, 1), NewName = "Component5" }; // Act var result = await endpoint.Handle(request, CancellationToken.None); // Assert Assert.Null(result); }
public async Task <WorkspaceEdit> Handle(RenameParams request, CancellationToken token) { var omnisharpRequest = new RenameRequest { FileName = Helpers.FromUri(request.TextDocument.Uri), RenameTo = request.NewName, Column = Convert.ToInt32(request.Position.Character), Line = Convert.ToInt32(request.Position.Line), Buffer = request.NewName }; var omnisharpResponse = await _renameHandler.Handle(omnisharpRequest); if (omnisharpResponse.ErrorMessage != null) { } var changes = omnisharpResponse.Changes.ToDictionary(change => Helpers.ToUri(change.FileName), x => x.Changes.Select(edit => new TextEdit { NewText = edit.NewText, Range = Helpers.ToRange((edit.StartColumn, edit.StartLine), (edit.EndColumn, edit.EndLine)) }));
public async Task HandleRequestAsync_DocumentNotFound_ReturnsNull() { // Arrange var documentManager = new TestDocumentManager(); var requestInvoker = Mock.Of <LSPRequestInvoker>(MockBehavior.Strict); var projectionProvider = Mock.Of <LSPProjectionProvider>(MockBehavior.Strict); var documentMappingProvider = Mock.Of <LSPDocumentMappingProvider>(MockBehavior.Strict); var renameHandler = new RenameHandler(requestInvoker, documentManager, projectionProvider, documentMappingProvider, LoggerProvider); var renameRequest = new RenameParams() { Position = new Position(0, 1), NewName = "NewName", TextDocument = new TextDocumentIdentifier() { Uri = Uri }, }; // Act var result = await renameHandler.HandleRequestAsync(renameRequest, new ClientCapabilities(), CancellationToken.None).ConfigureAwait(false); // Assert Assert.Null(result); }
public override TextDocumentIdentifier?GetTextDocumentIdentifier(RenameParams request) => request.TextDocument;
public abstract Task <WorkspaceEdit> Handle(RenameParams request, CancellationToken cancellationToken);
public virtual Task <WorkspaceEdit> Rename(RenameParams @params, CancellationToken cancellationToken) => throw new NotImplementedException();
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); }
public Task <WorkspaceEdit> GetTextDocumentRenameAsync(RenameParams renameParams, CancellationToken cancellationToken) => _requestHandlerProvider.ExecuteRequestAsync <RenameParams, WorkspaceEdit>(Methods.TextDocumentRenameName, renameParams, _clientCapabilities, _clientName, cancellationToken);
// routines related to providing information for editor commands /// <summary> /// Returns the workspace edit that describes the changes to be done if the symbol at the given position - if any - is renamed to the given name. /// Returns null if no symbol exists at the specified position, /// or if the specified uri is not a valid file uri. /// or if some parameters are unspecified (null) or inconsistent with the tracked editor state. /// </summary> public WorkspaceEdit Rename(RenameParams param, bool versionedChanges = false) => ValidFileUri(param?.TextDocument?.Uri) && !IgnoreFile(param.TextDocument.Uri) ? this.Projects.Rename(param, versionedChanges) : null;
public override async Task <WorkspaceEdit> Rename(RenameParams @params, CancellationToken cancellationToken) { ProjectFiles.GetEntry(@params.textDocument, @params._version, out var entry, out var tree); if (entry == null || tree == null) { throw new InvalidOperationException(Resources.RenameVariable_UnableGetExpressionAnalysis); } var references = await FindReferences(new ReferencesParams { textDocument = new TextDocumentIdentifier { uri = @params.textDocument.uri }, position = @params.position, context = new ReferenceContext { includeDeclaration = true } }, cancellationToken); if (references.Any(x => x._isModule)) { throw new InvalidOperationException(Resources.RenameVariable_CannotRenameModuleName); } var definition = references.FirstOrDefault(r => r._kind == ReferenceKind.Definition); if (definition == null) { throw new InvalidOperationException(Resources.RenameVariable_CannotRename); } var definitionSpan = definition.range.ToLinearSpan(tree); var reader = new DocumentReader(entry as IDocument, ProjectFiles.GetPart(definition.uri)); var originalName = reader.Read(definitionSpan.Start, definitionSpan.Length); if (originalName == null) { throw new InvalidOperationException(Resources.RenameVariable_SelectSymbol); } if (!references.Any(r => r._kind == ReferenceKind.Definition || r._kind == ReferenceKind.Reference)) { throw new InvalidOperationException(Resources.RenameVariable_NoInformationAvailableForVariable.FormatUI(originalName)); } // See https://en.wikipedia.org/wiki/Name_mangling, Python section. var privatePrefix = entry.Analysis.GetPrivatePrefix(definition.range.start); if (!string.IsNullOrEmpty(privatePrefix) && !string.IsNullOrEmpty(originalName) && originalName.StartsWithOrdinal(privatePrefix)) { originalName = originalName.Substring(privatePrefix.Length + 1); } // Group by URI for more optimal document reading in FilterPrivatePrefixed var grouped = references .GroupBy(x => x.uri) .ToDictionary(g => g.Key, e => e.ToList()); var refs = FilterPrivatePrefixed(grouped, originalName, privatePrefix, @params.newName, @params.textDocument.uri, reader); // Convert to Dictionary<Uri, TextEdit[]> var changes = refs .ToDictionary( kvp => kvp.Key, kvp => kvp.Value.Select(t => new TextEdit { range = t.range, newText = @params.newName }).ToArray()); return(new WorkspaceEdit { changes = changes }); }
public static Task <WorkspaceEdit> Rename(this ILanguageClientDocument mediator, RenameParams @params, CancellationToken cancellationToken = default) { return(mediator.SendRequest(@params, cancellationToken)); }
public async Task <WorkspaceEdit> Handle(RenameParams request, CancellationToken cancellationToken) { if (request is null) { throw new ArgumentNullException(nameof(request)); } if (!_languageServerFeatureOptions.SupportsFileManipulation) { // If we cannot rename a component file then return early indicating a failure to rename anything. return(null); } var requestDocumentSnapshot = await Task.Factory.StartNew(() => { var path = request.TextDocument.Uri.GetAbsoluteOrUNCPath(); _documentResolver.TryResolveDocument(path, out var documentSnapshot); return(documentSnapshot); }, cancellationToken, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler).ConfigureAwait(false); if (requestDocumentSnapshot is null) { return(null); } if (!FileKinds.IsComponent(requestDocumentSnapshot.FileKind)) { return(null); } var codeDocument = await requestDocumentSnapshot.GetGeneratedOutputAsync().ConfigureAwait(false); if (codeDocument.IsUnsupported()) { return(null); } var originTagHelpers = await GetOriginTagHelpersAsync(requestDocumentSnapshot, codeDocument, request.Position).ConfigureAwait(false); if (originTagHelpers is null || originTagHelpers.Count == 0) { return(null); } var originComponentDocumentSnapshot = await _componentSearchEngine.TryLocateComponentAsync(originTagHelpers.First()).ConfigureAwait(false); if (originComponentDocumentSnapshot is null) { return(null); } var newPath = MakeNewPath(originComponentDocumentSnapshot.FilePath, request.NewName); if (File.Exists(newPath)) { return(null); } var documentChanges = new List <WorkspaceEditDocumentChange>(); AddFileRenameForComponent(documentChanges, originComponentDocumentSnapshot, newPath); AddEditsForCodeDocument(documentChanges, originTagHelpers, request.NewName, request.TextDocument.Uri, codeDocument); var documentSnapshots = await GetAllDocumentSnapshotsAsync(requestDocumentSnapshot, cancellationToken).ConfigureAwait(false); foreach (var documentSnapshot in documentSnapshots) { await AddEditsForCodeDocumentAsync(documentChanges, originTagHelpers, request.NewName, documentSnapshot, cancellationToken); } return(new WorkspaceEdit { DocumentChanges = documentChanges, }); }