Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Var processing #323

Merged
merged 11 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,19 @@ jobs:
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v3
- name: Checkout ci.common
uses: actions/checkout@v3
with:
repository: OpenLiberty/ci.common
path: ci.common
- name: Set up Java
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 17
- name: Build ci common
working-directory: ci.common
run: ./mvnw -V clean install --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false -DskipTests
- name: Build Lemminx Liberty
working-directory: ./lemminx-liberty
run: ./mvnw clean package -ntp -DskipTests
Expand Down
23 changes: 23 additions & 0 deletions lemminx-liberty/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,29 @@
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.12.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.openliberty.tools</groupId>
<artifactId>ci.common</artifactId>
<version>1.8.36-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.Map;

import io.openliberty.tools.langserver.lemminx.codeactions.ReplacePlatform;
import io.openliberty.tools.langserver.lemminx.codeactions.ReplaceVariable;
import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionRequest;
import org.eclipse.lsp4j.CodeAction;
Expand Down Expand Up @@ -60,6 +61,7 @@ private void registerCodeActions() {
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.INCORRECT_VARIABLE_CODE, new ReplaceVariable());
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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;

Expand All @@ -28,6 +29,7 @@
import org.eclipse.lemminx.services.extensions.completion.ICompletionResponse;
import org.eclipse.lemminx.utils.XMLPositionUtility;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.CompletionItemKind;
import org.eclipse.lsp4j.InsertReplaceEdit;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextEdit;
Expand All @@ -43,6 +45,32 @@

