Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RenameProvider #2788

Merged
merged 14 commits into from
Jul 17, 2022
5 changes: 3 additions & 2 deletions docs/en/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Perfomance measurement - [SSL 3.1](../bench/index.html)
* Quick fixes for several diagnostics
* Run diagnostics engine from command line
* Run formatter engine from command line
* Rename symbol

## Supported protocol operations

Expand Down Expand Up @@ -100,8 +101,8 @@ Perfomance measurement - [SSL 3.1](../bench/index.html)
| [formatting](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting) | <img src="./assets/images/checkmark.svg" alt="yes" width="20"> | | |
| [rangeFormatting](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rangeFormatting) | <img src="./assets/images/checkmark.svg" alt="yes" width="20"> | | |
| [onTypeFormatting](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_onTypeFormatting) | <img src="./assets/images/cross.svg" alt="no" width="20"> | | |
| [rename](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename) | <img src="./assets/images/cross.svg" alt="no" width="20"> | | |
| [prepareRename](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_prepareRename) | <img src="./assets/images/cross.svg" alt="no" width="20"> | | |
| [rename](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename) | <img src="./assets/images/checkmark.svg" alt="yes" width="20"> | | |
| [prepareRename](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_prepareRename) | <img src="./assets/images/checkmark.svg" alt="yes" width="20"> | | |
| [foldingRange](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_foldingRange) | <img src="./assets/images/checkmark.svg" alt="yes" width="20"> | | |
| [selectionRange](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_selectionRange) | <img src="./assets/images/checkmark.svg" alt="yes" width="20"> | | |
| [prepareCallHierarchy](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_prepareCallHierarchy) | <img src="./assets/images/checkmark.svg" alt="yes" width="20"> | | |
Expand Down
5 changes: 3 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
* "Быстрые исправления" (quick fixes) для ряда диагностик и "быстрые действия" (code actions)
* Запуск движка диагностик из командной строки
* Запуск форматирования файлов в каталоге из командной строки
* Переименование символов

## Поддерживаемые операции протокола

Expand Down Expand Up @@ -100,8 +101,8 @@
| [formatting](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting) | <img src="./assets/images/checkmark.svg" alt="yes" width="20"> | | |
| [rangeFormatting](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rangeFormatting) | <img src="./assets/images/checkmark.svg" alt="yes" width="20"> | | |
| [onTypeFormatting](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_onTypeFormatting) | <img src="./assets/images/cross.svg" alt="no" width="20"> | | |
| [rename](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename) | <img src="./assets/images/cross.svg" alt="no" width="20"> | | |
| [prepareRename](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_prepareRename) | <img src="./assets/images/cross.svg" alt="no" width="20"> | | |
| [rename](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename) | <img src="./assets/images/checkmark.svg" alt="yes" width="20"> | | |
| [prepareRename](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_prepareRename) | <img src="./assets/images/checkmark.svg" alt="yes" width="20"> | | |
| [foldingRange](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_foldingRange) | <img src="./assets/images/checkmark.svg" alt="yes" width="20"> | | |
| [selectionRange](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_selectionRange) | <img src="./assets/images/checkmark.svg" alt="yes" width="20"> | | |
| [prepareCallHierarchy](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_prepareCallHierarchy) | <img src="./assets/images/checkmark.svg" alt="yes" width="20"> | | |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.lsp4j.CallHierarchyRegistrationOptions;
import org.eclipse.lsp4j.ClientCapabilities;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.CodeActionOptions;
import org.eclipse.lsp4j.CodeLensOptions;
Expand All @@ -44,13 +45,17 @@
import org.eclipse.lsp4j.InitializeParams;
import org.eclipse.lsp4j.InitializeResult;
import org.eclipse.lsp4j.ReferenceOptions;
import org.eclipse.lsp4j.RenameCapabilities;
import org.eclipse.lsp4j.RenameOptions;
import org.eclipse.lsp4j.SaveOptions;
import org.eclipse.lsp4j.SelectionRangeRegistrationOptions;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.ServerInfo;
import org.eclipse.lsp4j.TextDocumentClientCapabilities;
import org.eclipse.lsp4j.TextDocumentSyncKind;
import org.eclipse.lsp4j.TextDocumentSyncOptions;
import org.eclipse.lsp4j.WorkspaceSymbolOptions;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.LanguageServer;
import org.eclipse.lsp4j.services.TextDocumentService;
import org.eclipse.lsp4j.services.WorkspaceService;
Expand All @@ -62,6 +67,7 @@
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

