Skip to content

Commit

Permalink
IRenameParticipant.doRename() is not conform with LSP-defined rename …
Browse files Browse the repository at this point in the history
…result eclipse#1521
  • Loading branch information
vrubezhny committed Jun 1, 2023
1 parent 7c2c591 commit 3f40e5f
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
*******************************************************************************/
package org.eclipse.lemminx.extensions.references.participants;

import static org.eclipse.lemminx.utils.TextEditUtils.mergeOrAddTextEdits;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand All @@ -26,6 +28,8 @@
import org.eclipse.lemminx.services.extensions.IRenameRequest;
import org.eclipse.lsp4j.PrepareRenameResult;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.ResourceOperation;
import org.eclipse.lsp4j.TextDocumentEdit;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
Expand Down Expand Up @@ -88,8 +92,8 @@ private static String createPlaceHolder(SearchNode searchNode) {
// --------------- Rename

@Override
public void doRename(IRenameRequest request, List<TextEdit> edits, CancelChecker cancelChecker) {
edits.addAll(getRenameTextEdits(request, cancelChecker));
public void doRename(IRenameRequest request, List<Either<TextDocumentEdit, ResourceOperation>> documentChanges, CancelChecker cancelChecker) {
mergeOrAddTextEdits(request.getXMLDocument(), getRenameTextEdits(request, cancelChecker), documentChanges);
}

private List<TextEdit> getRenameTextEdits(IRenameRequest request, CancelChecker cancelChecker) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2022 Red Hat Inc. and others.
* Copyright (c) 2022, 2023 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
Expand All @@ -11,6 +11,8 @@
*******************************************************************************/
package org.eclipse.lemminx.extensions.relaxng.grammar.rng;

import static org.eclipse.lemminx.utils.TextEditUtils.mergeOrAddTextEdits;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand All @@ -30,6 +32,8 @@
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.PrepareRenameResult;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.ResourceOperation;
import org.eclipse.lsp4j.TextDocumentEdit;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
Expand Down Expand Up @@ -59,8 +63,8 @@ public Either<Range, PrepareRenameResult> prepareRename(IPrepareRenameRequest re
// --------------- Rename

@Override
public void doRename(IRenameRequest request, List<TextEdit> edits, CancelChecker cancelChecker) {
edits.addAll(getRenameTextEdits(request, cancelChecker));
public void doRename(IRenameRequest request, List<Either<TextDocumentEdit, ResourceOperation>> documentChanges, CancelChecker cancelChecker) {
mergeOrAddTextEdits(request.getXMLDocument(), getRenameTextEdits(request, cancelChecker), documentChanges);
}

private List<TextEdit> getRenameTextEdits(IRenameRequest request, CancelChecker cancelChecker) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019 Red Hat Inc. and others.
* Copyright (c) 2019, 2023 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
Expand All @@ -11,6 +11,8 @@
*******************************************************************************/
package org.eclipse.lemminx.extensions.xsd.participants;

import static org.eclipse.lemminx.utils.TextEditUtils.mergeOrAddTextEdits;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand All @@ -32,6 +34,8 @@
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.PrepareRenameResult;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.ResourceOperation;
import org.eclipse.lsp4j.TextDocumentEdit;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
Expand Down Expand Up @@ -62,8 +66,8 @@ public Either<Range, PrepareRenameResult> prepareRename(IPrepareRenameRequest re
// --------------- Rename

@Override
public void doRename(IRenameRequest request, List<TextEdit> edits, CancelChecker cancelChecker) {
edits.addAll(getRenameTextEdits(request, cancelChecker));
public void doRename(IRenameRequest request, List<Either<TextDocumentEdit, ResourceOperation>> documentChanges, CancelChecker cancelChecker) {
mergeOrAddTextEdits(request.getXMLDocument(), getRenameTextEdits(request, cancelChecker), documentChanges);
}

private List<TextEdit> getRenameTextEdits(IRenameRequest request, CancelChecker cancelChecker) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018 Angelo ZERR
* Copyright (c) 2018, 2023 Angelo ZERR
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -27,12 +27,12 @@
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLValidationSettings;
import org.eclipse.lemminx.services.extensions.XMLExtensionsRegistry;
import org.eclipse.lemminx.services.extensions.diagnostics.DiagnosticsResult;
import org.eclipse.lemminx.services.format.TextEditUtils;
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lemminx.settings.XMLCodeLensSettings;
import org.eclipse.lemminx.settings.XMLCompletionSettings;
import org.eclipse.lemminx.settings.XMLFoldingSettings;
import org.eclipse.lemminx.settings.XMLSymbolSettings;
import org.eclipse.lemminx.utils.TextEditUtils;
import org.eclipse.lemminx.utils.XMLPositionUtility;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionContext;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019 Red Hat Inc. and others.
* Copyright (c) 2019, 2023 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
Expand All @@ -11,6 +11,7 @@
*******************************************************************************/
package org.eclipse.lemminx.services;

import static org.eclipse.lemminx.utils.TextEditUtils.mergeOrAddTextEdits;
import static org.eclipse.lemminx.utils.XMLPositionUtility.covers;
import static org.eclipse.lemminx.utils.XMLPositionUtility.doesTagCoverPosition;
import static org.eclipse.lemminx.utils.XMLPositionUtility.getTagNameRange;
Expand All @@ -21,6 +22,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CancellationException;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand All @@ -38,16 +40,20 @@
import org.eclipse.lemminx.services.extensions.XMLExtensionsRegistry;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.ResourceOperation;
import org.eclipse.lsp4j.TextDocumentEdit;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4j.jsonrpc.messages.Either;

/**
* Handle all rename requests
*
* Author: Nikolas Komonen - [email protected]
*/
public class XMLRename {
class XMLRename {

private static final Logger LOGGER = Logger.getLogger(XMLRename.class.getName());

Expand Down Expand Up @@ -76,14 +82,14 @@ public WorkspaceEdit doRename(DOMDocument xmlDocument, Position position, String
if (node == null || (!node.isAttribute() && !node.isElement() && !node.isText())
|| (node.isElement() && !((DOMElement) node).hasTagName())) {

return createWorkspaceEdit(xmlDocument.getDocumentURI(), Collections.emptyList());
cancelChecker.checkCanceled();
return createWorkspaceEdit(Collections.emptyList());
}

List<TextEdit> textEdits = new ArrayList<>();

List<Either<TextDocumentEdit, ResourceOperation>> documentChanges = new ArrayList<>();
for (IRenameParticipant participant : extensionsRegistry.getRenameParticipants()) {
try {
participant.doRename(renameRequest, textEdits, cancelChecker);
participant.doRename(renameRequest, documentChanges, cancelChecker);
} catch (CancellationException e) {
throw e;
} catch (Exception e) {
Expand All @@ -93,13 +99,13 @@ public WorkspaceEdit doRename(DOMDocument xmlDocument, Position position, String
}
}

textEdits.addAll(getRenameTextEdits(xmlDocument, node, position, newText));
cancelChecker.checkCanceled();
mergeOrAddTextEdits(xmlDocument, getRenameTextEdits(xmlDocument, node, position, newText), documentChanges);

cancelChecker.checkCanceled();

return createWorkspaceEdit(xmlDocument.getDocumentURI(), textEdits);
return createWorkspaceEdit(documentChanges);
}

private List<TextEdit> getRenameTextEdits(DOMDocument xmlDocument, DOMNode node, Position position,
String newText) {
if (node == null || node.isText()) {
Expand Down Expand Up @@ -279,6 +285,10 @@ private List<TextEdit> getXmlnsAttrRenameTextEdits(DOMDocument xmlDocument, DOME
return Collections.emptyList();
}

private WorkspaceEdit createWorkspaceEdit(List<Either<TextDocumentEdit, ResourceOperation>> documentChanges) {
return new WorkspaceEdit(documentChanges);
}

private WorkspaceEdit createWorkspaceEdit(String documentURI, List<TextEdit> textEdits) {
Map<String, List<TextEdit>> changes = new HashMap<>();
changes.put(documentURI, textEdits);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019 Red Hat Inc. and others.
* Copyright (c) 2019, 2023 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
Expand All @@ -15,7 +15,8 @@

import org.eclipse.lsp4j.PrepareRenameResult;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.ResourceOperation;
import org.eclipse.lsp4j.TextDocumentEdit;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4j.jsonrpc.messages.Either;

Expand All @@ -25,7 +26,22 @@
*/
public interface IRenameParticipant {

void doRename(IRenameRequest request, List<TextEdit> edits, CancelChecker cancelChecker);
/**
* Creates the list of document changes for the rename operation.
*
* @since 0.26
* @param request A rename request
* @param documentChanges A list to collect either text document edits or rename operations
* @param cancelChecker Cancel checker
*/
void doRename(IRenameRequest request, List<Either<TextDocumentEdit, ResourceOperation>> documentChanges, CancelChecker cancelChecker);

/**
* Checks if rename operation can be executed for a given prepare rename request
*
* @param request A prepare rename request
* @param cancelChecker Cancel checker
* @return Either range or rename operation result of prepare rename operation
*/
Either<Range, PrepareRenameResult> prepareRename(IPrepareRenameRequest request, CancelChecker cancelChecker);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2022 Red Hat Inc. and others.
* Copyright (c) 2022, 2023 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
Expand Down Expand Up @@ -35,6 +35,7 @@
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lemminx.settings.XMLFormattingOptions;
import org.eclipse.lemminx.utils.StringUtils;
import org.eclipse.lemminx.utils.TextEditUtils;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextEdit;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2022 Red Hat Inc. and others.
* Copyright (c) 2022, 2023 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
Expand All @@ -9,20 +9,26 @@
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.lemminx.services.format;
package org.eclipse.lemminx.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import org.eclipse.lemminx.commons.BadLocationException;
import org.eclipse.lemminx.commons.TextDocument;
import org.eclipse.lemminx.dom.DOMDocument;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.ResourceOperation;
import org.eclipse.lsp4j.TextDocumentEdit;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
import org.eclipse.lsp4j.jsonrpc.messages.Either;

/**
* Utilities for {@link TextEdit}.
Expand Down Expand Up @@ -147,4 +153,36 @@ public static int adjustOffsetWithLeftWhitespaces(int leftLimit, int to, String
return leftLimit;
}

/**
* Merges the given text edits into an existing text document edits or creates and adds new
* text document edits for a given list of text edits.
*
* @param document XML Document being edited
* @param textEdits A list of Text edits to add or merge
* @param documentChanges Target list of either text document edits or rename operations
*/
public static void mergeOrAddTextEdits(DOMDocument document, List<TextEdit> textEdits,
List<Either<TextDocumentEdit, ResourceOperation>> documentChanges) {
String documentURI = document.getDocumentURI();
Optional<TextDocumentEdit> change = documentChanges.stream().filter(Either::isLeft)
.filter(e -> documentURI.equals(e.getLeft().getTextDocument().getUri()))
.map(Either::getLeft).findFirst();
if(change.isPresent()) {
TextDocumentEdit textDocumentEdit = change.get();
List<TextEdit> edits = new ArrayList<>();
edits.addAll(textDocumentEdit.getEdits());
textEdits.stream().forEach(te -> {
if (!edits.contains(te)) {
edits.add(te);
}
});
textDocumentEdit.setEdits(edits);
} else {
VersionedTextDocumentIdentifier projectVersionedTextDocumentIdentifier = new VersionedTextDocumentIdentifier(
documentURI, document.getTextDocument().getVersion());
documentChanges.add(Either.forLeft(new TextDocumentEdit(
projectVersionedTextDocumentIdentifier, textEdits)));
}
}

}
Loading

0 comments on commit 3f40e5f

Please sign in to comment.