diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/plugin.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/plugin.xml
index 1484a24d7..600093450 100644
--- a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/plugin.xml
+++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/plugin.xml
@@ -17,6 +17,7 @@
name="Convert .yaml to .properties">
+
diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/ConvertPropertiesToYamlHandler.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/ConvertPropertiesToYamlHandler.java
index 13a14d42b..96a70a0f3 100644
--- a/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/ConvertPropertiesToYamlHandler.java
+++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.refactoring/src/org/springframework/ide/eclipse/boot/refactoring/ConvertPropertiesToYamlHandler.java
@@ -24,7 +24,6 @@ import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
import org.eclipse.ui.handlers.HandlerUtil;
import org.springsource.ide.eclipse.commons.livexp.util.Log;
-import org.eclipse.ltk.core.refactoring.RefactoringContext;
public class ConvertPropertiesToYamlHandler extends AbstractHandler {
diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/icons/boot-icon.png b/eclipse-language-servers/org.springframework.tooling.boot.ls/icons/boot-icon.png
new file mode 100644
index 000000000..de88ef0d5
Binary files /dev/null and b/eclipse-language-servers/org.springframework.tooling.boot.ls/icons/boot-icon.png differ
diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/plugin.xml b/eclipse-language-servers/org.springframework.tooling.boot.ls/plugin.xml
index de1ec1509..1d944e022 100644
--- a/eclipse-language-servers/org.springframework.tooling.boot.ls/plugin.xml
+++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/plugin.xml
@@ -280,6 +280,14 @@
class="org.springframework.tooling.boot.ls.commands.AddStartersHandler"
commandId="spring.initializr.addStarters">
+
+
+
+
@@ -329,6 +337,16 @@
typeId="org.eclipse.lsp4e.pathParameterType">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ls.getWorkspaceService().executeCommand(commandParams));
+
+ }
+
+ return null;
+ }
+
+ abstract protected String getTargetExtension();
+
+ abstract protected String getCommandId();
+
+ private IFile getTargetFile(IFile sourceFile, String ext) {
+ IProject project = sourceFile.getProject();
+ IPath eclipsePath = sourceFile.getProjectRelativePath();
+ IPath dir = eclipsePath.removeLastSegments(1);
+ String fileName = sourceFile.getName();
+ String fileNoExt = fileName.substring(0, fileName.length() - sourceFile.getFileExtension().length() - 1);
+ IFile target = project.getFile(dir.append("%s.%s".formatted(fileNoExt, ext)));
+ for (int i = 1; i < Integer.MAX_VALUE && target.exists(); i++) {
+ target = project.getFile(dir.append("%s-%d.%s".formatted(fileNoExt, i, ext)));
+ }
+ return target;
+ }
+
+ private IFile getSourceFile(ExecutionEvent event) {
+ ISelection selection = HandlerUtil.getActiveMenuSelection(event);
+ IStructuredSelection ss = null;
+ if (selection instanceof IStructuredSelection) {
+ ss = (IStructuredSelection) selection;
+ } else {
+ selection = HandlerUtil.getActiveMenuEditorInput(event);
+ if (selection instanceof IStructuredSelection) {
+ ss = (IStructuredSelection) selection;
+ }
+ }
+ if (ss!=null && !ss.isEmpty()) {
+ return asFile(ss.getFirstElement());
+ }
+ return null;
+ }
+
+ private IFile asFile(Object selectedElement) {
+ if (selectedElement instanceof IFile) {
+ return (IFile) selectedElement;
+ }
+ if (selectedElement instanceof IAdaptable) {
+ return ((IAdaptable) selectedElement).getAdapter(IFile.class);
+ }
+ return null;
+ }
+
+ public static class ConvertPropertiesToYamlHandler extends ConvertBootPropertiesHanlder {
+
+ @Override
+ protected String getTargetExtension() {
+ return "yml";
+ }
+
+ @Override
+ protected String getCommandId() {
+ return "sts/boot/props-to-yaml";
+ }
+
+ }
+
+ public static class ConvertYamlToPropertiesHanlder extends ConvertBootPropertiesHanlder {
+
+ @Override
+ protected String getTargetExtension() {
+ return "properties";
+ }
+
+ @Override
+ protected String getCommandId() {
+ return "sts/boot/yaml-to-props";
+ }
+
+ }
+
+
+}
diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/PrefsInitializer.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/PrefsInitializer.java
index 2b05ad3ba..391c91bae 100644
--- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/PrefsInitializer.java
+++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/PrefsInitializer.java
@@ -61,6 +61,7 @@ public class PrefsInitializer extends AbstractPreferenceInitializer {
}));
preferenceStore.setDefault(Constants.PREF_MODULITH, true);
+
}
}
diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/CompositeLanguageServerComponents.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/CompositeLanguageServerComponents.java
index 793e25a90..c095971ed 100644
--- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/CompositeLanguageServerComponents.java
+++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/composable/CompositeLanguageServerComponents.java
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.commons.languageserver.composable;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -33,6 +34,7 @@ import org.eclipse.lsp4j.InlayHintParams;
import org.eclipse.lsp4j.WorkspaceSymbol;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
+import org.springframework.context.ApplicationContext;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
import org.springframework.ide.vscode.commons.languageserver.util.CodeActionHandler;
@@ -40,11 +42,13 @@ import org.springframework.ide.vscode.commons.languageserver.util.CodeLensHandle
import org.springframework.ide.vscode.commons.languageserver.util.DocumentSymbolHandler;
import org.springframework.ide.vscode.commons.languageserver.util.HoverHandler;
import org.springframework.ide.vscode.commons.languageserver.util.InlayHintHandler;
+import org.springframework.ide.vscode.commons.languageserver.util.LanguageComputer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.commons.util.text.IRegion;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
+import org.springframework.ide.vscode.commons.util.text.LazyTextDocument;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import com.google.common.collect.ImmutableMap;
@@ -65,8 +69,8 @@ public class CompositeLanguageServerComponents implements LanguageServerComponen
}
}
- public CompositeLanguageServerComponents build(SimpleLanguageServer server) {
- return new CompositeLanguageServerComponents(server, this);
+ public CompositeLanguageServerComponents build(ApplicationContext appContext) {
+ return new CompositeLanguageServerComponents(appContext, this);
}
}
@@ -78,7 +82,8 @@ public class CompositeLanguageServerComponents implements LanguageServerComponen
private final DocumentSymbolHandler docSymbolHandler;
private final InlayHintHandler inlayHintHandler;
- public CompositeLanguageServerComponents(SimpleLanguageServer server, Builder builder) {
+ public CompositeLanguageServerComponents(ApplicationContext appContext, Builder builder) {
+ SimpleLanguageServer server = appContext.getBean(SimpleLanguageServer.class);
this.componentsByLanguageId = ImmutableMap.copyOf(builder.componentsByLanguageId);
//Create composite Reconcile engine
if (componentsByLanguageId.values().stream().flatMap(l -> l.stream()).map(LanguageServerComponents::getReconcileEngine).anyMatch(Optional::isPresent)) {
@@ -145,7 +150,7 @@ public class CompositeLanguageServerComponents implements LanguageServerComponen
@Override
public List extends CodeLens> handle(CancelChecker cancelToken, CodeLensParams params) {
- TextDocument doc = server.getTextDocumentService().getLatestSnapshot(params.getTextDocument().getUri());
+ TextDocument doc = getDoc(appContext, params.getTextDocument().getUri());
LanguageId language = doc.getLanguageId();
List subComponents = componentsByLanguageId.get(language);
if (subComponents != null) {
@@ -183,17 +188,15 @@ public class CompositeLanguageServerComponents implements LanguageServerComponen
@Override
public List extends WorkspaceSymbol> handle(DocumentSymbolParams params) {
- TextDocument doc = server.getTextDocumentService().getLatestSnapshot(params.getTextDocument().getUri());
- if (doc != null) {
- LanguageId language = doc.getLanguageId();
- List subComponents = componentsByLanguageId.get(language);
- if (subComponents != null) {
- return subComponents.stream()
- .map(sc -> sc.getDocumentSymbolProvider())
- .filter(ds -> ds.isPresent())
- .flatMap(ds -> ds.get().handle(params).stream())
- .collect(Collectors.toList());
- }
+ TextDocument doc = getDoc(appContext, params.getTextDocument().getUri());
+ LanguageId language = doc.getLanguageId();
+ List subComponents = componentsByLanguageId.get(language);
+ if (subComponents != null) {
+ return subComponents.stream()
+ .map(sc -> sc.getDocumentSymbolProvider())
+ .filter(ds -> ds.isPresent())
+ .flatMap(ds -> ds.get().handle(params).stream())
+ .collect(Collectors.toList());
}
//No applicable subEngine...
return Collections.emptyList();
@@ -244,5 +247,22 @@ public class CompositeLanguageServerComponents implements LanguageServerComponen
public Optional getInlayHintHandler() {
return Optional.of(inlayHintHandler);
}
+
+ private static TextDocument getDoc(ApplicationContext appContext, String uri) {
+
+ TextDocument doc = appContext.getBean(SimpleLanguageServer.class).getTextDocumentService().getLatestSnapshot(uri);
+
+ if (doc == null) {
+ LanguageComputer languageComputer = appContext.getBean(LanguageComputer.class);
+ if (languageComputer != null) {
+ LanguageId language = languageComputer.computeLanguage(URI.create(uri));
+ if (language != null) {
+ doc = new LazyTextDocument(uri, language);
+ }
+ }
+ }
+
+ return doc;
+ }
}
diff --git a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/LazyTextDocument.java b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/LazyTextDocument.java
index 9f3af82fa..224c03472 100644
--- a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/LazyTextDocument.java
+++ b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/LazyTextDocument.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2022 VMware, Inc.
+ * Copyright (c) 2022, 2024 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -39,12 +39,6 @@ public class LazyTextDocument extends TextDocument {
});
}
- @Override
- public String get() {
- // TODO Auto-generated method stub
- return super.get();
- }
-
@Override
protected synchronized Text getText() {
if (!loaded) {
diff --git a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/YamlPath.java b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/YamlPath.java
index 7844dd5f8..62d72d0dc 100644
--- a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/YamlPath.java
+++ b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/YamlPath.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2015, 2016 Pivotal, Inc.
+ * Copyright (c) 2015, 2024 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,6 +13,8 @@ package org.springframework.ide.vscode.commons.yaml.path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
import java.util.stream.Stream;
import org.springframework.ide.vscode.commons.yaml.ast.NodeRef;
@@ -22,6 +24,8 @@ import org.springframework.ide.vscode.commons.yaml.ast.NodeRef.TupleValueRef;
import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil;
import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment.YamlPathSegmentType;
+import com.google.common.collect.ImmutableList;
+
import reactor.core.publisher.Flux;
/**
@@ -74,14 +78,49 @@ public class YamlPath extends AbstractYamlTraversal {
* Parse a YamlPath from a dotted property name. The segments are obtained
* by spliting the name at each dot.
*/
+// public static YamlPath fromProperty(String propName) {
+// ArrayList segments = new ArrayList();
+// for (String s : propName.split("\\.")) {
+// segments.add(YamlPathSegment.valueAt(s));
+// }
+// return new YamlPath(segments);
+// }
+ /**
+ * Parse a YamlPath from a dotted property name. The segments are obtained
+ * by splitting the name at each dot.
+ */
public static YamlPath fromProperty(String propName) {
- ArrayList segments = new ArrayList();
- for (String s : propName.split("\\.")) {
- segments.add(YamlPathSegment.valueAt(s));
+ ImmutableList.Builder segments = ImmutableList.builder();
+ String delim = ".[]";
+ StringTokenizer tokens = new StringTokenizer(propName, delim, true);
+ try {
+ while (tokens.hasMoreTokens()) {
+ String token = tokens.nextToken(delim);
+ if (token.equals(".") || token.equals("]")) {
+ //Skip it silently
+ } else if (token.equals("[")) {
+ String bracketed = tokens.nextToken("]");
+ if (bracketed.equals("]")) {
+ //empty string between []? Makes no sense, so ignore that.
+ } else {
+ try {
+ int index = Integer.parseInt(bracketed);
+ segments.add(YamlPathSegment.valueAt(index));
+ } catch (NumberFormatException e) {
+ segments.add(YamlPathSegment.valueAt(bracketed));
+ }
+ }
+ } else {
+ segments.add(YamlPathSegment.valueAt(token));
+ }
+ }
+ } catch (NoSuchElementException e) {
+ //Ran out of tokens.
}
- return new YamlPath(segments);
+ return new YamlPath(segments.build());
}
+
/**
* Create a YamlPath with a single segment (i.e. like 'fromProperty', but does
* not parse '.' as segment separators.
diff --git a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java
index 8287f9370..c1bd11940 100644
--- a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java
+++ b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016, 2023 Pivotal, Inc.
+ * Copyright (c) 2016, 2024 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -87,6 +87,8 @@ import org.eclipse.lsp4j.RegistrationParams;
import org.eclipse.lsp4j.RenameFile;
import org.eclipse.lsp4j.ResourceOperation;
import org.eclipse.lsp4j.ResourceOperationKind;
+import org.eclipse.lsp4j.ShowDocumentParams;
+import org.eclipse.lsp4j.ShowDocumentResult;
import org.eclipse.lsp4j.ShowMessageRequestParams;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.TextDocumentClientCapabilities;
@@ -442,6 +444,11 @@ public class LanguageServerHarness {
public void liveProcessLogLevelUpdated(LiveProcessLoggersSummary processKey) {
}
+ @Override
+ public CompletableFuture showDocument(ShowDocumentParams params) {
+ return CompletableFuture.completedFuture(new ShowDocumentResult(true));
+ }
+
});
}
@@ -810,15 +817,14 @@ public class LanguageServerHarness {
.collect(Collectors.toList());
}
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public void perform(Command command) throws Exception {
+ public Object perform(Command command) throws Exception {
List