diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d885f6f8..549113dc 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -39,7 +39,7 @@ jobs:
java-version: 17
- name: Build Lemminx Liberty
working-directory: ./lemminx-liberty
- run: ./mvnw clean package -ntp
+ run: ./mvnw clean package -ntp -DskipTests
- name: Test Lemminx Liberty
working-directory: ./lemminx-liberty
run: ./mvnw verify -ntp
\ No newline at end of file
diff --git a/lemminx-liberty/pom.xml b/lemminx-liberty/pom.xml
index 28698ab8..d026891d 100644
--- a/lemminx-liberty/pom.xml
+++ b/lemminx-liberty/pom.xml
@@ -4,7 +4,7 @@
io.openliberty.tools
liberty-langserver-lemminx
jar
- 2.0.2-SNAPSHOT
+ 2.1-SNAPSHOT
lemminx-liberty
https://github.com/OpenLiberty/liberty-language-server
@@ -55,6 +55,15 @@
17
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.1.2
+
+
+ maven-failsafe-plugin
+ 3.1.2
+
org.apache.maven.plugins
maven-shade-plugin
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 0d8a93fa..a2092722 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
@@ -24,6 +24,7 @@
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import io.openliberty.tools.langserver.lemminx.codeactions.AddAttribute;
+import io.openliberty.tools.langserver.lemminx.codeactions.AddFeature;
import io.openliberty.tools.langserver.lemminx.codeactions.CreateFile;
import io.openliberty.tools.langserver.lemminx.codeactions.EditAttribute;
import io.openliberty.tools.langserver.lemminx.codeactions.ReplaceFeature;
@@ -55,6 +56,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.MISSING_CONFIGURED_FEATURE_CODE, new AddFeature());
}
}
}
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 b61941a0..736c359c 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
@@ -23,27 +23,41 @@
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
+import io.openliberty.tools.langserver.lemminx.data.FeatureListGraph;
import io.openliberty.tools.langserver.lemminx.data.LibertyRuntime;
import io.openliberty.tools.langserver.lemminx.services.FeatureService;
+import io.openliberty.tools.langserver.lemminx.services.LibertyProjectsManager;
+import io.openliberty.tools.langserver.lemminx.services.LibertyWorkspace;
import io.openliberty.tools.langserver.lemminx.services.SettingsService;
import io.openliberty.tools.langserver.lemminx.util.*;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.logging.Logger;
public class LibertyDiagnosticParticipant implements IDiagnosticsParticipant {
+ private static final Logger LOGGER = Logger.getLogger(LibertyDiagnosticParticipant.class.getName());
+
+ public static final String LIBERTY_LEMMINX_SOURCE = "liberty-lemminx";
+
public static final String MISSING_FILE_MESSAGE = "The resource at the specified location could not be found.";
public static final String MISSING_FILE_CODE = "missing_file";
+ public static final String MISSING_CONFIGURED_FEATURE_MESSAGE = "This config element does not relate to a feature configured in the featureManager. Remove this element or add a relevant feature.";
+ public static final String MISSING_CONFIGURED_FEATURE_CODE = "lost_config_element";
+
public static final String NOT_OPTIONAL_MESSAGE = "The specified resource cannot be skipped. Check location value or set optional to true.";
public static final String NOT_OPTIONAL_CODE = "not_optional";
public static final String IMPLICIT_NOT_OPTIONAL_MESSAGE = "The specified resource cannot be skipped. Check location value or add optional attribute.";
public static final String IMPLICIT_NOT_OPTIONAL_CODE = "implicit_not_optional";
public static final String INCORRECT_FEATURE_CODE = "incorrect_feature";
+
+ private Set includedFeatures;
@Override
public void doDiagnostics(DOMDocument domDocument, List diagnostics,
@@ -53,22 +67,29 @@ public void doDiagnostics(DOMDocument domDocument, List diagnostics,
try {
validateDom(domDocument, diagnostics);
} catch (IOException e) {
- System.err.println("Error validating document " + domDocument.getDocumentURI());
- System.err.println(e.getMessage());
+ LOGGER.severe("Error validating document " + domDocument.getDocumentURI());
+ LOGGER.severe(e.getMessage());
}
}
- private void validateDom(DOMDocument domDocument, List list) throws IOException {
+ private void validateDom(DOMDocument domDocument, List diagnosticsList) throws IOException {
List nodes = domDocument.getDocumentElement().getChildren();
-
+ List tempDiagnosticsList = new ArrayList();
+ includedFeatures = new HashSet<>();
+ LibertyWorkspace workspace = LibertyProjectsManager.getInstance().getWorkspaceFolder(domDocument.getDocumentURI());
+ // TODO: Consider adding a cached feature list onto repo to optimize
+ FeatureListGraph featureGraph = (workspace == null) ? new FeatureListGraph() : workspace.getFeatureListGraph();
for (DOMNode node : nodes) {
- if (LibertyConstants.FEATURE_MANAGER_ELEMENT.equals(node.getNodeName())) {
- validateFeature(domDocument, list, node);
- } else if (LibertyConstants.INCLUDE_ELEMENT.equals(node.getNodeName())) {
- validateIncludeLocation(domDocument, list, node);
+ String nodeName = node.getNodeName();
+ if (LibertyConstants.FEATURE_MANAGER_ELEMENT.equals(nodeName)) {
+ validateFeature(domDocument, diagnosticsList, node);
+ } else if (LibertyConstants.INCLUDE_ELEMENT.equals(nodeName)) {
+ validateIncludeLocation(domDocument, diagnosticsList, node);
+ } else if (featureGraph.isConfigElement(nodeName)) { // defaults to false
+ holdConfigElement(domDocument, node, tempDiagnosticsList);
}
}
-
+ validateConfigElements(diagnosticsList, tempDiagnosticsList, featureGraph);
}
private void validateFeature(DOMDocument domDocument, List list, DOMNode featureManager) {
@@ -80,7 +101,6 @@ private void validateFeature(DOMDocument domDocument, List list, DOM
// Search for duplicate features
// or features that do not exist
- Set includedFeatures = new HashSet<>();
List features = featureManager.getChildren();
for (DOMNode featureNode : features) {
DOMNode featureTextNode = (DOMNode) featureNode.getChildNodes().item(0);
@@ -93,13 +113,13 @@ private void validateFeature(DOMDocument domDocument, List list, DOM
Range range = XMLPositionUtility.createRange(featureTextNode.getStart(), featureTextNode.getEnd(),
domDocument);
String message = "ERROR: The feature \"" + featureName + "\" does not exist.";
- list.add(new Diagnostic(range, message, DiagnosticSeverity.Error, "liberty-lemminx", INCORRECT_FEATURE_CODE));
+ list.add(new Diagnostic(range, message, DiagnosticSeverity.Error, LIBERTY_LEMMINX_SOURCE, INCORRECT_FEATURE_CODE));
} else {
if (includedFeatures.contains(featureName)) {
Range range = XMLPositionUtility.createRange(featureTextNode.getStart(),
featureTextNode.getEnd(), domDocument);
String message = "ERROR: " + featureName + " is already included.";
- list.add(new Diagnostic(range, message, DiagnosticSeverity.Error, "liberty-lemminx"));
+ list.add(new Diagnostic(range, message, DiagnosticSeverity.Error, LIBERTY_LEMMINX_SOURCE));
} else {
includedFeatures.add(featureName);
}
@@ -117,7 +137,7 @@ private void validateFeature(DOMDocument domDocument, List list, DOM
* 2) performed in isConfigXMLFile
* 4) not yet implemented/determined
*/
- private void validateIncludeLocation(DOMDocument domDocument, List list, DOMNode node) {
+ private void validateIncludeLocation(DOMDocument domDocument, List diagnosticsList, DOMNode node) {
String locAttribute = node.getAttribute("location");
if (locAttribute == null) {
return;
@@ -131,7 +151,7 @@ private void validateIncludeLocation(DOMDocument domDocument, List l
Range range = XMLPositionUtility.createRange(locNode.getStart(), locNode.getEnd(), domDocument);
if (!locAttribute.endsWith(".xml")) {
String message = "The specified resource is not an XML file.";
- list.add(new Diagnostic(range, message, DiagnosticSeverity.Warning, "liberty-lemminx"));
+ diagnosticsList.add(new Diagnostic(range, message, DiagnosticSeverity.Warning, LIBERTY_LEMMINX_SOURCE));
return;
}
@@ -144,15 +164,56 @@ private void validateIncludeLocation(DOMDocument domDocument, List l
if (!configFile.exists()) {
DOMAttr optNode = node.getAttributeNode("optional");
if (optNode == null) {
- list.add(new Diagnostic(range, IMPLICIT_NOT_OPTIONAL_MESSAGE, DiagnosticSeverity.Error, "liberty-lemminx", IMPLICIT_NOT_OPTIONAL_CODE));
+ diagnosticsList.add(new Diagnostic(range, IMPLICIT_NOT_OPTIONAL_MESSAGE, DiagnosticSeverity.Error, LIBERTY_LEMMINX_SOURCE, IMPLICIT_NOT_OPTIONAL_CODE));
} else if (optNode.getValue().equals("false")) {
Range optRange = XMLPositionUtility.createRange(optNode.getStart(), optNode.getEnd(), domDocument);
- list.add(new Diagnostic(optRange, NOT_OPTIONAL_MESSAGE, DiagnosticSeverity.Error, "liberty-lemminx", NOT_OPTIONAL_CODE));
+ diagnosticsList.add(new Diagnostic(optRange, NOT_OPTIONAL_MESSAGE, DiagnosticSeverity.Error, LIBERTY_LEMMINX_SOURCE, NOT_OPTIONAL_CODE));
}
- list.add(new Diagnostic(range, MISSING_FILE_MESSAGE, DiagnosticSeverity.Warning, "liberty-lemminx", MISSING_FILE_CODE));
+ diagnosticsList.add(new Diagnostic(range, MISSING_FILE_MESSAGE, DiagnosticSeverity.Warning, LIBERTY_LEMMINX_SOURCE, MISSING_FILE_CODE));
}
} catch (IllegalArgumentException e) {
- list.add(new Diagnostic(range, MISSING_FILE_MESSAGE, DiagnosticSeverity.Warning, "liberty-lemminx-exception", MISSING_FILE_CODE));
+ diagnosticsList.add(new Diagnostic(range, MISSING_FILE_MESSAGE, DiagnosticSeverity.Warning, "liberty-lemminx-exception", MISSING_FILE_CODE));
+ }
+ }
+
+ /**
+ * Create temporary diagnostics for validation for single pass-through.
+ * @param domDocument
+ * @param diagnosticsList
+ * @param configElementNode
+ * @param tempDiagnosticsList
+ */
+ private void holdConfigElement(DOMDocument domDocument, DOMNode configElementNode, List tempDiagnosticsList) {
+ String configElementName = configElementNode.getNodeName();
+ Range range = XMLPositionUtility
+ .createRange(configElementNode.getStart(), configElementNode.getEnd(), domDocument);
+ Diagnostic tempDiagnostic = new Diagnostic(range, MISSING_CONFIGURED_FEATURE_MESSAGE, null, LIBERTY_LEMMINX_SOURCE, MISSING_CONFIGURED_FEATURE_CODE);
+ tempDiagnostic.setSource(configElementName);
+ tempDiagnosticsList.add(tempDiagnostic);
+ }
+
+ /**
+ * Compare the required feature set with included feature set for each config element.
+ * @param diagnosticsList
+ * @param tempDiagnosticsList
+ * @param featureGraph
+ */
+ private void validateConfigElements(List diagnosticsList, List tempDiagnosticsList, FeatureListGraph featureGraph) {
+ if (featureGraph.isEmpty()) {
+ return;
+ }
+ if (includedFeatures.isEmpty()) {
+ diagnosticsList.addAll(tempDiagnosticsList);
+ return;
+ }
+ for (Diagnostic tempDiagnostic : tempDiagnosticsList) {
+ String configElement = tempDiagnostic.getSource();
+ Set includedFeaturesCopy = new HashSet(includedFeatures);
+ Set compatibleFeaturesList = featureGraph.getAllEnabledBy(configElement);
+ includedFeaturesCopy.retainAll(compatibleFeaturesList);
+ if (includedFeaturesCopy.isEmpty()) {
+ diagnosticsList.add(tempDiagnostic);
+ }
}
}
-}
+}
\ No newline at end of file
diff --git a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/AddFeature.java b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/AddFeature.java
new file mode 100644
index 00000000..38aae88b
--- /dev/null
+++ b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/AddFeature.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+* Copyright (c) 2023 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 java.util.List;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import org.eclipse.lemminx.commons.BadLocationException;
+import org.eclipse.lemminx.commons.CodeActionFactory;
+import org.eclipse.lemminx.commons.TextDocument;
+import org.eclipse.lemminx.dom.DOMDocument;
+import org.eclipse.lemminx.dom.DOMElement;
+import org.eclipse.lemminx.dom.DOMNode;
+import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionParticipant;
+import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionRequest;
+import org.eclipse.lemminx.utils.XMLPositionUtility;
+import org.eclipse.lsp4j.CodeAction;
+import org.eclipse.lsp4j.Diagnostic;
+import org.eclipse.lsp4j.Range;
+import org.eclipse.lsp4j.jsonrpc.CancelChecker;
+
+import io.openliberty.tools.langserver.lemminx.services.LibertyProjectsManager;
+import io.openliberty.tools.langserver.lemminx.util.LibertyConstants;
+
+public class AddFeature implements ICodeActionParticipant {
+ Logger LOGGER = Logger.getLogger(AddFeature.class.getName());
+
+ /** This code action adresses 3 main situations:
+ * 1) Add a feature to an existing empty featureManager
+ * 2) Add a feature to an existing featureManager with children
+ * 3) Add a feature and new featureManager
+ *
+ * To calculate where to insert, each scenario will use a reference point to calculate range
+ * 1) The startTag of the featureManager
+ * 2) The last child of the featureManager
+ * 3) The startTag of the server.xml
+ */
+ public static final String FEATURE_FORMAT = "%s";
+ public static final String FEATUREMANAGER_FORMAT =
+ "\n\t"+
+ "\n\t\t%s"+
+ "\n\t";
+
+ @Override
+ public void doCodeAction(ICodeActionRequest request, List codeActions, CancelChecker cancelChecker) {
+ Diagnostic diagnostic = request.getDiagnostic();
+ DOMDocument document = request.getDocument();
+ TextDocument textDocument = document.getTextDocument();
+ // getAllEnabledBy would return all transitive features but typically offers too much
+ Set featureCandidates = LibertyProjectsManager.getInstance()
+ .getWorkspaceFolder(document.getDocumentURI())
+ .getFeatureListGraph().get(diagnostic.getSource()).getEnabledBy();
+ if (featureCandidates.isEmpty()) {
+ return;
+ }
+
+ String insertText = "";
+ int referenceRangeStart = 0;
+ int referenceRangeEnd = 0;
+
+ for (DOMNode node : document.getDocumentElement().getChildren()) {
+ if (LibertyConstants.FEATURE_MANAGER_ELEMENT.equals(node.getNodeName())) {
+ DOMNode lastChild = node.getLastChild();
+ if (node.getChildren().size() > 1) {
+ // Situation 2
+ insertText = "\n" + FEATURE_FORMAT;
+ referenceRangeStart = lastChild.getStart();
+ referenceRangeEnd = lastChild.getEnd();
+ } else {
+ if (lastChild != null && (lastChild.hasChildNodes() || lastChild.isComment())) {
+ // Situation 2
+ insertText = "\n" + FEATURE_FORMAT;
+ referenceRangeStart = lastChild.getStart();
+ referenceRangeEnd = lastChild.getEnd();
+ } else {
+ // Situation 1
+ insertText = "\n\t" + FEATURE_FORMAT;
+ DOMElement featureManager = (DOMElement) node;
+ referenceRangeStart = featureManager.getStartTagOpenOffset();
+ referenceRangeEnd = featureManager.getStartTagCloseOffset()+1;
+ }
+ }
+ break;
+ }
+ }
+ // Situation 3
+ if (insertText.isEmpty()) {
+ insertText = FEATUREMANAGER_FORMAT;
+ DOMElement server = document.getDocumentElement();
+ referenceRangeStart = server.getStart();
+ referenceRangeEnd = server.getStartTagCloseOffset()+1;
+ }
+ Range referenceRange = XMLPositionUtility.createRange(referenceRangeStart, referenceRangeEnd, document);
+
+ String indent = " ";
+ try {
+ indent = request.getXMLGenerator().getWhitespacesIndent();
+ } catch (BadLocationException e) {
+ LOGGER.info("Defaulting indent to four spaces.");
+ }
+ insertText = IndentUtil.formatText(insertText, indent, referenceRange.getStart().getCharacter());
+
+ for (String feature : featureCandidates) {
+ String title = "Add feature " + feature;
+ codeActions.add(CodeActionFactory.insert(
+ title, referenceRange.getEnd(), String.format(insertText, feature), textDocument, diagnostic));
+ }
+ }
+}
diff --git a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/IndentUtil.java b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/IndentUtil.java
new file mode 100644
index 00000000..205eecad
--- /dev/null
+++ b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/codeactions/IndentUtil.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+* Copyright (c) 2023 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;
+
+// Use this helper class to format your strings with indentation
+public class IndentUtil {
+ public static final String NEW_LINE = System.lineSeparator();
+
+ public static String whitespaceBuffer(String indent, int column) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < column / indent.length(); ++i) {
+ sb.append(indent);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Will return a string where `\n` will be replaced with a proper line separator and match the
+ * indentation level for the passed in column number. Adding `\t` will add an indent level.
+ * @param text
+ * @param indent
+ * @param column
+ * @return
+ */
+ public static String formatText(String text, String indent, int column) {
+ return text.replace("\n", System.lineSeparator() + whitespaceBuffer(indent, column))
+ .replace("\t", indent);
+ }
+}
diff --git a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/data/FeatureListGraph.java b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/data/FeatureListGraph.java
new file mode 100644
index 00000000..3d4a40ff
--- /dev/null
+++ b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/data/FeatureListGraph.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+* Copyright (c) 2023 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.data;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class FeatureListGraph {
+ private String runtime = "";
+ private Map nodes;
+ private Map> enabledByCache;
+ private Map> enablesCache;
+
+ public FeatureListGraph() {
+ nodes = new HashMap();
+ enabledByCache = new HashMap>();
+ enablesCache = new HashMap>();
+ }
+
+ public FeatureListNode addFeature(String nodeName) {
+ if (nodes.containsKey(nodeName)) {
+ return nodes.get(nodeName);
+ }
+ FeatureListNode node = new FeatureListNode(nodeName);
+ nodes.put(nodeName, node);
+ return node;
+ }
+
+ public FeatureListNode addConfigElement(String nodeName) {
+ if (nodes.containsKey(nodeName)) {
+ return nodes.get(nodeName);
+ }
+ FeatureListNode node = new FeatureListNode(nodeName);
+ nodes.put(nodeName, node);
+ return node;
+ }
+
+ public FeatureListNode get(String nodeName) {
+ return nodes.get(nodeName);
+ }
+
+ public boolean isEmpty() {
+ return nodes.isEmpty();
+ }
+
+ public boolean isConfigElement(String featureListNode) {
+ if (!nodes.containsKey(featureListNode)) {
+ return false;
+ }
+ return nodes.get(featureListNode).isConfigElement();
+ }
+
+ public void setRuntime(String runtime) {
+ this.runtime = runtime;
+ }
+
+ public String getRuntime() {
+ return this.runtime;
+ }
+
+ /**
+ * Returns a superset of 'owning' features that enable a given config element or feature.
+ * @param elementName
+ * @return
+ */
+ public Set getAllEnabledBy(String elementName) {
+ if (enabledByCache.containsKey(elementName)) {
+ return enabledByCache.get(elementName);
+ }
+ if (!nodes.containsKey(elementName)) {
+ return null;
+ }
+ // Implements a breadth-first-search on parent nodes
+ Set allEnabledBy = new HashSet(nodes.get(elementName).getEnabledBy());
+ Deque queue = new ArrayDeque(allEnabledBy);
+ Set visited = new HashSet();
+ while (!queue.isEmpty()) {
+ String node = queue.getFirst();
+ queue.removeFirst();
+ if (visited.contains(node)) {
+ continue;
+ }
+ Set enablers = nodes.get(node).getEnabledBy();
+ visited.add(node);
+ allEnabledBy.addAll(enablers);
+ queue.addAll(enablers);
+ }
+ enabledByCache.put(elementName, allEnabledBy);
+ return allEnabledBy;
+ }
+
+ /**
+ * Returns the set of supported features or config elements for a given feature.
+ * @param feature
+ * @return
+ */
+ public Set getAllEnables(String feature) {
+ if (enablesCache.containsKey(feature)) {
+ return enablesCache.get(feature);
+ }
+ if (!nodes.containsKey(feature)) {
+ return null;
+ }
+ // Implements a breadth-first-search on child nodes
+ Set allEnables = new HashSet(nodes.get(feature).getEnables());
+ Deque queue = new ArrayDeque(allEnables);
+ Set visited = new HashSet();
+ while (!queue.isEmpty()) {
+ String node = queue.getFirst();
+ queue.removeFirst();
+ if (visited.contains(node)) {
+ continue;
+ }
+ Set enablers = nodes.get(node).getEnables();
+ visited.add(node);
+ allEnables.addAll(enablers);
+ queue.addAll(enablers);
+ }
+ enablesCache.put(feature, allEnables);
+ return allEnables;
+ }
+
+ /** Will be useful for future features **/
+
+ // public Set getAllConfigElements(String feature) {
+ // Set configElements = new HashSet();
+ // for (String node : getAllEnables(feature)) {
+ // if (isConfigElement(node)) {
+ // configElements.add(node);
+ // }
+ // }
+ // return configElements;
+ // }
+
+ // public Set getAllEnabledFeatures(String feature) {
+ // Set enabledFeatures = new HashSet();
+ // for (String node : getAllEnables(feature)) {
+ // if (!isConfigElement(node)) {
+ // enabledFeatures.add(node);
+ // }
+ // }
+ // return enabledFeatures;
+ // }
+}
\ No newline at end of file
diff --git a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/data/FeatureListNode.java b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/data/FeatureListNode.java
new file mode 100644
index 00000000..4c8e1ccb
--- /dev/null
+++ b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/data/FeatureListNode.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+* Copyright (c) 2023 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.data;
+
+import java.util.HashSet;
+import java.util.Set;
+
+
+// Class to represent a feature OR config element in a feature list xml
+public class FeatureListNode {
+ protected String nodeName;
+ protected Set enabledBy;
+ protected Set enables;
+
+ public FeatureListNode(String nodeName) {
+ enabledBy = new HashSet();
+ enables = new HashSet();
+ this.nodeName = nodeName;
+ }
+
+ public void addEnabledBy(String nodeName) {
+ enabledBy.add(nodeName);
+ }
+
+ public void addEnables(String nodeName) {
+ enables.add(nodeName);
+ }
+
+ public Set getEnabledBy() {
+ return enabledBy;
+ }
+
+ public Set getEnables() {
+ return enables;
+ }
+
+ // based on a heuristic that features use major versions and config elements don't use '.'
+ public boolean isConfigElement() {
+ return this.nodeName.indexOf('.') == -1;
+ }
+}
\ No newline at end of file
diff --git a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/models/feature/Feature.java b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/models/feature/Feature.java
index 1b1d798e..13c3943c 100644
--- a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/models/feature/Feature.java
+++ b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/models/feature/Feature.java
@@ -16,6 +16,7 @@
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlRootElement;
+import java.util.List;
@XmlRootElement(name = "feature")
@XmlAccessorType(XmlAccessType.FIELD)
@@ -33,6 +34,9 @@ public class Feature {
private String version;
WlpInformation wlpInformation;
+ private List configElement;
+ private List enables;
+
// Getter Methods
public String getDescription() {
@@ -67,6 +71,14 @@ public WlpInformation getWlpInformation() {
return wlpInformation;
}
+ public List getConfigElements() {
+ return configElement;
+ }
+
+ public List getEnables() {
+ return enables;
+ }
+
// Setter Methods
public void setDescription(String description) {
@@ -100,4 +112,12 @@ public void setVersion(String version) {
public void setWlpInformation(WlpInformation wlpInformation) {
this.wlpInformation = wlpInformation;
}
+
+ public void setConfigElements(List configElement) {
+ this.configElement = configElement;
+ }
+
+ public void setEnables(List enables) {
+ this.enables = enables;
+ }
}
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 afe29631..b13a5cca 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
@@ -42,7 +42,8 @@
import com.google.gson.Gson;
import com.google.gson.JsonParseException;
-
+import io.openliberty.tools.langserver.lemminx.data.FeatureListGraph;
+import io.openliberty.tools.langserver.lemminx.data.FeatureListNode;
import io.openliberty.tools.langserver.lemminx.models.feature.Feature;
import io.openliberty.tools.langserver.lemminx.models.feature.FeatureInfo;
import io.openliberty.tools.langserver.lemminx.models.feature.WlpInformation;
@@ -179,7 +180,7 @@ public List getFeatures(String libertyVersion, String libertyRuntime, i
if (!libertyVersion.endsWith("-beta")) {
try {
// verify that request delay (seconds) has gone by since last fetch request
- // Note that the default delay is 120 seconds and can cause us to generate a feature list instead of download from MC when
+ // Note that the default delay is 10 seconds and can cause us to generate a feature list instead of download from MC when
// switching back and forth between projects.
long currentTime = System.currentTimeMillis();
if (this.featureUpdateTime == -1 || currentTime >= (this.featureUpdateTime + (requestDelay * 1000))) {
@@ -269,10 +270,8 @@ public List collectExistingFeatures(DOMNode featureManager, String curre
* @param libertyVersion must not be null and should be a valid Liberty version (e.g. 23.0.0.6)
* @return list of installed features, or empty list
*/
- private List getInstalledFeaturesList(String documentURI, String libertyRuntime, String libertyVersion) {
+ public List getInstalledFeaturesList(LibertyWorkspace libertyWorkspace, String libertyRuntime, String libertyVersion) {
List installedFeatures = new ArrayList();
-
- LibertyWorkspace libertyWorkspace = LibertyProjectsManager.getInstance().getWorkspaceFolder(documentURI);
if (libertyWorkspace == null || libertyWorkspace.getWorkspaceString() == null) {
return installedFeatures;
}
@@ -287,7 +286,6 @@ private List getInstalledFeaturesList(String documentURI, String libert
try {
// Need to handle both local installation and container
File featureListFile = null;
-
if (libertyWorkspace.isLibertyInstalled()) {
Path featureListJAR = LibertyUtils.findLibertyFileForWorkspace(libertyWorkspace, Paths.get("bin", "tools", "ws-featurelist.jar"));
if (featureListJAR != null && featureListJAR.toFile().exists()) {
@@ -315,6 +313,11 @@ private List getInstalledFeaturesList(String documentURI, String libert
LOGGER.info("Returning installed features: " + installedFeatures.size());
return installedFeatures;
}
+
+ public List getInstalledFeaturesList(String documentURI, String libertyRuntime, String libertyVersion) {
+ LibertyWorkspace libertyWorkspace = LibertyProjectsManager.getInstance().getWorkspaceFolder(documentURI);
+ return getInstalledFeaturesList(libertyWorkspace, libertyRuntime, libertyVersion);
+ }
/**
* Generate the featurelist file for a LibertyWorkspace using the ws-featurelist.jar in the corresponding Liberty installation
@@ -374,21 +377,41 @@ public List readFeaturesFromFeatureListFile(List installedFeat
// Note: Only the public features are loaded when unmarshalling the passed featureListFile.
if ((featureInfo.getFeatures() != null) && (featureInfo.getFeatures().size() > 0)) {
- for (int i = 0; i < featureInfo.getFeatures().size(); i++) {
- Feature f = featureInfo.getFeatures().get(i);
+ FeatureListGraph featureListGraph = new FeatureListGraph();
+ for (Feature f : featureInfo.getFeatures()) {
f.setShortDescription(f.getDescription());
// The xml featureListFile does not have a wlpInformation element like the json does, but our code depends on looking up
// features by the shortName found in wlpInformation. So create a WlpInformation object and initialize the shortName to
// the feature name.
WlpInformation wlpInfo = new WlpInformation(f.getName());
f.setWlpInformation(wlpInfo);
+
+ String currentFeature = f.getName();
+ List enables = f.getEnables();
+ List configElements = f.getConfigElements();
+ FeatureListNode currentFeatureNode = featureListGraph.addFeature(currentFeature);
+ if (enables != null) {
+ for (String enabledFeature : enables) {
+ FeatureListNode feature = featureListGraph.addFeature(enabledFeature);
+ feature.addEnabledBy(currentFeature);
+ currentFeatureNode.addEnables(enabledFeature);
+ }
+ }
+ if (configElements != null) {
+ for (String configElement : configElements) {
+ FeatureListNode configNode = featureListGraph.addConfigElement(configElement);
+ configNode.addEnabledBy(currentFeature);
+ currentFeatureNode.addEnables(configElement);
+ }
+ }
}
installedFeatures = featureInfo.getFeatures();
+ libertyWorkspace.setFeatureListGraph(featureListGraph);
libertyWorkspace.setInstalledFeatureList(installedFeatures);
} else {
LOGGER.warning("Unable to get installed features for current Liberty workspace: " + libertyWorkspace.getWorkspaceString());
+ libertyWorkspace.setFeatureListGraph(new FeatureListGraph());
}
return installedFeatures;
}
-
}
diff --git a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/services/LibertyWorkspace.java b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/services/LibertyWorkspace.java
index 4022061a..50d95dbf 100644
--- a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/services/LibertyWorkspace.java
+++ b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/services/LibertyWorkspace.java
@@ -26,9 +26,11 @@
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Unmarshaller;
-
+import io.openliberty.tools.langserver.lemminx.data.FeatureListGraph;
+import io.openliberty.tools.langserver.lemminx.data.LibertyRuntime;
import io.openliberty.tools.langserver.lemminx.models.feature.Feature;
import io.openliberty.tools.langserver.lemminx.models.settings.DevcMetadata;
+import io.openliberty.tools.langserver.lemminx.util.LibertyUtils;
public class LibertyWorkspace {
@@ -43,6 +45,7 @@ public class LibertyWorkspace {
private List installedFeatureList;
private String libertyInstallationDir;
private boolean isExternalLibertyInstallation;
+ private FeatureListGraph featureListGraph;
// devc vars
private String containerName;
@@ -65,6 +68,7 @@ public LibertyWorkspace(String workspaceFolderURI) {
this.installedFeatureList = new ArrayList();
this.containerName = null;
this.containerAlive = false;
+ this.featureListGraph = new FeatureListGraph();
}
public String getWorkspaceString() {
@@ -206,4 +210,24 @@ public String toString() {
return workspaceFolderURI;
}
+ public void setFeatureListGraph(FeatureListGraph featureListGraph) {
+ this.featureListGraph = featureListGraph;
+ if (isLibertyInstalled) {
+ this.featureListGraph.setRuntime(libertyRuntime + "-" + libertyVersion);
+ }
+ }
+
+ public FeatureListGraph getFeatureListGraph() {
+ String workspaceRuntime = libertyRuntime + "-" + libertyVersion;
+ boolean generateGraph = featureListGraph.isEmpty() || !featureListGraph.getRuntime().equals(workspaceRuntime);
+ if (this.isLibertyInstalled && generateGraph) {
+ LOGGER.info("Generating installed features list and storing to cache for workspace " + workspaceFolderURI);
+ FeatureService.getInstance().getInstalledFeaturesList(this, libertyRuntime, libertyVersion);
+ if (!this.featureListGraph.isEmpty()) {
+ LOGGER.info("Config element validation enabled for workspace: " + workspaceFolderURI);
+ }
+ }
+ return this.featureListGraph;
+ }
+
}
diff --git a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/services/SettingsService.java b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/services/SettingsService.java
index d65806df..a768155a 100644
--- a/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/services/SettingsService.java
+++ b/lemminx-liberty/src/main/java/io/openliberty/tools/langserver/lemminx/services/SettingsService.java
@@ -26,8 +26,8 @@ public static SettingsService getInstance() {
return instance;
}
- // default request delay is 120 seconds
- private static int DEFAULT_REQUEST_DELAY = 120;
+ // default request delay is 10 seconds
+ private static int DEFAULT_REQUEST_DELAY = 10;
private SettingsService() {
}
diff --git a/lemminx-liberty/src/test/java/io/openliberty/CodeActionUtilitiesTest.java b/lemminx-liberty/src/test/java/io/openliberty/CodeActionUtilitiesTest.java
new file mode 100644
index 00000000..88513389
--- /dev/null
+++ b/lemminx-liberty/src/test/java/io/openliberty/CodeActionUtilitiesTest.java
@@ -0,0 +1,33 @@
+package io.openliberty;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+import io.openliberty.tools.langserver.lemminx.codeactions.IndentUtil;
+
+public class CodeActionUtilitiesTest {
+
+ @Test
+ public void indentSpacesTest() {
+ String indent = " "; // four spaces
+ String sampleText = "\n\ttest";
+ int column = 4;
+ String expectedText = System.lineSeparator() + " test";
+ String formatedText = IndentUtil.formatText(sampleText, indent, column);
+ assertEquals(expectedText, formatedText, "Expected length of " + expectedText.length() + ". Found " + formatedText.length());
+
+ int column2 = 3;
+ String expectedText2 = System.lineSeparator() + " test";
+ assertEquals(expectedText2, IndentUtil.formatText(sampleText, indent, column2), "Incorrect detection starting indent.");
+ }
+
+ @Test
+ public void indentTabsTest() {
+ String indent = " ";
+ String sampleText = "\n\ttest";
+ int column = 1;
+ String expectedText = System.lineSeparator() + indent + indent + "test";
+ assertEquals(expectedText, IndentUtil.formatText(sampleText, indent, column), "Incorrect whitespace buffer calculation.");
+ }
+}
diff --git a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java
index 2ff59d45..3ec292c7 100644
--- a/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java
+++ b/lemminx-liberty/src/test/java/io/openliberty/LibertyDiagnosticTest.java
@@ -6,10 +6,15 @@
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.WorkspaceFolder;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import io.openliberty.tools.langserver.lemminx.LibertyDiagnosticParticipant;
+import io.openliberty.tools.langserver.lemminx.models.feature.Feature;
+import io.openliberty.tools.langserver.lemminx.services.FeatureService;
import io.openliberty.tools.langserver.lemminx.services.LibertyProjectsManager;
+import io.openliberty.tools.langserver.lemminx.services.LibertyWorkspace;
+import jakarta.xml.bind.JAXBException;
import static org.eclipse.lemminx.XMLAssert.r;
import static org.eclipse.lemminx.XMLAssert.ca;
@@ -21,13 +26,26 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import java.util.Collection;
import java.util.Collections;
public class LibertyDiagnosticTest {
static String newLine = System.lineSeparator();
- static String serverXMLURI = "test/server.xml";
+
+ static File srcResourcesDir = new File("src/test/resources");
+ static File featureList = new File("src/test/resources/featurelist-ol-23.0.0.1-beta.xml");
+ static String serverXMLURI = new File(srcResourcesDir, "test/server.xml").toURI().toString();
+ static List initList = new ArrayList();
+ LibertyProjectsManager libPM;
+ LibertyWorkspace libWorkspace;
+
+ @BeforeEach
+ public void setupWorkspace() {
+ initList.add(new WorkspaceFolder(srcResourcesDir.toURI().toString()));
+ libPM = LibertyProjectsManager.getInstance();
+ libPM.setWorkspaceFolders(initList);
+ libWorkspace = libPM.getLibertyWorkspaceFolders().iterator().next();
+ }
@Test
public void testFeatureDuplicateDiagnostic() {
@@ -175,4 +193,71 @@ public void testDiagnosticsForInclude() throws IOException {
XMLAssert.testDiagnosticsFor(serverXML, null, null, serverXMLFile.toURI().toString(),
not_xml, multi_liner, not_optional, missing_xml, optional_not_defined, missing_xml2);
}
+
+ @Test
+ public void testConfigElementMissingFeatureManager() throws JAXBException {
+ assertTrue(featureList.exists());
+ FeatureService.getInstance().readFeaturesFromFeatureListFile(new ArrayList(), libWorkspace, featureList);
+
+ String serverXml = "";
+ Diagnostic config_for_missing_feature = new Diagnostic();
+ config_for_missing_feature.setRange(r(0, serverXml.indexOf("".length()));
+ config_for_missing_feature.setCode(LibertyDiagnosticParticipant.MISSING_CONFIGURED_FEATURE_CODE);
+ config_for_missing_feature.setMessage(LibertyDiagnosticParticipant.MISSING_CONFIGURED_FEATURE_MESSAGE);
+
+ XMLAssert.testDiagnosticsFor(serverXml, null, null, serverXMLURI, config_for_missing_feature);
+ }
+
+ @Test
+ public void testConfigElementDirect() throws JAXBException {
+ assertTrue(featureList.exists());
+ FeatureService.getInstance().readFeaturesFromFeatureListFile(new ArrayList(), libWorkspace, featureList);
+
+ String correctFeature = " ssl-1.0";
+ String incorrectFeature = " jaxrs-2.0";
+ String configElement = " ";
+ int diagnosticStart = configElement.indexOf("<");
+ int diagnosticLength = configElement.trim().length();
+
+ String serverXML1 = String.join(newLine,
+ "",
+ " ",
+ correctFeature,
+ " ",
+ configElement,
+ ""
+ );
+ XMLAssert.testDiagnosticsFor(serverXML1, null, null, serverXMLURI);
+
+ String serverXML2 = String.join(newLine,
+ "",
+ " ",
+ incorrectFeature,
+ " ",
+ configElement,
+ ""
+ );
+
+ Diagnostic config_for_missing_feature = new Diagnostic();
+ config_for_missing_feature.setRange(r(4, diagnosticStart, 4, diagnosticStart + diagnosticLength));
+ config_for_missing_feature.setCode(LibertyDiagnosticParticipant.MISSING_CONFIGURED_FEATURE_CODE);
+ config_for_missing_feature.setMessage(LibertyDiagnosticParticipant.MISSING_CONFIGURED_FEATURE_MESSAGE);
+
+ XMLAssert.testDiagnosticsFor(serverXML2, null, null, serverXMLURI, config_for_missing_feature);
+ }
+
+ @Test
+ public void testConfigElementTransitive() throws JAXBException {
+ assertTrue(featureList.exists());
+ FeatureService.getInstance().readFeaturesFromFeatureListFile(new ArrayList(), libWorkspace, featureList);
+ String serverXML1 = String.join(newLine,
+ "",
+ " ",
+ " microProfile-5.0",
+ " ",
+ " ",
+ ""
+ );
+ XMLAssert.testDiagnosticsFor(serverXML1, null, null, serverXMLURI);
+ }
}
\ No newline at end of file
diff --git a/lemminx-liberty/src/test/java/io/openliberty/LibertyFeatureTest.java b/lemminx-liberty/src/test/java/io/openliberty/LibertyFeatureTest.java
index 74264808..c3971b37 100644
--- a/lemminx-liberty/src/test/java/io/openliberty/LibertyFeatureTest.java
+++ b/lemminx-liberty/src/test/java/io/openliberty/LibertyFeatureTest.java
@@ -1,5 +1,6 @@
package io.openliberty;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -11,6 +12,7 @@
import org.eclipse.lsp4j.WorkspaceFolder;
import org.junit.jupiter.api.Test;
+import io.openliberty.tools.langserver.lemminx.data.FeatureListGraph;
import io.openliberty.tools.langserver.lemminx.models.feature.Feature;
import io.openliberty.tools.langserver.lemminx.services.FeatureService;
import io.openliberty.tools.langserver.lemminx.services.LibertyProjectsManager;
@@ -41,5 +43,17 @@ public void getInstalledFeaturesListTest() throws JAXBException {
assertTrue(installedFeatures.equals(libWorkspace.getInstalledFeatureList()));
// Check that list contains a beta feature
assertTrue(installedFeatures.removeIf(f -> (f.getName().equals("cdi-4.0"))));
+
+ // Check if config map gets built
+ FeatureListGraph fg = libWorkspace.getFeatureListGraph();
+ assertEquals(76, fg.getAllEnabledBy("ssl-1.0").size());
+ assertEquals(1, fg.get("ssl").getEnabledBy().size());
+ assertTrue(fg.get("ssl").getEnabledBy().contains("ssl-1.0"));
+ assertEquals(77, fg.getAllEnabledBy("ssl").size());
+ assertEquals(235, fg.getAllEnabledBy("library").size());
+ assertTrue(fg.getAllEnabledBy("ltpa").contains("adminCenter-1.0")); // direct enabler
+ assertTrue(fg.getAllEnabledBy("ssl").contains("microProfile-5.0")); // transitive enabler
+ assertTrue(fg.getAllEnables("microProfile-5.0").contains("ssl"));
+ assertTrue(fg.getAllEnables("jakartaee-8.0").contains("classloading"));
}
}
diff --git a/lemminx-liberty/src/test/java/io/openliberty/XmlReaderTest.java b/lemminx-liberty/src/test/java/io/openliberty/XmlReaderTest.java
index 011e5dec..05c81f8b 100644
--- a/lemminx-liberty/src/test/java/io/openliberty/XmlReaderTest.java
+++ b/lemminx-liberty/src/test/java/io/openliberty/XmlReaderTest.java
@@ -21,26 +21,26 @@ public class XmlReaderTest {
@Test
public void readEmptyXml() throws IOException {
File emptyXml = new File(resourcesDir, "empty_server.xml");
- assertFalse(XmlReader.hasServerRoot(emptyXml.getCanonicalPath()));
- assertFalse(LibertyUtils.isServerXMLFile(emptyXml.getCanonicalPath()));
- assertFalse(LibertyUtils.isConfigXMLFile(emptyXml.getCanonicalPath()));
+ assertFalse(XmlReader.hasServerRoot(emptyXml.toURI().toString()));
+ assertFalse(LibertyUtils.isServerXMLFile(emptyXml.toURI().toString()));
+ assertFalse(LibertyUtils.isConfigXMLFile(emptyXml.toURI().toString()));
}
@Test
public void readServerXml() throws IOException {
File sampleServerXml = new File(resourcesDir, "sample/custom_server.xml");
- assertTrue(XmlReader.hasServerRoot(sampleServerXml.getCanonicalPath()));
- assertFalse(LibertyUtils.isServerXMLFile(sampleServerXml.getCanonicalPath()));
- assertFalse(LibertyUtils.isConfigDirFile(sampleServerXml.getCanonicalPath()));
- assertTrue(LibertyUtils.isConfigXMLFile(sampleServerXml.getCanonicalPath()));
+ assertTrue(XmlReader.hasServerRoot(sampleServerXml.toURI().toString()));
+ assertFalse(LibertyUtils.isServerXMLFile(sampleServerXml.toURI().toString()));
+ assertFalse(LibertyUtils.isConfigDirFile(sampleServerXml.toURI().toString()));
+ assertTrue(LibertyUtils.isConfigXMLFile(sampleServerXml.toURI().toString()));
}
@Test
public void readLibertyPluginConfigXml() throws IOException {
File lpcXml = new File(resourcesDir, "sample/liberty-plugin-config.xml");
Path lpcXmlPath = lpcXml.toPath();
- assertFalse(XmlReader.hasServerRoot(lpcXml.getCanonicalPath()));
- assertFalse(LibertyUtils.isConfigXMLFile(lpcXml.getCanonicalPath()));
+ assertFalse(XmlReader.hasServerRoot(lpcXml.toURI().toString()));
+ assertFalse(LibertyUtils.isConfigXMLFile(lpcXml.toURI().toString()));
Set elementNames = new HashSet ();
elementNames.add("configFile");
diff --git a/liberty-ls/pom.xml b/liberty-ls/pom.xml
index 4ab1bf44..31e31b44 100644
--- a/liberty-ls/pom.xml
+++ b/liberty-ls/pom.xml
@@ -5,7 +5,7 @@
io.openliberty.tools
liberty-langserver
- 2.0.2-SNAPSHOT
+ 2.1-SNAPSHOT
liberty.langserver
https://openliberty.io/