From f7b3e72c2efc1768235c4d9c07ee4b2fc06429e2 Mon Sep 17 00:00:00 2001 From: Victor Rubezhny Date: Thu, 1 Jun 2023 18:03:12 +0200 Subject: [PATCH] IRenameParticipant.doRename() is not conform with LSP-defined rename result #1521 --- .../XMLReferencesRenameParticipant.java | 15 +++-- .../grammar/rng/RNGRenameParticipant.java | 20 +++--- .../participants/XSDRenameParticipant.java | 19 +++--- .../lemminx/services/RenameResponse.java | 63 +++++++++++++++++++ .../lemminx/services/XMLLanguageService.java | 4 +- .../eclipse/lemminx/services/XMLRename.java | 27 ++++---- .../extensions/IRenameParticipant.java | 20 +++++- .../services/extensions/IRenameResponse.java | 44 +++++++++++++ .../services/format/XMLFormatterDocument.java | 3 +- .../format => utils}/TextEditUtils.java | 26 +++++++- .../java/org/eclipse/lemminx/XMLAssert.java | 16 +++-- .../ErrorParticipantLanguageServiceTest.java | 4 +- .../format/LeftWhitespacesOffsetTest.java | 3 +- .../services/format/TextEditUtilsTest.java | 3 +- 14 files changed, 213 insertions(+), 54 deletions(-) create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/RenameResponse.java create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/extensions/IRenameResponse.java rename org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/{services/format => utils}/TextEditUtils.java (79%) diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/references/participants/XMLReferencesRenameParticipant.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/references/participants/XMLReferencesRenameParticipant.java index 7ddddd031..39e6c73e4 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/references/participants/XMLReferencesRenameParticipant.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/references/participants/XMLReferencesRenameParticipant.java @@ -11,6 +11,8 @@ *******************************************************************************/ package org.eclipse.lemminx.extensions.references.participants; +import static org.eclipse.lemminx.utils.TextEditUtils.creatTextDocumentEdit; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -24,8 +26,11 @@ import org.eclipse.lemminx.services.extensions.IPrepareRenameRequest; import org.eclipse.lemminx.services.extensions.IRenameParticipant; import org.eclipse.lemminx.services.extensions.IRenameRequest; +import org.eclipse.lemminx.services.extensions.IRenameResponse; 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; @@ -88,11 +93,11 @@ private static String createPlaceHolder(SearchNode searchNode) { // --------------- Rename @Override - public void doRename(IRenameRequest request, List edits, CancelChecker cancelChecker) { - edits.addAll(getRenameTextEdits(request, cancelChecker)); + public void doRename(IRenameRequest request, IRenameResponse renameResponse, CancelChecker cancelChecker) { + renameResponse.addTextDocumentEdit(getRenameTextDocumentEdit(request, cancelChecker)); } - private List getRenameTextEdits(IRenameRequest request, CancelChecker cancelChecker) { + private TextDocumentEdit getRenameTextDocumentEdit(IRenameRequest request, CancelChecker cancelChecker) { SearchQuery query = SearchQueryFactory.createToQueryByRetrievingToBefore(request.getNode(), request.getOffset(), plugin.getReferencesSettings(), cancelChecker); if (query == null) { @@ -100,7 +105,7 @@ private List getRenameTextEdits(IRenameRequest request, CancelChecker // - the node is neither a text nor an attribute // - it doesn't exists some expressions for the DOM document of the node. // - there are none expressions which matches the node. - return Collections.emptyList(); + return null; } query.setMatchNode(true); query.setSearchInIncludedFiles(true); @@ -117,7 +122,7 @@ private List getRenameTextEdits(IRenameRequest request, CancelChecker // Insert at first, the text edit for the node which was updated Range range = query.getSearchNode().createRange(true); textEdits.add(0, new TextEdit(range, newText)); - return textEdits; + return creatTextDocumentEdit(request.getXMLDocument(), textEdits); } } \ No newline at end of file diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/grammar/rng/RNGRenameParticipant.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/grammar/rng/RNGRenameParticipant.java index bf599bb87..43510afa9 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/grammar/rng/RNGRenameParticipant.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/grammar/rng/RNGRenameParticipant.java @@ -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 @@ -11,6 +11,8 @@ *******************************************************************************/ package org.eclipse.lemminx.extensions.relaxng.grammar.rng; +import static org.eclipse.lemminx.utils.TextEditUtils.creatTextDocumentEdit; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -25,11 +27,13 @@ import org.eclipse.lemminx.services.extensions.IPrepareRenameRequest; import org.eclipse.lemminx.services.extensions.IRenameParticipant; import org.eclipse.lemminx.services.extensions.IRenameRequest; +import org.eclipse.lemminx.services.extensions.IRenameResponse; import org.eclipse.lemminx.utils.DOMUtils; import org.eclipse.lemminx.utils.XMLPositionUtility; import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.PrepareRenameResult; import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.TextDocumentEdit; import org.eclipse.lsp4j.TextEdit; import org.eclipse.lsp4j.jsonrpc.CancelChecker; import org.eclipse.lsp4j.jsonrpc.messages.Either; @@ -59,22 +63,22 @@ public Either prepareRename(IPrepareRenameRequest re // --------------- Rename @Override - public void doRename(IRenameRequest request, List edits, CancelChecker cancelChecker) { - edits.addAll(getRenameTextEdits(request, cancelChecker)); + public void doRename(IRenameRequest request, IRenameResponse renameResponse, CancelChecker cancelChecker) { + renameResponse.addTextDocumentEdit(getRenameTextDocumentEdit(request, cancelChecker)); } - private List getRenameTextEdits(IRenameRequest request, CancelChecker cancelChecker) { + private TextDocumentEdit getRenameTextDocumentEdit(IRenameRequest request, CancelChecker cancelChecker) { // RNG rename can be applied for: // - define/@name DOMAttr attr = findAttrToRename(request); if (attr == null) { - return Collections.emptyList(); + return null; } DOMElement ownerElement = attr.getOwnerElement(); DOMDocument document = request.getXMLDocument(); String newText = request.getNewText(); List locations = getReferenceLocations(ownerElement, cancelChecker); - return renameAttributeValueTextEdits(document, attr, newText, locations); + return creatTextDocumentEdit(document, renameAttributeValueTextEdits(document, attr, newText, locations)); } private List getReferenceLocations(DOMNode node, CancelChecker cancelChecker) { @@ -105,9 +109,7 @@ private List renameAttributeValueTextEdits(DOMDocument document, DOMAt for (Location location : locations) { Range textEditRange = location.getRange(); reduceRangeFromBothEnds(textEditRange, 1); - - TextEdit textEdit = new TextEdit(textEditRange, newText); - textEdits.add(textEdit); + textEdits.add(new TextEdit(textEditRange, newText)); } return textEdits; diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xsd/participants/XSDRenameParticipant.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xsd/participants/XSDRenameParticipant.java index 6601fbcc8..23b37ebaa 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xsd/participants/XSDRenameParticipant.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xsd/participants/XSDRenameParticipant.java @@ -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 @@ -11,6 +11,8 @@ *******************************************************************************/ package org.eclipse.lemminx.extensions.xsd.participants; +import static org.eclipse.lemminx.utils.TextEditUtils.creatTextDocumentEdit; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -26,12 +28,14 @@ import org.eclipse.lemminx.services.extensions.IPrepareRenameRequest; import org.eclipse.lemminx.services.extensions.IRenameParticipant; import org.eclipse.lemminx.services.extensions.IRenameRequest; +import org.eclipse.lemminx.services.extensions.IRenameResponse; import org.eclipse.lemminx.utils.DOMUtils; import org.eclipse.lemminx.utils.XMLPositionUtility; import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.PrepareRenameResult; import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.TextDocumentEdit; import org.eclipse.lsp4j.TextEdit; import org.eclipse.lsp4j.jsonrpc.CancelChecker; import org.eclipse.lsp4j.jsonrpc.messages.Either; @@ -62,23 +66,23 @@ public Either prepareRename(IPrepareRenameRequest re // --------------- Rename @Override - public void doRename(IRenameRequest request, List edits, CancelChecker cancelChecker) { - edits.addAll(getRenameTextEdits(request, cancelChecker)); + public void doRename(IRenameRequest request, IRenameResponse renameResponse, CancelChecker cancelChecker) { + renameResponse.addTextDocumentEdit(getRenameTextDocumentEdit(request, cancelChecker)); } - private List getRenameTextEdits(IRenameRequest request, CancelChecker cancelChecker) { + private TextDocumentEdit getRenameTextDocumentEdit(IRenameRequest request, CancelChecker cancelChecker) { // XSD rename can be applied for: // - xsd:complexType/@name // - xs:simpleType/@name DOMAttr attr = findAttrToRename(request); if (attr == null) { - return Collections.emptyList(); + return null; } DOMElement ownerElement = attr.getOwnerElement(); DOMDocument document = request.getXMLDocument(); String newText = request.getNewText(); List locations = getReferenceLocations(ownerElement, cancelChecker); - return renameAttributeValueTextEdits(document, attr, newText, locations); + return creatTextDocumentEdit(document, renameAttributeValueTextEdits(document, attr, newText, locations)); } private List getReferenceLocations(DOMNode node, CancelChecker cancelChecker) { @@ -123,8 +127,7 @@ private List renameAttributeValueTextEdits(DOMDocument document, DOMAt increaseStartRange(textEditRange, colonIndex + 1); } - TextEdit textEdit = new TextEdit(textEditRange, newText); - textEdits.add(textEdit); + textEdits.add(new TextEdit(textEditRange, newText)); } return textEdits; diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/RenameResponse.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/RenameResponse.java new file mode 100644 index 000000000..827c381ec --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/RenameResponse.java @@ -0,0 +1,63 @@ +/******************************************************************************* +* Copyright (c) 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 +* +* SPDX-License-Identifier: EPL-2.0 +* +* Contributors: +* Red Hat Inc. - initial API and implementation +*******************************************************************************/ +package org.eclipse.lemminx.services; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.eclipse.lemminx.services.extensions.IRenameResponse; +import org.eclipse.lsp4j.ResourceOperation; +import org.eclipse.lsp4j.TextDocumentEdit; +import org.eclipse.lsp4j.TextEdit; +import org.eclipse.lsp4j.jsonrpc.messages.Either; + +/** + * Rename response object to store the rename operation results + */ +class RenameResponse implements IRenameResponse { + private List> documentChanges = new ArrayList<>(); + + @Override + public void addTextDocumentEdit(TextDocumentEdit textDocumentEdit) { + if (textDocumentEdit == null) { + return; + } + + String documentURI = textDocumentEdit.getTextDocument().getUri(); + Optional change = documentChanges.stream().filter(Either::isLeft) + .filter(e -> documentURI.equals(e.getLeft().getTextDocument().getUri())) + .map(Either::getLeft).findFirst(); + if(change.isPresent()) { + TextDocumentEdit existingTextDocumentEdit = change.get(); + List edits = new ArrayList<>(); + edits.addAll(existingTextDocumentEdit.getEdits()); + textDocumentEdit.getEdits().stream().forEach(te -> { + if (!edits.contains(te)) { + edits.add(te); + } + }); + existingTextDocumentEdit.setEdits(edits); + } else { + documentChanges.add(Either.forLeft(textDocumentEdit)); + } + } + + @Override + public void addResourceOperation(ResourceOperation resourceOperation) { + documentChanges.add(Either.forRight(resourceOperation)); + } + + public List> getDocumentChanges() { + return documentChanges; + } +} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/XMLLanguageService.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/XMLLanguageService.java index 1e62fb639..923b8d141 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/XMLLanguageService.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/XMLLanguageService.java @@ -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 @@ -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; diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/XMLRename.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/XMLRename.java index 8b0187796..f175db3da 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/XMLRename.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/XMLRename.java @@ -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 @@ -11,6 +11,8 @@ *******************************************************************************/ package org.eclipse.lemminx.services; +import static org.eclipse.lemminx.utils.TextEditUtils.creatTextDocumentEdit; +import static org.eclipse.lemminx.utils.TextEditUtils.createWorkspaceEdit; import static org.eclipse.lemminx.utils.XMLPositionUtility.covers; import static org.eclipse.lemminx.utils.XMLPositionUtility.doesTagCoverPosition; import static org.eclipse.lemminx.utils.XMLPositionUtility.getTagNameRange; @@ -47,7 +49,7 @@ * * Author: Nikolas Komonen - nkomonen@redhat.com */ -public class XMLRename { +class XMLRename { private static final Logger LOGGER = Logger.getLogger(XMLRename.class.getName()); @@ -76,14 +78,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 textEdits = new ArrayList<>(); - + RenameResponse renameResponse = new RenameResponse(); for (IRenameParticipant participant : extensionsRegistry.getRenameParticipants()) { try { - participant.doRename(renameRequest, textEdits, cancelChecker); + participant.doRename(renameRequest, renameResponse, cancelChecker); } catch (CancellationException e) { throw e; } catch (Exception e) { @@ -93,11 +95,12 @@ public WorkspaceEdit doRename(DOMDocument xmlDocument, Position position, String } } - textEdits.addAll(getRenameTextEdits(xmlDocument, node, position, newText)); + cancelChecker.checkCanceled(); + renameResponse.addTextDocumentEdit(creatTextDocumentEdit( + xmlDocument, getRenameTextEdits(xmlDocument, node, position, newText))); cancelChecker.checkCanceled(); - - return createWorkspaceEdit(xmlDocument.getDocumentURI(), textEdits); + return createWorkspaceEdit(renameResponse.getDocumentChanges()); } private List getRenameTextEdits(DOMDocument xmlDocument, DOMNode node, Position position, @@ -279,12 +282,6 @@ private List getXmlnsAttrRenameTextEdits(DOMDocument xmlDocument, DOME return Collections.emptyList(); } - private WorkspaceEdit createWorkspaceEdit(String documentURI, List textEdits) { - Map> changes = new HashMap<>(); - changes.put(documentURI, textEdits); - return new WorkspaceEdit(changes); - } - /** * Creates a list of start and end tag rename's. * diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/extensions/IRenameParticipant.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/extensions/IRenameParticipant.java index 78ada5407..5d49e7a30 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/extensions/IRenameParticipant.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/extensions/IRenameParticipant.java @@ -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 @@ -15,7 +15,6 @@ import org.eclipse.lsp4j.PrepareRenameResult; import org.eclipse.lsp4j.Range; -import org.eclipse.lsp4j.TextEdit; import org.eclipse.lsp4j.jsonrpc.CancelChecker; import org.eclipse.lsp4j.jsonrpc.messages.Either; @@ -25,7 +24,22 @@ */ public interface IRenameParticipant { - void doRename(IRenameRequest request, List edits, CancelChecker cancelChecker); + /** + * Creates the list of document changes for the rename operation. + * + * @param request A rename request + * @param documentChanges A list to collect either text document edits or rename operations + * @param cancelChecker Cancel checker + * @since 0.26 + */ + void doRename(IRenameRequest request, IRenameResponse renameResponse, 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 prepareRename(IPrepareRenameRequest request, CancelChecker cancelChecker); } \ No newline at end of file diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/extensions/IRenameResponse.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/extensions/IRenameResponse.java new file mode 100644 index 000000000..939efee1f --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/extensions/IRenameResponse.java @@ -0,0 +1,44 @@ +/******************************************************************************* +* Copyright (c) 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 +* +* SPDX-License-Identifier: EPL-2.0 +* +* Contributors: +* Red Hat Inc. - initial API and implementation +*******************************************************************************/ +package org.eclipse.lemminx.services.extensions; + +import java.util.List; + +import org.eclipse.lsp4j.ResourceOperation; +import org.eclipse.lsp4j.TextDocumentEdit; + +/** + * Rename response API. + * + * @dince 0.26 + */ +public interface IRenameResponse { + + /** + * Adds text document edit to rename response. + * + * @param request A rename request + * @param textDocumentEdit A TextDocumentEdit object to be added to rename response + * @since 0.26 + */ + void addTextDocumentEdit(TextDocumentEdit textDocumentEdit); + + /** + * Adds resource operation to rename response. + * + * @param request A rename request + * @param resourceOperation A ResourceOperation object to store to rename response + * @since 0.26 + */ + void addResourceOperation(ResourceOperation resourceOperation); + +} \ No newline at end of file diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/format/XMLFormatterDocument.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/format/XMLFormatterDocument.java index 582c0312d..425a94b67 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/format/XMLFormatterDocument.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/format/XMLFormatterDocument.java @@ -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 @@ -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; diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/format/TextEditUtils.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/utils/TextEditUtils.java similarity index 79% rename from org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/format/TextEditUtils.java rename to org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/utils/TextEditUtils.java index 281c9c332..f8212c708 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/format/TextEditUtils.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/utils/TextEditUtils.java @@ -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 @@ -9,7 +9,7 @@ * 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; @@ -20,9 +20,15 @@ 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.WorkspaceEdit; +import org.eclipse.lsp4j.jsonrpc.messages.Either; /** * Utilities for {@link TextEdit}. @@ -147,4 +153,20 @@ public static int adjustOffsetWithLeftWhitespaces(int leftLimit, int to, String return leftLimit; } + /** + * Creates a TextDocumentEdit object for the specified document and list of text edits + * + * @param document Document to be changed + * @param textEdits a list of text edit changes + * @return A Text Dpcument Edit object + */ + public static TextDocumentEdit creatTextDocumentEdit(DOMDocument document, List textEdits) { + VersionedTextDocumentIdentifier projectVersionedTextDocumentIdentifier = new VersionedTextDocumentIdentifier( + document.getDocumentURI(), document.getTextDocument().getVersion()); + return new TextDocumentEdit(projectVersionedTextDocumentIdentifier, textEdits); + } + + public static WorkspaceEdit createWorkspaceEdit(List> documentChanges) { + return new WorkspaceEdit(documentChanges); + } } diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/XMLAssert.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/XMLAssert.java index 473941fd4..c5398e81a 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/XMLAssert.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/XMLAssert.java @@ -12,7 +12,7 @@ */ package org.eclipse.lemminx; -import static org.eclipse.lemminx.services.format.TextEditUtils.applyEdits; +import static org.eclipse.lemminx.utils.TextEditUtils.applyEdits; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertIterableEquals; @@ -28,6 +28,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.function.Consumer; @@ -56,7 +57,6 @@ import org.eclipse.lemminx.services.XMLLanguageService; import org.eclipse.lemminx.services.extensions.diagnostics.IXMLErrorCode; import org.eclipse.lemminx.services.extensions.save.AbstractSaveContext; -import org.eclipse.lemminx.services.format.TextEditUtils; import org.eclipse.lemminx.settings.SharedSettings; import org.eclipse.lemminx.settings.XMLCodeLensSettings; import org.eclipse.lemminx.settings.XMLSymbolSettings; @@ -310,7 +310,7 @@ public static void testCompletionApply(String value, CompletionItem completionIt if (completionItem.getAdditionalTextEdits() != null) { edits.addAll(completionItem.getAdditionalTextEdits()); } - String actual = TextEditUtils.applyEdits(document, edits); + String actual = applyEdits(document, edits); assertEquals(expected, actual); } @@ -1786,7 +1786,13 @@ public static void assertRename(XMLLanguageService languageService, String value } WorkspaceEdit workspaceEdit = languageService.doRename(document, position, newText, () -> { }); - List actualEdits = workspaceEdit.getChanges().get(fileURI); + final String uri = fileURI; + Optional documentChange = workspaceEdit.getDocumentChanges() + .stream().filter(Either::isLeft) + .filter(e -> uri.equals(e.getLeft().getTextDocument().getUri())) + .map(Either::getLeft).findFirst(); + List actualEdits = documentChange.isPresent() ? + documentChange.get().getEdits() : Collections.emptyList(); assertArrayEquals(expectedEdits.toArray(), actualEdits.toArray()); } @@ -1937,7 +1943,7 @@ public static void assertSurroundWith(String xml, SurroundWithKind kind, boolean snippetsSupported) .get(); - String actual = TextEditUtils.applyEdits(document, Arrays.asList(response.getStart(), response.getEnd())); + String actual = applyEdits(document, Arrays.asList(response.getStart(), response.getEnd())); assertEquals(expected, actual); } diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/extensions/ErrorParticipantLanguageServiceTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/extensions/ErrorParticipantLanguageServiceTest.java index 0a8ee7c79..90fe71834 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/extensions/ErrorParticipantLanguageServiceTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/extensions/ErrorParticipantLanguageServiceTest.java @@ -50,6 +50,7 @@ import org.eclipse.lemminx.services.DocumentSymbolsResult; import org.eclipse.lemminx.services.SymbolInformationResult; import org.eclipse.lemminx.services.XMLLanguageService; +import org.eclipse.lemminx.services.extensions.IRenameResponse; import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionParticipant; import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionRequest; import org.eclipse.lemminx.services.extensions.completion.ICompletionParticipant; @@ -78,7 +79,6 @@ import org.eclipse.lsp4j.Range; import org.eclipse.lsp4j.SymbolInformation; import org.eclipse.lsp4j.SymbolKind; -import org.eclipse.lsp4j.TextEdit; import org.eclipse.lsp4j.jsonrpc.CancelChecker; import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.junit.jupiter.api.Test; @@ -302,7 +302,7 @@ public Either prepareRename(IPrepareRenameRequest re } @Override - public void doRename(IRenameRequest request, List locations, CancelChecker cancelChecker) { + public void doRename(IRenameRequest request, IRenameResponse renameResponse, CancelChecker cancelChecker) { throw new RuntimeException("This participant is broken"); } }); diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/format/LeftWhitespacesOffsetTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/format/LeftWhitespacesOffsetTest.java index 845241518..5567c5254 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/format/LeftWhitespacesOffsetTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/format/LeftWhitespacesOffsetTest.java @@ -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 @@ -14,6 +14,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import org.eclipse.lemminx.AbstractCacheBasedTest; +import org.eclipse.lemminx.utils.TextEditUtils; import org.junit.jupiter.api.Test; /** diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/format/TextEditUtilsTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/format/TextEditUtilsTest.java index 2092c916b..2557ca5fb 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/format/TextEditUtilsTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/format/TextEditUtilsTest.java @@ -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 @@ -18,6 +18,7 @@ import org.eclipse.lemminx.AbstractCacheBasedTest; import org.eclipse.lemminx.commons.TextDocument; +import org.eclipse.lemminx.utils.TextEditUtils; import org.eclipse.lsp4j.TextEdit; import org.junit.jupiter.api.Test;