@Slf4j
Expand Down Expand Up @@ -101,6 +107,7 @@ public CompletableFuture<InitializeResult> initialize(InitializeParams params) {
capabilities.setCallHierarchyProvider(getCallHierarchyProvider());
capabilities.setSelectionRangeProvider(getSelectionRangeProvider());
capabilities.setColorProvider(getColorProvider());
capabilities.setRenameProvider(getRenameProvider(params));

var result = new InitializeResult(capabilities, serverInfo);

Expand Down Expand Up @@ -273,4 +280,32 @@ private static ColorProviderOptions getColorProvider() {
colorProviderOptions.setWorkDoneProgress(Boolean.FALSE);
return colorProviderOptions;
}

private static Either<Boolean, RenameOptions> getRenameProvider(InitializeParams params) {

if (Boolean.TRUE.equals(getRenamePrepareSupport(params))) {

var renameOptions = new RenameOptions();
renameOptions.setWorkDoneProgress(Boolean.FALSE);
renameOptions.setPrepareProvider(Boolean.TRUE);

return Either.forRight(renameOptions);

} else {

return Either.forLeft(Boolean.TRUE);

}

}

private static Boolean getRenamePrepareSupport(InitializeParams params) {
return Optional.of(params)
.map(InitializeParams::getCapabilities)
.map(ClientCapabilities::getTextDocument)
.map(TextDocumentClientCapabilities::getRename)
.map(RenameCapabilities::getPrepareSupport)
.orElse(false);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.github._1c_syntax.bsl.languageserver.providers.FormatProvider;
import com.github._1c_syntax.bsl.languageserver.providers.HoverProvider;
import com.github._1c_syntax.bsl.languageserver.providers.ReferencesProvider;
import com.github._1c_syntax.bsl.languageserver.providers.RenameProvider;
import com.github._1c_syntax.bsl.languageserver.providers.SelectionRangeProvider;
import com.github._1c_syntax.bsl.languageserver.utils.Ranges;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -75,11 +76,16 @@
import org.eclipse.lsp4j.HoverParams;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.LocationLink;
import org.eclipse.lsp4j.PrepareRenameParams;
import org.eclipse.lsp4j.PrepareRenameResult;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.ReferenceParams;
import org.eclipse.lsp4j.RenameParams;
import org.eclipse.lsp4j.SelectionRange;
import org.eclipse.lsp4j.SelectionRangeParams;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.TextDocumentService;
import org.springframework.stereotype.Component;
Expand Down Expand Up @@ -108,6 +114,7 @@ public class BSLTextDocumentService implements TextDocumentService, ProtocolExte
private final CallHierarchyProvider callHierarchyProvider;
private final SelectionRangeProvider selectionRangeProvider;
private final ColorProvider colorProvider;
private final RenameProvider renameProvider;

@Override
public CompletableFuture<Hover> hover(HoverParams params) {
Expand Down Expand Up @@ -367,6 +374,27 @@ public CompletableFuture<Diagnostics> diagnostics(DiagnosticParams params) {
});
}
asosnoviy marked this conversation as resolved.
Show resolved Hide resolved

@Override
public CompletableFuture<Either<Range, PrepareRenameResult>> prepareRename(PrepareRenameParams params) {
var documentContext = context.getDocument(params.getTextDocument().getUri());
if (documentContext == null) {
return CompletableFuture.completedFuture(null);
}
asosnoviy marked this conversation as resolved.
Show resolved Hide resolved

return CompletableFuture.supplyAsync(() ->
Either.forLeft(renameProvider.getPrepareRename(documentContext, params)));
}

@Override
public CompletableFuture<WorkspaceEdit> rename(RenameParams params) {
var documentContext = context.getDocument(params.getTextDocument().getUri());
if (documentContext == null) {
return CompletableFuture.completedFuture(null);
}

asosnoviy marked this conversation as resolved.
Show resolved Hide resolved
return CompletableFuture.supplyAsync(() -> renameProvider.getRename(documentContext, params));
}

public void reset() {
context.clear();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* This file is a part of BSL Language Server.
*
* Copyright (c) 2018-2022
* Alexey Sosnoviy <labotamy@gmail.com>, Nikita Fedkin <nixel2007@gmail.com> and contributors
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*
* BSL Language Server is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* BSL Language Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BSL Language Server.
*/
package com.github._1c_syntax.bsl.languageserver.providers;

import com.github._1c_syntax.bsl.languageserver.context.DocumentContext;
import com.github._1c_syntax.bsl.languageserver.context.symbol.SourceDefinedSymbol;
import com.github._1c_syntax.bsl.languageserver.references.ReferenceIndex;
import com.github._1c_syntax.bsl.languageserver.references.ReferenceResolver;
import com.github._1c_syntax.bsl.languageserver.references.model.Reference;
import lombok.RequiredArgsConstructor;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.RenameParams;
import org.eclipse.lsp4j.TextDocumentPositionParams;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* Провайдер, обрабатывающий запросы {@code textDocument/rename}
* и {@code textDocument/prepareRename}.
*
* @see <a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename">Rename Request specification</a>.
* @see <a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_prepareRename">Prepare Document Request specification</a>.
*/
@Component
@RequiredArgsConstructor
public final class RenameProvider {

private final ReferenceResolver referenceResolver;
private final ReferenceIndex referenceIndex;

/**
* {@link WorkspaceEdit}
*
* @param documentContext Контекст документа.
* @param params Параметры вызова.
* @return Изменения документов
*/
public WorkspaceEdit getRename(DocumentContext documentContext, RenameParams params) {

var position = params.getPosition();
var sourceDefinedSymbol = referenceResolver.findReference(documentContext.getUri(), position)
.flatMap(Reference::getSourceDefinedSymbol);

Map<String, List<TextEdit>> changes = Stream.concat(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

не будет ли здесь задублированного референса, если тыкать переименование по месту определения символа?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sourceDefinedSymbol
.stream()
.map(referenceIndex::getReferencesTo)
.flatMap(Collection::stream),
sourceDefinedSymbol
.stream().map(RenameProvider::referenceOf)
).collect(Collectors.groupingBy(ref -> ref.getUri().toString(), getTexEdits(params)));

return new WorkspaceEdit(changes);
}

private static Reference referenceOf(SourceDefinedSymbol symbol) {
return Reference.of(symbol, symbol, new Location(symbol.getOwner().getUri().toString(), symbol.getSelectionRange()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

здесь надо добавить OccurrenceType.DEFINITION последним параметром. мало ли где стрельнет.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

/**
* {@link Range}
*
* @param documentContext Контекст документа.
* @param params Параметры вызова.
* @return Range
*/
public Range getPrepareRename(DocumentContext documentContext, TextDocumentPositionParams params) {

return referenceResolver.findReference(
documentContext.getUri(), params.getPosition())
.filter(Reference::isSourceDefinedSymbolReference)
.map(Reference::getSelectionRange)
nixel2007 marked this conversation as resolved.
Show resolved Hide resolved
.orElse(null);
}

private static Collector<Reference, ?, List<TextEdit>> getTexEdits(RenameParams params) {
return Collectors.mapping(
Reference::getSelectionRange,
Collectors.mapping(range -> newTextEdit(params, range), Collectors.toList())
);
}

private static TextEdit newTextEdit(RenameParams params, Range range) {
return new TextEdit(range, params.getNewName());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@
import com.ginsberg.junit.exit.ExpectSystemExitWithStatus;
import com.github._1c_syntax.bsl.languageserver.util.CleanupContextBeforeClassAndAfterEachTestMethod;
import com.github._1c_syntax.utils.Absolute;
import org.eclipse.lsp4j.ClientCapabilities;
import org.eclipse.lsp4j.InitializeParams;
import org.eclipse.lsp4j.InitializeResult;
import org.eclipse.lsp4j.RenameCapabilities;
import org.eclipse.lsp4j.TextDocumentClientCapabilities;
import org.eclipse.lsp4j.WorkspaceFolder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -61,6 +64,28 @@ void initialize() throws ExecutionException, InterruptedException {
assertThat(initialize.getCapabilities().getWorkspaceSymbolProvider().isRight()).isTrue();
}

@Test
void initializeRename() throws ExecutionException, InterruptedException {
// given
InitializeParams params = new InitializeParams();

WorkspaceFolder workspaceFolder = new WorkspaceFolder(Absolute.path(PATH_TO_METADATA).toUri().toString());
List<WorkspaceFolder> workspaceFolders = List.of(workspaceFolder);
params.setWorkspaceFolders(workspaceFolders);

var capabilities = new ClientCapabilities();
params.setCapabilities(capabilities);
capabilities.setTextDocument(new TextDocumentClientCapabilities());
var textDocument = capabilities.getTextDocument();
textDocument.setRename(new RenameCapabilities());
textDocument.getRename().setPrepareSupport(true);
// when
InitializeResult initialize = server.initialize(params).get();

// then
assertThat(initialize.getCapabilities().getRenameProvider().isRight()).isTrue();
}

@Test
void shutdown() throws ExecutionException, InterruptedException {
CompletableFuture<Object> shutdown = server.shutdown();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
import org.eclipse.lsp4j.DidCloseTextDocumentParams;
import org.eclipse.lsp4j.DidOpenTextDocumentParams;
import org.eclipse.lsp4j.DidSaveTextDocumentParams;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.PrepareRenameParams;
import org.eclipse.lsp4j.RenameParams;
import org.eclipse.lsp4j.TextDocumentContentChangeEvent;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.TextDocumentItem;
Expand Down Expand Up @@ -137,6 +140,28 @@ void testDiagnosticsKnownFileFilteredRange() throws ExecutionException, Interrup
assertThat(diagnostics.getDiagnostics()).hasSize(2);
}

@Test
void testRename() throws ExecutionException, InterruptedException, IOException {
var params = new RenameParams();
params.setTextDocument(getTextDocumentIdentifier());
params.setPosition(new Position(0, 16));

var result = textDocumentService.rename(params);

assertThat(result).isNotNull();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это прям подстава, по факту там null =)

}

@Test
void testRenamePrepare() throws ExecutionException, InterruptedException, IOException {
var params = new PrepareRenameParams();
params.setTextDocument(getTextDocumentIdentifier());
params.setPosition(new Position(0, 16));

var result = textDocumentService.prepareRename(params);

assertThat(result).isNotNull();
}

private File getTestFile() {
return new File("./src/test/resources/BSLTextDocumentServiceTest.bsl");
}
Expand Down
Loading