diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java index 0d018ff97..7be296d18 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2023 Pivotal, Inc. + * Copyright (c) 2017, 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 @@ -44,4 +44,6 @@ public class Constants { public static final String PREF_START_LS_EARLY = "start.boot-ls.early"; public static final String PREF_COMMON_PROPS_METADATA = "boot-java.common.properties-metadata"; + + public static final String PREF_MODULITH = "boot-java.modulith-project-tracking"; } diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/DelegatingStreamConnectionProvider.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/DelegatingStreamConnectionProvider.java index 9243794ff..c97921f53 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/DelegatingStreamConnectionProvider.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/DelegatingStreamConnectionProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2023 Pivotal, Inc. + * Copyright (c) 2017, 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 @@ -212,6 +212,7 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi bootJavaObj.put("change-detection", bootChangeDetection); bootJavaObj.put("validation", validation); bootJavaObj.put("remote-apps", getAllRemoteApps()); + bootJavaObj.put("modulith-project-tracking", preferenceStore.getBoolean(Constants.PREF_MODULITH)); bootJavaObj.put("rewrite", Map.of( "recipe-filters", StringListEditor.decode(preferenceStore.getString(Constants.PREF_REWRITE_RECIPE_FILTERS)), diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/BootJavaPreferencesPage.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/BootJavaPreferencesPage.java index 2d2109326..8cec47a46 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/BootJavaPreferencesPage.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/prefs/BootJavaPreferencesPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2023 Pivotal, Inc. + * Copyright (c) 2017, 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 @@ -42,6 +42,9 @@ public class BootJavaPreferencesPage extends FieldEditorPreferencePage implement addField(new BooleanFieldEditor(Constants.PREF_SCAN_JAVA_TEST_SOURCES, "Scan Java test sources", fieldEditorParent)); addField(new BooleanFieldEditor(Constants.PREF_CHANGE_DETECTION, "Live Boot Change Detection", fieldEditorParent)); + + // Experimental Modulith support + addField(new BooleanFieldEditor(Constants.PREF_MODULITH, "Spring Boot Modulith automatic project tracking and metadata update", fieldEditorParent)); Composite c = new Composite(fieldEditorParent, SWT.NONE); GridDataFactory.fillDefaults().grab(true, false).applyTo(c); 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 48cb942d0..5b92f75e0 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 @@ -60,6 +60,8 @@ public class PrefsInitializer extends AbstractPreferenceInitializer { "org.springframework.rewrite.test.*", "rewrite.test.*" })); + + preferenceStore.setDefault(Constants.PREF_MODULITH, true); } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootJavaConfig.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootJavaConfig.java index 1954686e5..169cebe21 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootJavaConfig.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootJavaConfig.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2023 Pivotal, Inc. + * Copyright (c) 2017, 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 @@ -91,6 +91,11 @@ public class BootJavaConfig implements InitializingBean { return enabled != null && enabled.booleanValue(); } + public boolean isModulithAutoProjectTrackingEnabled() { + Boolean enabled = settings.getBoolean("boot-java", "modulith-project-tracking"); + return enabled != null && enabled.booleanValue(); + } + public String[] xmlBeansFoldersToScan() { String foldersStr = settings.getString("boot-java", "support-spring-xml-config", "scan-folders"); if (foldersStr != null) { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/modulith/ModulithService.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/modulith/ModulithService.java index 091367b75..aa99c785e 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/modulith/ModulithService.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/modulith/ModulithService.java @@ -76,11 +76,15 @@ public class ModulithService { private static final String CMD_LIST_MODULITH_PROJECTS = "sts/modulith/projects"; private final ExecutorService executor; + private final ProjectObserver.Listener projectListener; + private final ProjectObserver projectObserver; + private final JavaProjectFinder projectFinder; private SimpleLanguageServer server; private SpringSymbolIndex springIndex; private BootJavaReconcileEngine reconciler; private BootJavaConfig config; + private boolean autoTrackingProjects; private Map cache; private Map> metadataRequested; @@ -94,6 +98,8 @@ public class ModulithService { BootJavaReconcileEngine reconciler, BootJavaConfig config ) { + this.projectFinder = projectFinder; + this.projectObserver = projectObserver; this.config = config; this.cache = new ConcurrentHashMap<>(); this.metadataRequested = new ConcurrentHashMap<>(); @@ -102,8 +108,9 @@ public class ModulithService { this.springIndex = springIndex; this.reconciler = reconciler; this.executor = Executors.newCachedThreadPool(); + this.autoTrackingProjects = false; - projectObserver.addListener(new ProjectObserver.Listener() { + this.projectListener = new ProjectObserver.Listener() { @Override public void deleted(IJavaProject project) { @@ -113,13 +120,7 @@ public class ModulithService { @Override public void created(IJavaProject project) { - if (isModulithDependentProject(project)) { - if (anyClassFilesPresent(project)) { - requestMetadata(project, DEBOUNCE_TIME).thenAccept(res -> startListening(project)); - } else { - startListening(project); - } - } + projectAdded(project); } @Override @@ -135,7 +136,7 @@ public class ModulithService { } } } - }); + }; server.onCommand(CMD_MODULITH_REFRESH, params -> { String uri = ((JsonElement) params.getArguments().get(0)).getAsString(); @@ -150,6 +151,31 @@ public class ModulithService { ); }); + config.addListener(v -> setAutoTrackingProjects(config.isModulithAutoProjectTrackingEnabled())); + + } + + private void projectAdded(IJavaProject project) { + if (isModulithDependentProject(project)) { + if (anyClassFilesPresent(project)) { + requestMetadata(project, DEBOUNCE_TIME).thenAccept(res -> startListening(project)); + } else { + startListening(project); + } + } + } + + private void setAutoTrackingProjects(boolean autoTrackingProjects) { + if (this.autoTrackingProjects != autoTrackingProjects) { + this.autoTrackingProjects = autoTrackingProjects; + if (autoTrackingProjects) { + projectObserver.addListener(projectListener); + projectFinder.all().forEach(this::projectAdded); + } else { + projectObserver.removeListener(projectListener); + projectFinder.all().forEach(this::stopListening); + } + } } private boolean startListening(IJavaProject project) { diff --git a/vscode-extensions/vscode-spring-boot/package.json b/vscode-extensions/vscode-spring-boot/package.json index 4b6cddab9..c906c6802 100644 --- a/vscode-extensions/vscode-spring-boot/package.json +++ b/vscode-extensions/vscode-spring-boot/package.json @@ -229,6 +229,11 @@ }, "description": "Array of jmx urls pointing to remote spring boot applications to poll for live hover information. A typical url looks something like this: `service:jmx:rmi://localhost:9111/jndi/rmi://localhost:9111/jmxrmi`" }, + "boot-java.modulith-project-tracking": { + "type": "boolean", + "default": true, + "description": "Spring Boot Modulith automatic project tracking and metadata update" + }, "boot-java-vscode-only.test-jars": { "type": "boolean", "default": true,