Skip to content

Commit

Permalink
init push
Browse files Browse the repository at this point in the history
  • Loading branch information
dshimo committed Oct 5, 2023
1 parent 231e004 commit 629777c
Show file tree
Hide file tree
Showing 11 changed files with 478 additions and 31 deletions.
2 changes: 1 addition & 1 deletion lemminx-liberty/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<groupId>io.openliberty.tools</groupId>
<artifactId>liberty-langserver-lemminx</artifactId>
<packaging>jar</packaging>
<version>2.0.2-SNAPSHOT</version>
<version>2.1-SNAPSHOT</version>

<name>lemminx-liberty</name>
<url>https://github.com/OpenLiberty/liberty-language-server</url>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,39 @@
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.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 configure a feature 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<String> includedFeatures = null;

@Override
public void doDiagnostics(DOMDocument domDocument, List<Diagnostic> diagnostics,
Expand All @@ -53,22 +65,33 @@ public void doDiagnostics(DOMDocument domDocument, List<Diagnostic> diagnostics,
try {
validateDom(domDocument, diagnostics);
} catch (IOException e) {
// LOGGER.severe("Error validating document " + domDocument.getDocumentURI());
// LOGGER.severe(e.getMessage());
System.err.println("Error validating document " + domDocument.getDocumentURI());
System.err.println(e.getMessage());
}
}

private void validateDom(DOMDocument domDocument, List<Diagnostic> list) throws IOException {
private void validateDom(DOMDocument domDocument, List<Diagnostic> diagnosticsList) throws IOException {
List<DOMNode> nodes = domDocument.getDocumentElement().getChildren();
List<Diagnostic> tempDiagnosticsList = new ArrayList<Diagnostic>();

// TODO: consider initiallizing FeatureService even when features aren't detected
FeatureListGraph featureGraph = FeatureService.getInstance().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)) {
LOGGER.warning("Detected a config element!");
holdConfigElement(domDocument, diagnosticsList, node, tempDiagnosticsList);
}
}

LOGGER.warning("Entering validateConfigElements");
validateConfigElements(diagnosticsList, tempDiagnosticsList, featureGraph);
}

private void validateFeature(DOMDocument domDocument, List<Diagnostic> list, DOMNode featureManager) {
Expand All @@ -93,19 +116,20 @@ private void validateFeature(DOMDocument domDocument, List<Diagnostic> 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);
}
}
}
}
this.includedFeatures = includedFeatures;
}

/**
Expand All @@ -117,7 +141,7 @@ private void validateFeature(DOMDocument domDocument, List<Diagnostic> list, DOM
* 2) performed in isConfigXMLFile
* 4) not yet implemented/determined
*/
private void validateIncludeLocation(DOMDocument domDocument, List<Diagnostic> list, DOMNode node) {
private void validateIncludeLocation(DOMDocument domDocument, List<Diagnostic> diagnosticsList, DOMNode node) {
String locAttribute = node.getAttribute("location");
if (locAttribute == null) {
return;
Expand All @@ -131,7 +155,7 @@ private void validateIncludeLocation(DOMDocument domDocument, List<Diagnostic> 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;
}

Expand All @@ -144,15 +168,38 @@ private void validateIncludeLocation(DOMDocument domDocument, List<Diagnostic> 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));
}
}

private void holdConfigElement(DOMDocument domDocument, List<Diagnostic> diagnosticsList, DOMNode configElementNode,
List<Diagnostic> 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);
}

private void validateConfigElements(List<Diagnostic> diagnosticsList, List<Diagnostic> tempDiagnosticsList,
FeatureListGraph featureGraph) {
for (Diagnostic tempDiagnostic : tempDiagnosticsList) {
String configElement = tempDiagnostic.getSource();
Set<String> includedFeaturesCopy = new HashSet<String>(includedFeatures);
Set<String> compatibleFeaturesList = featureGraph.getAllEnablers(configElement);
includedFeaturesCopy.retainAll(compatibleFeaturesList);
if (includedFeaturesCopy.isEmpty()) {
diagnosticsList.add(tempDiagnostic);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*******************************************************************************
* 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 org.eclipse.lemminx.commons.CodeActionFactory;
import org.eclipse.lemminx.dom.DOMDocument;
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.Position;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;

import io.openliberty.tools.langserver.lemminx.services.FeatureService;
import io.openliberty.tools.langserver.lemminx.util.LibertyConstants;

public class AddFeature implements ICodeActionParticipant {

// This method is still a work in progress.
@Override
public void doCodeAction(ICodeActionRequest request, List<CodeAction> codeActions, CancelChecker cancelChecker) {
Diagnostic diagnostic = request.getDiagnostic();
DOMDocument document = request.getDocument();
try {
List<DOMNode> nodes = document.getDocumentElement().getChildren();
DOMNode featureManagerNode = null;

for (DOMNode node : nodes) {
if (LibertyConstants.FEATURE_MANAGER_ELEMENT.equals(node.getNodeName())) {
featureManagerNode = node;
break;
}
}

Position insertPosition;
String insertText;
DOMNode locationNode;
if (featureManagerNode == null) {
locationNode = document.getDocumentElement().getFirstChild();
insertPosition = XMLPositionUtility.createRange(locationNode.getStart(), locationNode.getEnd(), document).getStart();
insertText = "<featureManager>\n<feature>asdf</feature>\n</featureManager>";

} else {
locationNode = featureManagerNode.getLastChild();
insertPosition = XMLPositionUtility.createRange(locationNode.getStart(), locationNode.getEnd(), document).getEnd();
insertText = "\n\t<feature>microProfile-5.0</feature>";
}

String configElement = diagnostic.getSource();
if (configElement.equals("ssl")) {
FeatureService.getInstance().getFeatureListGraph().get("ssl").getEnablers();
}
Set<String> featureCandidates = FeatureService.getInstance().getFeatureListGraph().get(configElement).getEnablers();
codeActions.add(CodeActionFactory.insert("This is a test: " + featureCandidates, insertPosition, insertText, document.getTextDocument(), diagnostic));
for (String feature : featureCandidates) {
String title = "Add feature " + feature;
codeActions.add(CodeActionFactory.insert(title, insertPosition, feature,
document.getTextDocument(), diagnostic));
}
} catch (Exception e) {

}
}
}
Loading

0 comments on commit 629777c

Please sign in to comment.