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 2.0 #325

Merged
merged 12 commits into from
Dec 24, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,15 @@ public void testInvalidVariableDiagnostic() {
);

Diagnostic dup1 = new Diagnostic();
dup1.setRange(r(5, 36, 5, 55));
dup1.setRange(r(5, 34, 5, 56));
dup1.setCode("incorrect_variable");
dup1.setSource("liberty-lemminx");
dup1.setSeverity(DiagnosticSeverity.Error);
dup1.setMessage("ERROR: The variable \"default.httpsl.port\" does not exist.");
dup1.setData("default.httpsl.port");

Diagnostic dup2 = new Diagnostic();
dup2.setRange(r(7, 31, 7, 50));
dup2.setRange(r(7, 29, 7, 51));
dup2.setCode("incorrect_variable");
dup2.setSource("liberty-lemminx");
dup2.setSeverity(DiagnosticSeverity.Error);
Expand Down Expand Up @@ -156,7 +156,7 @@ public void testInvalidVariableDiagnosticWithCodeAction() throws IOException, Ba
);

Diagnostic invalid1 = new Diagnostic();
invalid1.setRange(r(7, 31, 7, 44));
invalid1.setRange(r(7, 29, 7, 45));
invalid1.setCode("incorrect_variable");
invalid1.setMessage("ERROR: The variable \"default.https\" does not exist.");
invalid1.setData("default.https");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,24 @@ public void onAttributeValue(String valuePrefix, ICompletionRequest request, ICo
Properties variableProps = SettingsService.getInstance()
.getVariablesForServerXml(request.getXMLDocument()
.getDocumentURI());
String variableName = valuePrefix.replace("$", "")
.replace("{", "")
.replace("}", "");
variableProps.entrySet().stream().filter(it -> it.getKey().toString().toLowerCase().contains(variableName.toLowerCase()))
// value prefix will contain all existing attribute value, till the cursor
String variableName = valuePrefix;
String replacePrefix;
if (valuePrefix.contains("${")) {
variableName = valuePrefix.substring(valuePrefix.lastIndexOf("${"))
cherylking marked this conversation as resolved.
Show resolved Hide resolved
.replace("${", "");
if (variableName.contains("}")) {
variableName = variableName.replace("}", "");
}
// existing variables
replacePrefix = valuePrefix.substring(0, valuePrefix.lastIndexOf("${"));
} else {
replacePrefix = "";
}
String finalVariableName = variableName;
variableProps.entrySet().stream().filter(it -> it.getKey().toString().toLowerCase().contains(finalVariableName.toLowerCase()))
.forEach(variableProp -> {
String varValue = String.format("${%s}", variableProp.getKey());
String varValue = String.format("%s${%s}", replacePrefix, variableProp.getKey());

Either<TextEdit, InsertReplaceEdit> edit = Either.forLeft(new
TextEdit(request.getReplaceRange(), varValue));
Expand All @@ -67,7 +79,7 @@ public void onAttributeValue(String valuePrefix, ICompletionRequest request, ICo
completionItem.setTextEdit(edit);
completionItem.setFilterText(variableProp.getKey().toString());
completionItem.setKind(CompletionItemKind.Value);
completionItem.setDocumentation(String.format("%s = %s", variableProp.getKey(),variableProp.getValue()));
completionItem.setDocumentation(String.format("%s = %s", variableProp.getKey(), variableProp.getValue()));
cherylking marked this conversation as resolved.
Show resolved Hide resolved
response.addCompletionItem(completionItem);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ private void validateVariables(DOMDocument domDocument, List<Diagnostic> diagnos
for (VariableLoc variable : variables) {
if (!variablesMap.containsKey(variable.getValue())) {
String variableInDoc = String.format("${%s}", variable.getValue());
Range range = XMLPositionUtility.createRange(variable.getStartLoc(),variable.getEndLoc(),
Range range = XMLPositionUtility.createRange(variable.getStartLoc()-2,variable.getEndLoc()+1,
cherylking marked this conversation as resolved.
Show resolved Hide resolved
domDocument);
String message = "ERROR: The variable \"" + variable.getValue() + "\" does not exist.";

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.FileWatchService;
import io.openliberty.tools.langserver.lemminx.services.LibertyWorkspace;
import org.eclipse.lemminx.services.extensions.IDocumentLinkParticipant;
import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionParticipant;
Expand All @@ -26,6 +27,8 @@
import org.eclipse.lsp4j.InitializeParams;
import org.eclipse.lsp4j.WorkspaceFolder;

import java.io.File;
import java.nio.file.Path;
import java.util.List;
import java.util.logging.Logger;

Expand Down Expand Up @@ -77,6 +80,19 @@ public void start(InitializeParams initializeParams, XMLExtensionsRegistry xmlEx
} catch (Exception e) {
throw new RuntimeException(e);
}

// for each workspace, a file alteration observer is added
for (LibertyWorkspace workspace : LibertyProjectsManager.getInstance().getLibertyWorkspaceFolders()) {
// checking for any changes in target folder
Path libertyPath = new File(workspace.getWorkspaceURI().getPath(),
"target").toPath();
cherylking marked this conversation as resolved.
Show resolved Hide resolved
try {
FileWatchService.getInstance()
.addFileAlterationObserver(libertyPath.toString(), workspace);
} catch (Exception e) {
LOGGER.warning("unable to add file alteration observer for path " + libertyPath);
}
}
}

@Override
Expand All @@ -90,6 +106,7 @@ public void stop(XMLExtensionsRegistry xmlExtensionsRegistry) {
xmlExtensionsRegistry.unregisterHoverParticipant(hoverParticipant);
xmlExtensionsRegistry.unregisterDiagnosticsParticipant(diagnosticsParticipant);
xmlExtensionsRegistry.unregisterCodeActionParticipant(codeActionsParticipant);
FileWatchService.getInstance().cleanFileMonitors();
}

// Do save is called on startup with a Settings update
Expand All @@ -103,17 +120,5 @@ 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
@@ -0,0 +1,135 @@
/*******************************************************************************
* 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.services;

import io.openliberty.tools.langserver.lemminx.util.LibertyConstants;
import io.openliberty.tools.langserver.lemminx.util.LibertyUtils;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;

import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;

public class FileWatchService {

private final Set<FileAlterationObserver> fileObservers = new HashSet<>();
private final Set<FileAlterationMonitor> monitors = new HashSet<>();

private static final FileWatchService instance = new FileWatchService();

public static FileWatchService getInstance() {
return instance;
}

private static final Logger LOGGER = Logger.getLogger(FileWatchService.class.getName());

private FileWatchService() {
}

/**
* add observer for file changes
*
* @param parentPath parent location
* @param workspace workspace
*/
public void addFileAlterationObserver(String parentPath, LibertyWorkspace workspace)
throws Exception {
FileAlterationObserver observer = getFileAlterationObserver(parentPath, workspace);
observer.initialize();
fileObservers.add(observer);
FileAlterationMonitor monitor = new FileAlterationMonitor();
monitor.addObserver(observer);
monitor.start();
monitors.add(monitor);
}

private FileAlterationObserver getFileAlterationObserver(final String parentPath, LibertyWorkspace workspace) {
FileAlterationObserver observer = new FileAlterationObserver(parentPath);
addFileAlterationListener(observer, workspace);
return observer;
}

private void addFileAlterationListener(FileAlterationObserver observer, LibertyWorkspace workspace) {
observer.addListener(new FileAlterationListenerAdaptor() {
@Override
public void onDirectoryCreate(File file) {
onAlteration(file, workspace);
}

@Override
public void onDirectoryDelete(File file) {
onAlteration(file, workspace);
}

@Override
public void onDirectoryChange(File file) {
onAlteration(file, workspace);
}

@Override
public void onFileCreate(File file) {
onAlteration(file, workspace);
}

@Override
public void onFileDelete(File file) {
onAlteration(file, workspace);
}

@Override
public void onFileChange(File file) {
onAlteration(file, workspace);
}

/**
* update variables on file alteration, if modified file is a config
*
* @param file changed file
* @param workspace current workspace
*/
private void onAlteration(File file, LibertyWorkspace workspace) {
boolean watchedFileChanged = LibertyConstants.filesToWatch.stream().anyMatch(fileName -> file.getName().contains(fileName));
boolean isConfigXmlFile = false;
try {
isConfigXmlFile = LibertyUtils.isConfigXMLFile(file.getCanonicalPath());
} catch (IOException e) {
LOGGER.warning("Liberty XML variables cannot be updated for file path %s with error %s"
.formatted(file.getPath(), e.getMessage()));
}
if (watchedFileChanged || isConfigXmlFile) {
SettingsService.getInstance().populateVariablesForWorkspace(workspace);
LOGGER.info("Liberty XML variables updated for workspace URI " + workspace.getWorkspaceString());
}
}
});
}

/**
* clean all monitors for all workspaces
*/
public void cleanFileMonitors() {
fileObservers.clear();
try {
for (FileAlterationMonitor monitor : monitors) {
monitor.stop();
}
} catch (Exception e) {
LOGGER.warning("Issue while removing file monitors with error %s"
.formatted(e.getMessage()));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
*******************************************************************************/
package io.openliberty.tools.langserver.lemminx.util;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public final class LibertyConstants {
Expand Down Expand Up @@ -74,4 +76,6 @@ private LibertyConstants() {

public static String changedFeatureNameDiagMessage="ERROR: The %s feature cannot be configured with the %s feature because they are two different versions of the same feature. " +
"The feature name changed from %s to %s for Jakarta EE. Remove one of the features.";

public static List<String> filesToWatch= Arrays.asList(SERVER_XML,"server.env","bootstrap.properties");
cherylking marked this conversation as resolved.
Show resolved Hide resolved
}
Loading
Loading