public class LibertyCompletionParticipant extends CompletionParticipantAdapter {


@Override
public void onAttributeValue(String valuePrefix, ICompletionRequest request, ICompletionResponse response, CancelChecker cancelChecker) throws Exception {
if (!LibertyUtils.isConfigXMLFile(request.getXMLDocument()))
return;
Properties variableProps = SettingsService.getInstance()
.getVariablesForServerXml(request.getXMLDocument()
.getDocumentURI());
String variableName = valuePrefix.replace("$", "")
.replace("{", "")
.replace("}", "");
variableProps.entrySet().stream().filter(it -> it.getKey().toString().contains(variableName))
.forEach(variableProp -> {
String varValue = String.format("${%s}", variableProp.getKey());

Either<TextEdit, InsertReplaceEdit> edit = Either.forLeft(new
TextEdit(request.getReplaceRange(), varValue));
CompletionItem completionItem = new CompletionItem();
completionItem.setLabel(varValue);
completionItem.setTextEdit(edit);
completionItem.setFilterText(variableProp.getKey().toString());
completionItem.setKind(CompletionItemKind.Value);
response.addCompletionItem(completionItem);
});
}

@Override
public void onXMLContent(ICompletionRequest request, ICompletionResponse response, CancelChecker cancelChecker)
throws IOException, BadLocationException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
package io.openliberty.tools.langserver.lemminx;

import com.google.common.collect.Sets;
import com.google.gson.JsonPrimitive;
import org.eclipse.lemminx.dom.DOMAttr;
import org.eclipse.lemminx.dom.DOMDocument;
import org.eclipse.lemminx.dom.DOMElement;
import org.eclipse.lemminx.dom.DOMNode;
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLValidationSettings;
import org.eclipse.lemminx.services.extensions.diagnostics.IDiagnosticsParticipant;
Expand All @@ -36,12 +38,16 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static io.openliberty.tools.langserver.lemminx.util.LibertyConstants.changedFeatureNameDiagMessage;
Expand Down Expand Up @@ -71,6 +77,7 @@ public class LibertyDiagnosticParticipant implements IDiagnosticsParticipant {

public static final String INCORRECT_FEATURE_CODE = "incorrect_feature";
public static final String INCORRECT_PLATFORM_CODE = "incorrect_platform";
public static final String INCORRECT_VARIABLE_CODE = "incorrect_variable";

@Override
public void doDiagnostics(DOMDocument domDocument, List<Diagnostic> diagnostics,
Expand Down Expand Up @@ -107,8 +114,38 @@ private void validateDom(DOMDocument domDocument, List<Diagnostic> diagnosticsLi
}
}
validateConfigElements(domDocument, diagnosticsList, tempDiagnosticsList, featureGraph, includedFeatures, featureManagerPresent);
validateVariables(domDocument,diagnosticsList);
}

private void validateVariables(DOMDocument domDocument, List<Diagnostic> diagnosticsList) {
String docContent = domDocument.getTextDocument().getText();
List<String> variables = LibertyUtils.getVariablesFromTextContent(docContent);
Properties variablesMap = SettingsService.getInstance().getVariablesForServerXml(domDocument.getDocumentURI());
if (variablesMap.isEmpty() && !variables.isEmpty()) {
String message = "ERROR: Dev mode is not started for current liberty workspace. Please start Dev mode to enable variable processing.";
Range range = XMLPositionUtility.createRange(domDocument.getDocumentElement().getStartTagOpenOffset(), domDocument.getDocumentElement().getStartTagCloseOffset(),
domDocument);
Diagnostic diag = new Diagnostic(range, message, DiagnosticSeverity.Error, LIBERTY_LEMMINX_SOURCE);
diagnosticsList.add(diag);
return;
}
for (String variable : variables) {
if (!variablesMap.containsKey(variable)) {
String variableInDoc = String.format("${%s}", variable);
Range range = XMLPositionUtility.createRange(docContent.indexOf(variableInDoc),
docContent.indexOf(variableInDoc) + variableInDoc.length(),
domDocument);
String message = "ERROR: The variable \"" + variable + "\" does not exist";

Diagnostic diag = new Diagnostic(range, message, DiagnosticSeverity.Error, LIBERTY_LEMMINX_SOURCE, INCORRECT_VARIABLE_CODE);
diag.setData(variable);
diagnosticsList.add(diag);
}
}
}



private void validateFeaturesAndPlatforms(DOMDocument domDocument, List<Diagnostic> list, DOMNode featureManager, Set<String> includedFeatures) {

LibertyRuntime runtimeInfo = LibertyUtils.getLibertyRuntimeInfo(domDocument);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*******************************************************************************/
package io.openliberty.tools.langserver.lemminx;

import io.openliberty.tools.langserver.lemminx.services.LibertyWorkspace;
import org.eclipse.lemminx.services.extensions.IDocumentLinkParticipant;
import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.completion.ICompletionParticipant;
Expand Down Expand Up @@ -69,6 +70,13 @@ public void start(InitializeParams initializeParams, XMLExtensionsRegistry xmlEx

documentLinkParticipant = new LibertyDocumentLinkParticipant();
xmlExtensionsRegistry.registerDocumentLinkParticipant(documentLinkParticipant);

try {
SettingsService.getInstance()
.populateAllVariables(LibertyProjectsManager.getInstance().getLibertyWorkspaceFolders());
} catch (Exception e) {
throw new RuntimeException(e);
}
}

@Override
Expand All @@ -95,5 +103,17 @@ public void doSave(ISaveContext saveContext) {
SettingsService.getInstance().updateLibertySettings(xmlSettings);
LOGGER.info("Liberty XML settings updated");
}
if (saveContext.getType() == SaveContextType.DOCUMENT) {
try {
LibertyWorkspace workspace = LibertyProjectsManager.getInstance().getWorkspaceFolder(saveContext.getUri());
if (workspace != null) {
SettingsService.getInstance()
.populateVariablesForWorkspace(workspace);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
LOGGER.info("Liberty XML variables updated");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,10 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Logger;
import java.util.stream.Collectors;

public class LibertyHoverParticipant implements IHoverParticipant {
private static final Logger LOGGER = Logger.getLogger(LibertyHoverParticipant.class.getName());
Expand All @@ -47,6 +46,15 @@ public Hover onAttributeName(IHoverRequest request, CancelChecker cancelChecker)

@Override
public Hover onAttributeValue(IHoverRequest request, CancelChecker cancelChecker) {
List<String> variables = LibertyUtils.getVariablesFromTextContent(request.getNode().getTextContent());
if (variables.size() == 1) {
Properties variableMap = SettingsService.getInstance()
.getVariablesForServerXml(request.getXMLDocument()
.getDocumentURI());
if (variableMap.containsKey(variables.get(0))) {
return new Hover(new MarkupContent("plaintext", String.format("Current value is %s", variableMap.get(variables.get(0)))));
}
}
return null;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*******************************************************************************
* 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 com.google.gson.JsonPrimitive;
import io.openliberty.tools.langserver.lemminx.services.SettingsService;
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.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Logger;
import java.util.stream.Collectors;

public class ReplaceVariable implements ICodeActionParticipant {
private static final Logger LOGGER = Logger.getLogger(ReplaceVariable.class.getName());

@Override
public void doCodeAction(ICodeActionRequest request, List<CodeAction> codeActions, CancelChecker cancelChecker) {
Diagnostic diagnostic = request.getDiagnostic();
DOMDocument document = request.getDocument();
try {
// Get a list of variables that partially match the specified invalid variables.
// Create a code action to replace the invalid variable with each possible valid variable.
// First, get the invalid variable.
String invalidVariable = null;
if (diagnostic.getData() instanceof JsonPrimitive) {
invalidVariable = ((JsonPrimitive) diagnostic.getData()).getAsString();
}
if (diagnostic.getData() instanceof String) {
invalidVariable = (String) diagnostic.getData();
}
final boolean replaceVariable = invalidVariable != null && !invalidVariable.isBlank();

if (replaceVariable) {
Properties existingVariables=SettingsService.getInstance().getVariablesForServerXml(document.getDocumentURI());
// filter with entered word -> may not be required
String finalInvalidVariable = invalidVariable;
Set<Map.Entry<Object, Object>> filteredVariables = existingVariables
.entrySet().stream().filter(entry ->
entry.getKey().toString().toLowerCase()
.contains(finalInvalidVariable.toLowerCase()))
.collect(Collectors.toSet());
for (Map.Entry<Object, Object> nextVariable : filteredVariables) {
String title = "Replace Variable with " + nextVariable.getKey();
String variableInDoc = String.format("${%s}", nextVariable.getKey().toString());
codeActions.add(CodeActionFactory.replace(title, diagnostic.getRange(), variableInDoc, document.getTextDocument(), diagnostic));
}
/*for (Map.Entry<Object, Object> nextVariable : existingVariables.entrySet()) {
String title = "Replace Variable with " + nextVariable.getKey() + " with value = " + nextVariable.getValue();
codeActions.add(CodeActionFactory.replace(title, diagnostic.getRange(), nextVariable.getKey().toString(), document.getTextDocument(), diagnostic));
}*/
}
} catch (Exception e) {
// BadLocationException not expected
LOGGER.warning("Could not generate code action for replace variable: " + e);
}
}
}
Loading
Loading