From 9445851c8c414e27b2b867b63e4f073d5c48643f Mon Sep 17 00:00:00 2001 From: Arun Venmany Date: Thu, 17 Oct 2024 19:26:59 +0530 Subject: [PATCH 1/8] Fix for platform showing invalid quick fix Signed-off-by: Arun Venmany --- .../lemminx/LibertyCodeActionParticipant.java | 2 + .../lemminx/LibertyDiagnosticParticipant.java | 5 +- .../lemminx/codeactions/ReplacePlatform.java | 84 +++++++++++++++++++ .../io/openliberty/LibertyDiagnosticTest.java | 27 +++++- 4 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java diff --git a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/LibertyCodeActionParticipant.java b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/LibertyCodeActionParticipant.java index 07befb11..366268bd 100644 --- a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/LibertyCodeActionParticipant.java +++ b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/LibertyCodeActionParticipant.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Map; +import io.openliberty.tools.langserver.lemminx.codeactions.ReplacePlatform; import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionParticipant; import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionRequest; import org.eclipse.lsp4j.CodeAction; @@ -58,6 +59,7 @@ private void registerCodeActions() { codeActionParticipants.put(LibertyDiagnosticParticipant.NOT_OPTIONAL_CODE, new EditAttribute()); codeActionParticipants.put(LibertyDiagnosticParticipant.IMPLICIT_NOT_OPTIONAL_CODE, new AddAttribute()); codeActionParticipants.put(LibertyDiagnosticParticipant.INCORRECT_FEATURE_CODE, new ReplaceFeature()); + codeActionParticipants.put(LibertyDiagnosticParticipant.INCORRECT_PLATFORM_CODE, new ReplacePlatform()); codeActionParticipants.put(LibertyDiagnosticParticipant.MISSING_CONFIGURED_FEATURE_CODE, new AddFeature()); codeActionParticipants.put(LibertyDiagnosticParticipant.IS_FILE_NOT_DIR_CODE, new RemoveTrailingSlash()); codeActionParticipants.put(LibertyDiagnosticParticipant.Is_DIR_NOT_FILE_CODE, new AddTrailingSlash()); diff --git a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/LibertyDiagnosticParticipant.java b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/LibertyDiagnosticParticipant.java index 362de91b..2b05aa37 100644 --- a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/LibertyDiagnosticParticipant.java +++ b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/LibertyDiagnosticParticipant.java @@ -70,7 +70,8 @@ public class LibertyDiagnosticParticipant implements IDiagnosticsParticipant { public static final String Is_DIR_NOT_FILE_CODE = "is_dir_not_file"; public static final String INCORRECT_FEATURE_CODE = "incorrect_feature"; - + public static final String INCORRECT_PLATFORM_CODE = "incorrect_platform"; + @Override public void doDiagnostics(DOMDocument domDocument, List diagnostics, XMLValidationSettings validationSettings, CancelChecker cancelChecker) { @@ -386,7 +387,7 @@ private void validatePlatform(DOMDocument domDocument, List list, DO Range range = XMLPositionUtility.createRange(featureTextNode.getStart(), featureTextNode.getEnd(), domDocument); String message = "ERROR: The platform \"" + platformName + "\" does not exist."; - list.add(new Diagnostic(range, message, DiagnosticSeverity.Error, LIBERTY_LEMMINX_SOURCE, INCORRECT_FEATURE_CODE)); + list.add(new Diagnostic(range, message, DiagnosticSeverity.Error, LIBERTY_LEMMINX_SOURCE, INCORRECT_PLATFORM_CODE)); } // if this exact platform already exists, or another version of this feature already exists, then show a diagnostic else { diff --git a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java new file mode 100644 index 00000000..ee4bd465 --- /dev/null +++ b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java @@ -0,0 +1,84 @@ +/******************************************************************************* +* Copyright (c) 2024 IBM Corporation and others. +* +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License v. 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0. +* +* SPDX-License-Identifier: EPL-2.0 +* +* Contributors: +* IBM Corporation - initial API and implementation +*******************************************************************************/ + +package io.openliberty.tools.langserver.lemminx.codeactions; + +import io.openliberty.tools.langserver.lemminx.LibertyExtension; +import io.openliberty.tools.langserver.lemminx.data.LibertyRuntime; +import io.openliberty.tools.langserver.lemminx.services.FeatureService; +import io.openliberty.tools.langserver.lemminx.services.SettingsService; +import io.openliberty.tools.langserver.lemminx.util.LibertyUtils; +import org.eclipse.lemminx.commons.CodeActionFactory; +import org.eclipse.lemminx.dom.DOMDocument; +import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionParticipant; +import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionRequest; +import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.jsonrpc.CancelChecker; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Set; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +public class ReplacePlatform implements ICodeActionParticipant { + private static final Logger LOGGER = Logger.getLogger(LibertyExtension.class.getName()); + + @Override + public void doCodeAction(ICodeActionRequest request, List codeActions, CancelChecker cancelChecker) { + Diagnostic diagnostic = request.getDiagnostic(); + DOMDocument document = request.getDocument(); + try { + // Get a list of platforms that partially match the specified invalid platform. + // Create a code action to replace the invalid platform with each possible valid platform. + // First, get the invalid platform. + String invalidPlatform = document.findNodeAt(document.offsetAt(diagnostic.getRange().getEnd())).getTextContent(); + + final boolean replacePlatformName = invalidPlatform != null && !invalidPlatform.isBlank(); + // strip off version number after the - so that we can provide all possible valid versions of a platform for completion + final String platformNameToReplace = replacePlatformName && invalidPlatform.contains("-") ? invalidPlatform.substring(0, invalidPlatform.lastIndexOf("-")) : invalidPlatform; + + if (replacePlatformName) { + LibertyRuntime runtimeInfo = LibertyUtils.getLibertyRuntimeInfo(document); + Set allPlatforms = getAllPlatforms(runtimeInfo, document); + + List filteredPlatforms = allPlatforms.stream(). + filter(it -> it.contains(platformNameToReplace)) + .collect(Collectors.toList()); + // if no matching platform is found, show all platforms as quick fix actions + List replacementPlatforms = filteredPlatforms.isEmpty() ? new ArrayList<>(allPlatforms) : filteredPlatforms; + replacementPlatforms.sort(Comparator.naturalOrder()); + for (String nextPlatform : replacementPlatforms) { + if (!nextPlatform.equals(platformNameToReplace)) { + String title = "Replace platform with " + nextPlatform; + codeActions.add(CodeActionFactory.replace(title, diagnostic.getRange(), nextPlatform, document.getTextDocument(), diagnostic)); + } + } + } + } catch (Exception e) { + // BadLocationException not expected + LOGGER.warning("Could not generate code action for replace platform: " + e); + } + } + + private static Set getAllPlatforms(LibertyRuntime runtimeInfo, DOMDocument document) { + String libertyVersion = runtimeInfo == null ? null : runtimeInfo.getRuntimeVersion(); + String libertyRuntime = runtimeInfo == null ? null : runtimeInfo.getRuntimeType(); + + final int requestDelay = SettingsService.getInstance().getRequestDelay(); + return FeatureService.getInstance().getAllPlatforms(libertyVersion, libertyRuntime, requestDelay, + document.getDocumentURI()); + } +} diff --git a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java index 7dbf71fd..b8af3679 100644 --- a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java +++ b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java @@ -434,7 +434,7 @@ public void testInvalidPlatformDiagnostic() throws BadLocationException { "", // " ", // " batch-1.0", // - " jaX", // + " javaee", // " javaee-7.0", // " ", // " javaee-7.0", // @@ -444,9 +444,9 @@ public void testInvalidPlatformDiagnostic() throws BadLocationException { "" // ); Diagnostic invalid1 = new Diagnostic(); - invalid1.setRange(r(3, 25, 3, 28)); - invalid1.setCode(LibertyDiagnosticParticipant.INCORRECT_FEATURE_CODE); - invalid1.setMessage("ERROR: The platform \"jaX\" does not exist."); + invalid1.setRange(r(3, 25, 3, 31)); + invalid1.setCode(LibertyDiagnosticParticipant.INCORRECT_PLATFORM_CODE); + invalid1.setMessage("ERROR: The platform \"javaee\" does not exist."); Diagnostic invalid2 = new Diagnostic(); invalid2.setRange(r(6, 25, 6, 35)); @@ -464,6 +464,25 @@ public void testInvalidPlatformDiagnostic() throws BadLocationException { XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLURI, invalid1, invalid2, invalid3, invalid4); + //expecting code action to show all javaee platforms + List featuresStartWithJavaEE = new ArrayList<>(); + featuresStartWithJavaEE.add("javaee-6.0"); + featuresStartWithJavaEE.add("javaee-7.0"); + featuresStartWithJavaEE.add("javaee-8.0"); + Collections.sort(featuresStartWithJavaEE); + + List codeActions = new ArrayList<>(); + for (String nextFeature: featuresStartWithJavaEE) { + TextEdit texted = te(invalid1.getRange().getStart().getLine(), invalid1.getRange().getStart().getCharacter(), + invalid1.getRange().getEnd().getLine(), invalid1.getRange().getEnd().getCharacter(), nextFeature); + CodeAction invalidCodeAction = ca(invalid1, texted); + + codeActions.add(invalidCodeAction); + } + + XMLAssert.testCodeActionsFor(serverXML, invalid1, codeActions.get(0), codeActions.get(1), + codeActions.get(2)); + } @Test From dc22209372f32b88c183e965209674229ffa2214 Mon Sep 17 00:00:00 2001 From: Arun Venmany Date: Mon, 21 Oct 2024 16:53:15 +0530 Subject: [PATCH 2/8] added filters in platform quick fix to remove all existing platforms and conflicting platforms Signed-off-by: Arun Venmany --- .../lemminx/codeactions/ReplacePlatform.java | 63 ++++++-- .../lemminx/services/FeatureService.java | 37 +++++ .../io/openliberty/LibertyDiagnosticTest.java | 135 ++++++++++++++---- 3 files changed, 197 insertions(+), 38 deletions(-) diff --git a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java index ee4bd465..7df21d7d 100644 --- a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java +++ b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java @@ -17,6 +17,7 @@ import io.openliberty.tools.langserver.lemminx.data.LibertyRuntime; import io.openliberty.tools.langserver.lemminx.services.FeatureService; import io.openliberty.tools.langserver.lemminx.services.SettingsService; +import io.openliberty.tools.langserver.lemminx.util.LibertyConstants; import io.openliberty.tools.langserver.lemminx.util.LibertyUtils; import org.eclipse.lemminx.commons.CodeActionFactory; import org.eclipse.lemminx.dom.DOMDocument; @@ -29,9 +30,9 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.logging.Logger; -import java.util.stream.Collectors; public class ReplacePlatform implements ICodeActionParticipant { private static final Logger LOGGER = Logger.getLogger(LibertyExtension.class.getName()); @@ -53,14 +54,19 @@ public void doCodeAction(ICodeActionRequest request, List codeAction if (replacePlatformName) { LibertyRuntime runtimeInfo = LibertyUtils.getLibertyRuntimeInfo(document); Set allPlatforms = getAllPlatforms(runtimeInfo, document); - - List filteredPlatforms = allPlatforms.stream(). - filter(it -> it.contains(platformNameToReplace)) - .collect(Collectors.toList()); + List existingPlatforms = FeatureService.getInstance().collectExistingPlatforms(document, platformNameToReplace); + List replacementPlatforms = getReplacementPlatforms(document, + platformNameToReplace, allPlatforms, existingPlatforms); + // check for conflicting platforms for already existing platforms. remove them from quick fix items + List replacementPlatformsWithoutConflicts = getReplacementPlatformsWithoutConflicts(replacementPlatforms, existingPlatforms); + // filter with entered word + List filteredPlatforms = replacementPlatformsWithoutConflicts.stream(). + filter(it -> it.toLowerCase().startsWith(platformNameToReplace.toLowerCase())) + .toList(); // if no matching platform is found, show all platforms as quick fix actions - List replacementPlatforms = filteredPlatforms.isEmpty() ? new ArrayList<>(allPlatforms) : filteredPlatforms; - replacementPlatforms.sort(Comparator.naturalOrder()); - for (String nextPlatform : replacementPlatforms) { + List selectedPlatforms = filteredPlatforms.isEmpty() ? new ArrayList<>(replacementPlatformsWithoutConflicts) : filteredPlatforms; + + for (String nextPlatform : selectedPlatforms) { if (!nextPlatform.equals(platformNameToReplace)) { String title = "Replace platform with " + nextPlatform; codeActions.add(CodeActionFactory.replace(title, diagnostic.getRange(), nextPlatform, document.getTextDocument(), diagnostic)); @@ -73,6 +79,47 @@ public void doCodeAction(ICodeActionRequest request, List codeAction } } + /** + * get list of existing platforms to exclude from list of possible replacements + * also exclude any platform with a different version that matches an existing platform + * @param document DOM document + * @param platformNameToReplace platform for replacing + * @param allPlatforms all platforms + * @return replacement platforms + */ + private static List getReplacementPlatforms(DOMDocument document, String platformNameToReplace, Set allPlatforms, List existingPlatforms) { + List existingPlatformsWithoutVersion = existingPlatforms.stream().map(p->LibertyUtils.stripVersion(p).toLowerCase()).toList(); + return allPlatforms.stream().filter( + p -> !existingPlatformsWithoutVersion.contains(LibertyUtils.stripVersion(p)) + ).sorted(Comparator.naturalOrder()).toList(); + } + + /** + * find and remove conflicting platforms + * @param replacementPlatforms replacement platform list + * @param existingPlatforms existing platforms in doc + * @return non-conflicting platforms + */ + private static List getReplacementPlatformsWithoutConflicts(List replacementPlatforms, List existingPlatforms) { + List replacementPlatformsWithoutConflicts=new ArrayList<>(); + replacementPlatforms.forEach( + p->{ + String pWithoutVersion = LibertyUtils.stripVersion(p); + + Optional conflictingPlatform = existingPlatforms.stream().filter( + existingPlatform -> { + String conflictingPlatformName = LibertyConstants.conflictingPlatforms.get(pWithoutVersion); + return conflictingPlatformName != null && existingPlatform.startsWith(conflictingPlatformName); + } + ).findFirst(); + if(conflictingPlatform.isEmpty()){ + replacementPlatformsWithoutConflicts.add(p); + } + } + ); + return replacementPlatformsWithoutConflicts; + } + private static Set getAllPlatforms(LibertyRuntime runtimeInfo, DOMDocument document) { String libertyVersion = runtimeInfo == null ? null : runtimeInfo.getRuntimeVersion(); String libertyRuntime = runtimeInfo == null ? null : runtimeInfo.getRuntimeType(); diff --git a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/services/FeatureService.java b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/services/FeatureService.java index 6bc62a20..83094c5c 100644 --- a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/services/FeatureService.java +++ b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/services/FeatureService.java @@ -33,6 +33,7 @@ import java.util.logging.Logger; import io.openliberty.tools.langserver.lemminx.models.feature.FeatureTolerate; +import org.eclipse.lemminx.dom.DOMDocument; import org.eclipse.lemminx.dom.DOMNode; import org.eclipse.lemminx.uriresolver.CacheResourcesManager; import org.eclipse.lemminx.uriresolver.CacheResourcesManager.ResourceToDeploy; @@ -683,4 +684,40 @@ private void addRequiredFeatureNames(Feature feature, Set requiredFeatur requiredFeatureNames.add(extractedFeatureName); } } + /** + * Returns the platform names specified in the featureManager element in lower case, + * excluding the currentPlatformName if specified. + * @param document DOM document + * @param currentPlatformName current platform name + * @return all platforms in document + */ + public List collectExistingPlatforms(DOMDocument document, String currentPlatformName) { + List includedPlatforms = new ArrayList<>(); + List nodes = document.getDocumentElement().getChildren(); + DOMNode featureManager = null; + + for (DOMNode node : nodes) { + if (LibertyConstants.FEATURE_MANAGER_ELEMENT.equals(node.getNodeName())) { + featureManager = node; + break; + } + } + if (featureManager == null) { + return includedPlatforms; + } + + List platforms = featureManager.getChildren(); + for (DOMNode platformNode : platforms) { + DOMNode platformTextNode = (DOMNode) platformNode.getChildNodes().item(0); + // skip nodes that do not have any text value (ie. comments) + if (platformNode.getNodeName().equals(LibertyConstants.PLATFORM_ELEMENT) && platformTextNode != null) { + String platformName = platformTextNode.getTextContent(); + String platformNameLowerCase = platformName.toLowerCase(); + if ((!platformNameLowerCase.equalsIgnoreCase(currentPlatformName))) { + includedPlatforms.add(platformNameLowerCase); + } + } + } + return includedPlatforms; + } } diff --git a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java index b8af3679..c09d3c88 100644 --- a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java +++ b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java @@ -186,7 +186,7 @@ public void testDiagnosticsForInclude() throws IOException, BadLocationException " ", // "" ); - + // Diagnostic location1 = new Diagnostic(); File serverXMLFile = new File("src/test/resources/server.xml"); assertFalse(serverXMLFile.exists()); @@ -231,7 +231,7 @@ public void testDiagnosticsForInclude() throws IOException, BadLocationException fileIsDir.setCode("is_dir_not_file"); fileIsDir.setMessage("Path specified a file, but resource exists as a directory. Please add a trailing slash."); - XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLFile.toURI().toString(), + XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLFile.toURI().toString(), not_xml, multi_liner, not_optional, missing_xml, optional_not_defined, missing_xml2, dirIsFile, fileIsDir); @@ -247,7 +247,7 @@ public void testDiagnosticsForInclude() throws IOException, BadLocationException CodeAction fileIsDirCodeAction = ca(fileIsDir, fileIsDirTextEdit); - XMLAssert.testCodeActionsFor(serverXML, dirIsFile, dirIsFileCodeAction); + XMLAssert.testCodeActionsFor(serverXML, dirIsFile, dirIsFileCodeAction); XMLAssert.testCodeActionsFor(serverXML, fileIsDir, fileIsDirCodeAction); } @@ -268,7 +268,7 @@ public void testDiagnosticsForIncludeWindows() throws BadLocationException { " ", // "" ); - + // Diagnostic location1 = new Diagnostic(); File serverXMLFile = new File("src/test/resources/server.xml"); assertFalse(serverXMLFile.exists()); @@ -285,7 +285,7 @@ public void testDiagnosticsForIncludeWindows() throws BadLocationException { fileIsDir.setCode("is_dir_not_file"); fileIsDir.setMessage("Path specified a file, but resource exists as a directory. Please add a trailing slash."); - XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLFile.toURI().toString(), + XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLFile.toURI().toString(), dirIsFile, fileIsDir); String fixedFilePath = "location=\"\\empty_server.xml\""; @@ -298,7 +298,7 @@ public void testDiagnosticsForIncludeWindows() throws BadLocationException { fileIsDir.getRange().getEnd().getLine(), fileIsDir.getRange().getEnd().getCharacter(), fixedDirPath); CodeAction fileIsDirCodeAction = ca(fileIsDir, fileIsDirTextEdit); - XMLAssert.testCodeActionsFor(serverXML, dirIsFile, dirIsFileCodeAction); + XMLAssert.testCodeActionsFor(serverXML, dirIsFile, dirIsFileCodeAction); XMLAssert.testCodeActionsFor(serverXML, fileIsDir, fileIsDirCodeAction); } @@ -307,7 +307,7 @@ public void testDiagnosticsForIncludeWindows() throws BadLocationException { public void testConfigElementMissingFeatureManager() throws JAXBException { assertTrue(featureList.exists()); FeatureService.getInstance().readFeaturesFromFeatureListFile(new ArrayList(), libWorkspace, featureList); - + String serverXml = ""; // Temporarily disabling config element diagnostics if featureManager element is missing (until issue 230 is addressed) // Diagnostic config_for_missing_feature = new Diagnostic(); @@ -364,7 +364,7 @@ public void testConfigElementMissingFeatureUsingCachedFeaturelist() throws JAXBE TextDocumentEdit textDoc = tde(sampleserverXMLURI, 0, texted); WorkspaceEdit workspaceEdit = new WorkspaceEdit(Collections.singletonList(Either.forLeft(textDoc))); - + invalidCodeAction.setEdit(workspaceEdit); codeActions.add(invalidCodeAction); } @@ -434,7 +434,7 @@ public void testInvalidPlatformDiagnostic() throws BadLocationException { "", // " ", // " batch-1.0", // - " javaee", // + " jaX", // " javaee-7.0", // " ", // " javaee-7.0", // @@ -444,9 +444,9 @@ public void testInvalidPlatformDiagnostic() throws BadLocationException { "" // ); Diagnostic invalid1 = new Diagnostic(); - invalid1.setRange(r(3, 25, 3, 31)); + invalid1.setRange(r(3, 25, 3, 28)); invalid1.setCode(LibertyDiagnosticParticipant.INCORRECT_PLATFORM_CODE); - invalid1.setMessage("ERROR: The platform \"javaee\" does not exist."); + invalid1.setMessage("ERROR: The platform \"jaX\" does not exist."); Diagnostic invalid2 = new Diagnostic(); invalid2.setRange(r(6, 25, 6, 35)); @@ -464,25 +464,6 @@ public void testInvalidPlatformDiagnostic() throws BadLocationException { XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLURI, invalid1, invalid2, invalid3, invalid4); - //expecting code action to show all javaee platforms - List featuresStartWithJavaEE = new ArrayList<>(); - featuresStartWithJavaEE.add("javaee-6.0"); - featuresStartWithJavaEE.add("javaee-7.0"); - featuresStartWithJavaEE.add("javaee-8.0"); - Collections.sort(featuresStartWithJavaEE); - - List codeActions = new ArrayList<>(); - for (String nextFeature: featuresStartWithJavaEE) { - TextEdit texted = te(invalid1.getRange().getStart().getLine(), invalid1.getRange().getStart().getCharacter(), - invalid1.getRange().getEnd().getLine(), invalid1.getRange().getEnd().getCharacter(), nextFeature); - CodeAction invalidCodeAction = ca(invalid1, texted); - - codeActions.add(invalidCodeAction); - } - - XMLAssert.testCodeActionsFor(serverXML, invalid1, codeActions.get(0), codeActions.get(1), - codeActions.get(2)); - } @Test @@ -769,4 +750,98 @@ public void testUniquenessForNameChangedFeatureDiagnostic() throws BadLocationEx XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLURI, invalid); } + + @Test + public void testInvalidPlatformDiagnosticWithCodeCompletion() throws BadLocationException { + + String serverXML = String.join(newLine, // + "", // + " ", // + " javaEE", // + " ", // + "" // + ); + Diagnostic invalid1 = new Diagnostic(); + invalid1.setRange(r(2, 25, 2, 31)); + invalid1.setCode(LibertyDiagnosticParticipant.INCORRECT_PLATFORM_CODE); + invalid1.setMessage("ERROR: The platform \"javaEE\" does not exist."); + + XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLURI, + invalid1); + //expecting code action to show all javaee platforms ignoring input case + List featuresStartWithJavaEE = new ArrayList<>(); + featuresStartWithJavaEE.add("javaee-6.0"); + featuresStartWithJavaEE.add("javaee-7.0"); + featuresStartWithJavaEE.add("javaee-8.0"); + Collections.sort(featuresStartWithJavaEE); + + List codeActions = new ArrayList<>(); + for (String nextFeature : featuresStartWithJavaEE) { + TextEdit texted = te(invalid1.getRange().getStart().getLine(), invalid1.getRange().getStart().getCharacter(), + invalid1.getRange().getEnd().getLine(), invalid1.getRange().getEnd().getCharacter(), nextFeature); + CodeAction invalidCodeAction = ca(invalid1, texted); + + codeActions.add(invalidCodeAction); + } + + XMLAssert.testCodeActionsFor(serverXML, invalid1, codeActions.get(0), codeActions.get(1), + codeActions.get(2)); + + serverXML = String.join(newLine, // + "", // + " ", // + " batch-1.0", // + " ja", // + " javaee-7.0", // + " ", // + "" // + ); + invalid1 = new Diagnostic(); + invalid1.setRange(r(3, 25, 3, 27)); + invalid1.setCode(LibertyDiagnosticParticipant.INCORRECT_PLATFORM_CODE); + invalid1.setMessage("ERROR: The platform \"ja\" does not exist."); + + XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLURI, + invalid1); + // expecting code action to show all microprofile platforms only since + // 1. javaee is already included + // 2. jakartaee is conflicting with javaee platforms + List microProfilePlatforms = new ArrayList<>(); + microProfilePlatforms.add("microProfile-1.0"); + microProfilePlatforms.add("microProfile-1.2"); + microProfilePlatforms.add("microProfile-1.3"); + microProfilePlatforms.add("microProfile-1.4"); + microProfilePlatforms.add("microProfile-2.0"); + microProfilePlatforms.add("microProfile-2.1"); + microProfilePlatforms.add("microProfile-2.2"); + microProfilePlatforms.add("microProfile-3.0"); + microProfilePlatforms.add("microProfile-3.2"); + microProfilePlatforms.add("microProfile-3.3"); + microProfilePlatforms.add("microProfile-4.0"); + microProfilePlatforms.add("microProfile-4.1"); + microProfilePlatforms.add("microProfile-5.0"); + microProfilePlatforms.add("microProfile-6.0"); + microProfilePlatforms.add("microProfile-6.1"); + microProfilePlatforms.add("microProfile-7.0"); + Collections.sort(microProfilePlatforms); + + codeActions = new ArrayList<>(); + for (String nextFeature : microProfilePlatforms) { + TextEdit texted = te(invalid1.getRange().getStart().getLine(), invalid1.getRange().getStart().getCharacter(), + invalid1.getRange().getEnd().getLine(), invalid1.getRange().getEnd().getCharacter(), nextFeature); + CodeAction invalidCodeAction = ca(invalid1, texted); + + codeActions.add(invalidCodeAction); + } + + XMLAssert.testCodeActionsFor(serverXML, invalid1, codeActions.get(0), + codeActions.get(1), codeActions.get(2), + codeActions.get(3), codeActions.get(4), + codeActions.get(5), codeActions.get(6), + codeActions.get(7), codeActions.get(8), + codeActions.get(9), codeActions.get(10), + codeActions.get(11), codeActions.get(12), + codeActions.get(13), codeActions.get(14), + codeActions.get(15)); + } } \ No newline at end of file From 7ab2fb8f3630e242000a8e2df8e8eda5f673dfde Mon Sep 17 00:00:00 2001 From: Arun Venmany Date: Mon, 21 Oct 2024 19:02:36 +0530 Subject: [PATCH 3/8] removed code to show all available platforms if entered key is not matching Signed-off-by: Arun Venmany --- .../lemminx/codeactions/ReplacePlatform.java | 9 ++--- .../io/openliberty/LibertyDiagnosticTest.java | 39 +------------------ 2 files changed, 5 insertions(+), 43 deletions(-) diff --git a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java index 7df21d7d..d3dce713 100644 --- a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java +++ b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java @@ -61,12 +61,9 @@ public void doCodeAction(ICodeActionRequest request, List codeAction List replacementPlatformsWithoutConflicts = getReplacementPlatformsWithoutConflicts(replacementPlatforms, existingPlatforms); // filter with entered word List filteredPlatforms = replacementPlatformsWithoutConflicts.stream(). - filter(it -> it.toLowerCase().startsWith(platformNameToReplace.toLowerCase())) + filter(it -> it.toLowerCase().contains(platformNameToReplace.toLowerCase())) .toList(); - // if no matching platform is found, show all platforms as quick fix actions - List selectedPlatforms = filteredPlatforms.isEmpty() ? new ArrayList<>(replacementPlatformsWithoutConflicts) : filteredPlatforms; - - for (String nextPlatform : selectedPlatforms) { + for (String nextPlatform : filteredPlatforms) { if (!nextPlatform.equals(platformNameToReplace)) { String title = "Replace platform with " + nextPlatform; codeActions.add(CodeActionFactory.replace(title, diagnostic.getRange(), nextPlatform, document.getTextDocument(), diagnostic)); @@ -109,7 +106,7 @@ private static List getReplacementPlatformsWithoutConflicts(List Optional conflictingPlatform = existingPlatforms.stream().filter( existingPlatform -> { String conflictingPlatformName = LibertyConstants.conflictingPlatforms.get(pWithoutVersion); - return conflictingPlatformName != null && existingPlatform.startsWith(conflictingPlatformName); + return conflictingPlatformName != null && existingPlatform.contains(conflictingPlatformName); } ).findFirst(); if(conflictingPlatform.isEmpty()){ diff --git a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java index c09d3c88..8a24fd44 100644 --- a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java +++ b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java @@ -803,45 +803,10 @@ public void testInvalidPlatformDiagnosticWithCodeCompletion() throws BadLocation XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLURI, invalid1); - // expecting code action to show all microprofile platforms only since + // expecting code action to show no platforms since // 1. javaee is already included // 2. jakartaee is conflicting with javaee platforms - List microProfilePlatforms = new ArrayList<>(); - microProfilePlatforms.add("microProfile-1.0"); - microProfilePlatforms.add("microProfile-1.2"); - microProfilePlatforms.add("microProfile-1.3"); - microProfilePlatforms.add("microProfile-1.4"); - microProfilePlatforms.add("microProfile-2.0"); - microProfilePlatforms.add("microProfile-2.1"); - microProfilePlatforms.add("microProfile-2.2"); - microProfilePlatforms.add("microProfile-3.0"); - microProfilePlatforms.add("microProfile-3.2"); - microProfilePlatforms.add("microProfile-3.3"); - microProfilePlatforms.add("microProfile-4.0"); - microProfilePlatforms.add("microProfile-4.1"); - microProfilePlatforms.add("microProfile-5.0"); - microProfilePlatforms.add("microProfile-6.0"); - microProfilePlatforms.add("microProfile-6.1"); - microProfilePlatforms.add("microProfile-7.0"); - Collections.sort(microProfilePlatforms); - - codeActions = new ArrayList<>(); - for (String nextFeature : microProfilePlatforms) { - TextEdit texted = te(invalid1.getRange().getStart().getLine(), invalid1.getRange().getStart().getCharacter(), - invalid1.getRange().getEnd().getLine(), invalid1.getRange().getEnd().getCharacter(), nextFeature); - CodeAction invalidCodeAction = ca(invalid1, texted); - - codeActions.add(invalidCodeAction); - } - XMLAssert.testCodeActionsFor(serverXML, invalid1, codeActions.get(0), - codeActions.get(1), codeActions.get(2), - codeActions.get(3), codeActions.get(4), - codeActions.get(5), codeActions.get(6), - codeActions.get(7), codeActions.get(8), - codeActions.get(9), codeActions.get(10), - codeActions.get(11), codeActions.get(12), - codeActions.get(13), codeActions.get(14), - codeActions.get(15)); + XMLAssert.testCodeActionsFor(serverXML, invalid1); } } \ No newline at end of file From a70f81ccd19f63f7d856e9fbb09947edc8dddaba Mon Sep 17 00:00:00 2001 From: Arun Venmany Date: Tue, 22 Oct 2024 10:24:47 +0530 Subject: [PATCH 4/8] checked for lowercase issues and re organized lowercase code. added tests for microprofile Signed-off-by: Arun Venmany --- .../lemminx/codeactions/ReplacePlatform.java | 16 +++--- .../io/openliberty/LibertyDiagnosticTest.java | 54 ++++++++++++++++++- 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java index d3dce713..22d98a9d 100644 --- a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java +++ b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/ReplacePlatform.java @@ -55,8 +55,8 @@ public void doCodeAction(ICodeActionRequest request, List codeAction LibertyRuntime runtimeInfo = LibertyUtils.getLibertyRuntimeInfo(document); Set allPlatforms = getAllPlatforms(runtimeInfo, document); List existingPlatforms = FeatureService.getInstance().collectExistingPlatforms(document, platformNameToReplace); - List replacementPlatforms = getReplacementPlatforms(document, - platformNameToReplace, allPlatforms, existingPlatforms); + List replacementPlatforms = getReplacementPlatforms( + allPlatforms, existingPlatforms); // check for conflicting platforms for already existing platforms. remove them from quick fix items List replacementPlatformsWithoutConflicts = getReplacementPlatformsWithoutConflicts(replacementPlatforms, existingPlatforms); // filter with entered word @@ -79,15 +79,13 @@ public void doCodeAction(ICodeActionRequest request, List codeAction /** * get list of existing platforms to exclude from list of possible replacements * also exclude any platform with a different version that matches an existing platform - * @param document DOM document - * @param platformNameToReplace platform for replacing * @param allPlatforms all platforms * @return replacement platforms */ - private static List getReplacementPlatforms(DOMDocument document, String platformNameToReplace, Set allPlatforms, List existingPlatforms) { - List existingPlatformsWithoutVersion = existingPlatforms.stream().map(p->LibertyUtils.stripVersion(p).toLowerCase()).toList(); + private static List getReplacementPlatforms(Set allPlatforms, List existingPlatforms) { + List existingPlatformsWithoutVersionLowerCase = existingPlatforms.stream().map(p->LibertyUtils.stripVersion(p).toLowerCase()).toList(); return allPlatforms.stream().filter( - p -> !existingPlatformsWithoutVersion.contains(LibertyUtils.stripVersion(p)) + p -> !existingPlatformsWithoutVersionLowerCase.contains(LibertyUtils.stripVersion(p.toLowerCase())) ).sorted(Comparator.naturalOrder()).toList(); } @@ -101,12 +99,12 @@ private static List getReplacementPlatformsWithoutConflicts(List List replacementPlatformsWithoutConflicts=new ArrayList<>(); replacementPlatforms.forEach( p->{ - String pWithoutVersion = LibertyUtils.stripVersion(p); + String pWithoutVersion = LibertyUtils.stripVersion(p.toLowerCase()); Optional conflictingPlatform = existingPlatforms.stream().filter( existingPlatform -> { String conflictingPlatformName = LibertyConstants.conflictingPlatforms.get(pWithoutVersion); - return conflictingPlatformName != null && existingPlatform.contains(conflictingPlatformName); + return conflictingPlatformName != null && existingPlatform.toLowerCase().contains(conflictingPlatformName); } ).findFirst(); if(conflictingPlatform.isEmpty()){ diff --git a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java index 8a24fd44..42b3cd4e 100644 --- a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java +++ b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java @@ -801,12 +801,64 @@ public void testInvalidPlatformDiagnosticWithCodeCompletion() throws BadLocation invalid1.setCode(LibertyDiagnosticParticipant.INCORRECT_PLATFORM_CODE); invalid1.setMessage("ERROR: The platform \"ja\" does not exist."); + XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLURI, + invalid1); + + serverXML = String.join(newLine, // + "", // + " ", // + " batch-1.0", // + " miCroP", // + " javaee-7.0", // + " ", // + "" // + ); + invalid1 = new Diagnostic(); + invalid1.setRange(r(3, 25, 3, 31)); + invalid1.setCode(LibertyDiagnosticParticipant.INCORRECT_PLATFORM_CODE); + invalid1.setMessage("ERROR: The platform \"miCroP\" does not exist."); + XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLURI, invalid1); // expecting code action to show no platforms since // 1. javaee is already included // 2. jakartaee is conflicting with javaee platforms + List microProfilePlatforms = new ArrayList<>(); + microProfilePlatforms.add("microProfile-1.0"); + microProfilePlatforms.add("microProfile-1.2"); + microProfilePlatforms.add("microProfile-1.3"); + microProfilePlatforms.add("microProfile-1.4"); + microProfilePlatforms.add("microProfile-2.0"); + microProfilePlatforms.add("microProfile-2.1"); + microProfilePlatforms.add("microProfile-2.2"); + microProfilePlatforms.add("microProfile-3.0"); + microProfilePlatforms.add("microProfile-3.2"); + microProfilePlatforms.add("microProfile-3.3"); + microProfilePlatforms.add("microProfile-4.0"); + microProfilePlatforms.add("microProfile-4.1"); + microProfilePlatforms.add("microProfile-5.0"); + microProfilePlatforms.add("microProfile-6.0"); + microProfilePlatforms.add("microProfile-6.1"); + microProfilePlatforms.add("microProfile-7.0"); + Collections.sort(microProfilePlatforms); + + codeActions = new ArrayList<>(); + for (String nextFeature : microProfilePlatforms) { + TextEdit texted = te(invalid1.getRange().getStart().getLine(), invalid1.getRange().getStart().getCharacter(), + invalid1.getRange().getEnd().getLine(), invalid1.getRange().getEnd().getCharacter(), nextFeature); + CodeAction invalidCodeAction = ca(invalid1, texted); + + codeActions.add(invalidCodeAction); + } - XMLAssert.testCodeActionsFor(serverXML, invalid1); + XMLAssert.testCodeActionsFor(serverXML, invalid1, codeActions.get(0), + codeActions.get(1), codeActions.get(2), + codeActions.get(3), codeActions.get(4), + codeActions.get(5), codeActions.get(6), + codeActions.get(7), codeActions.get(8), + codeActions.get(9), codeActions.get(10), + codeActions.get(11), codeActions.get(12), + codeActions.get(13), codeActions.get(14), + codeActions.get(15)); } } \ No newline at end of file From 96dd03e32607f3f19105e41228201ce87ea43ed2 Mon Sep 17 00:00:00 2001 From: Arun Venmany Date: Tue, 22 Oct 2024 12:15:54 +0530 Subject: [PATCH 5/8] correcting copyrights Signed-off-by: Arun Venmany --- .../tools/langserver/lemminx/LibertyCodeActionParticipant.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/LibertyCodeActionParticipant.java b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/LibertyCodeActionParticipant.java index 366268bd..0b5f8401 100644 --- a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/LibertyCodeActionParticipant.java +++ b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/LibertyCodeActionParticipant.java @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2022, 2023 IBM Corporation and others. +* Copyright (c) 2022, 2024 IBM Corporation and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at From 658bee0330f80e646eefbe47b147cdc829054335 Mon Sep 17 00:00:00 2001 From: Arun Venmany Date: Tue, 22 Oct 2024 18:10:24 +0530 Subject: [PATCH 6/8] adding more code based on review comments Signed-off-by: Arun Venmany --- .../src/test/java/io/openliberty/LibertyDiagnosticTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java index 42b3cd4e..73e0a638 100644 --- a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java +++ b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java @@ -803,7 +803,7 @@ public void testInvalidPlatformDiagnosticWithCodeCompletion() throws BadLocation XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLURI, invalid1); - + XMLAssert.testCodeActionsFor(serverXML, invalid1); serverXML = String.join(newLine, // "", // " ", // @@ -820,7 +820,7 @@ public void testInvalidPlatformDiagnosticWithCodeCompletion() throws BadLocation XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLURI, invalid1); - // expecting code action to show no platforms since + // expecting code action to show only microprofile platforms since // 1. javaee is already included // 2. jakartaee is conflicting with javaee platforms List microProfilePlatforms = new ArrayList<>(); From c6661bb474e2f4b402e82768c5c5521878ea775b Mon Sep 17 00:00:00 2001 From: Arun Venmany Date: Tue, 22 Oct 2024 19:42:42 +0530 Subject: [PATCH 7/8] adding more comments on tests Signed-off-by: Arun Venmany --- .../src/test/java/io/openliberty/LibertyDiagnosticTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java index 73e0a638..d4656f47 100644 --- a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java +++ b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java @@ -803,6 +803,11 @@ public void testInvalidPlatformDiagnosticWithCodeCompletion() throws BadLocation XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLURI, invalid1); + // expecting code action to show nothing since + // 1. javaee is already included + // 2. jakartaee is conflicting with javaee platforms + // 3. user has entered value "ja", no platform is available which matches this input + XMLAssert.testCodeActionsFor(serverXML, invalid1); serverXML = String.join(newLine, // "", // @@ -820,6 +825,7 @@ public void testInvalidPlatformDiagnosticWithCodeCompletion() throws BadLocation XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLURI, invalid1); + // expecting code action to show only microprofile platforms since // 1. javaee is already included // 2. jakartaee is conflicting with javaee platforms From 2ad94c83c6a0345f4eed33fafd1e3235f93f69e8 Mon Sep 17 00:00:00 2001 From: Arun Venmany Date: Tue, 22 Oct 2024 19:47:12 +0530 Subject: [PATCH 8/8] adding more comments on tests Signed-off-by: Arun Venmany --- .../src/test/java/io/openliberty/LibertyDiagnosticTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java index d4656f47..d81a626b 100644 --- a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java +++ b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java @@ -827,8 +827,7 @@ public void testInvalidPlatformDiagnosticWithCodeCompletion() throws BadLocation invalid1); // expecting code action to show only microprofile platforms since - // 1. javaee is already included - // 2. jakartaee is conflicting with javaee platforms + // 1. user has entered "microP" List microProfilePlatforms = new ArrayList<>(); microProfilePlatforms.add("microProfile-1.0"); microProfilePlatforms.add("microProfile-1.2");