GH-1521: removed old prototype around detecting differences between different runs of the same project

Fixes GH-1521
This commit is contained in:
Martin Lippert
2025-03-24 17:07:24 +01:00
parent 04ff252215
commit 7ae1e52daa
11 changed files with 0 additions and 611 deletions

View File

@@ -28,8 +28,6 @@ public class Constants {
public static final String PREF_XML_CONFIGS_HYPERLINKS = "boot-java.support-spring-xml-config.hyperlinks";
public static final String PREF_XML_CONFIGS_CONTENT_ASSIST = "boot-java.support-spring-xml-config.content-assist";
public static final String PREF_CHANGE_DETECTION = "boot-java.change-detection.on";
public static final String PREF_JAVA_RECONCILE = "boot-java.java.reconcile";
public static final String PREF_REWRITE_RECIPE_FILTERS = "boot-java.rewrite.recipe-filters";

View File

@@ -180,7 +180,6 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
Map<String, Object> liveInformation = new HashMap<>();
Map<String, Object> liveInformationFetchData = new HashMap<>();
Map<String, Object> supportXML = new HashMap<>();
Map<String, Object> bootChangeDetection = new HashMap<>();
Map<String, Object> scanTestJavaSources = new HashMap<>();
Map<String, Object> javaSettings = new HashMap<>();
Map<String, Object> javaCompletionSettings = new HashMap<>();
@@ -197,7 +196,6 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
supportXML.put("scan-folders", preferenceStore.getString(Constants.PREF_XML_CONFIGS_SCAN_FOLDERS));
supportXML.put("hyperlinks", preferenceStore.getString(Constants.PREF_XML_CONFIGS_HYPERLINKS));
supportXML.put("content-assist", preferenceStore.getString(Constants.PREF_XML_CONFIGS_CONTENT_ASSIST));
bootChangeDetection.put("on", preferenceStore.getBoolean(Constants.PREF_CHANGE_DETECTION));
scanTestJavaSources.put("on", preferenceStore.getBoolean(Constants.PREF_SCAN_JAVA_TEST_SOURCES));
javaCompletionSettings.put("inject-bean", preferenceStore.getBoolean(Constants.PREF_COMPLETION_JAVA_INJECT_BEAN));
@@ -209,9 +207,7 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
bootJavaObj.put("jpql", preferenceStore.getBoolean(Constants.PREF_JPQL));
bootJavaObj.put("live-information", liveInformation);
bootJavaObj.put("support-spring-xml-config", supportXML);
bootJavaObj.put("change-detection", bootChangeDetection);
bootJavaObj.put("scan-java-test-sources", scanTestJavaSources);
bootJavaObj.put("change-detection", bootChangeDetection);
bootJavaObj.put("java", javaSettings);
bootJavaObj.put("remote-apps", getAllRemoteApps());
bootJavaObj.put("modulith-project-tracking", preferenceStore.getBoolean(Constants.PREF_MODULITH));

View File

@@ -41,8 +41,6 @@ public class BootJavaPreferencesPage extends FieldEditorPreferencePage implement
addField(new BooleanFieldEditor(Constants.PREF_START_LS_EARLY, "Start Language Server at startup if Spring Boot is a dependency", fieldEditorParent));
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));
// JPQL Support switch
addField(new BooleanFieldEditor(Constants.PREF_JPQL, "JPA Query language support", fieldEditorParent));

View File

@@ -40,8 +40,6 @@ public class PrefsInitializer extends AbstractPreferenceInitializer {
preferenceStore.setDefault(Constants.PREF_XML_CONFIGS_CONTENT_ASSIST, true);
preferenceStore.setDefault(Constants.PREF_XML_CONFIGS_SCAN_FOLDERS, "src/main");
preferenceStore.setDefault(Constants.PREF_CHANGE_DETECTION, false);
preferenceStore.setDefault(Constants.PREF_SCAN_JAVA_TEST_SOURCES, false);
preferenceStore.setDefault(Constants.PREF_JAVA_RECONCILE, true);

View File

@@ -131,11 +131,6 @@ public class BootJavaConfig implements InitializingBean {
return cleanedFolders.toArray(new String[cleanedFolders.size()]);
}
public boolean isChangeDetectionEnabled() {
Boolean enabled = settings.getBoolean("boot-java", "change-detection", "on");
return enabled != null && enabled.booleanValue();
}
public boolean isSpelExpressionValidationEnabled() {
Toggle categorySwitch = SpringProblemCategories.SPEL.getToggle();
return isProblemCategoryEnabled(categorySwitch);

View File

@@ -10,7 +10,6 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -63,7 +62,6 @@ import org.springframework.ide.vscode.boot.java.requestmapping.WebfluxHandlerCod
import org.springframework.ide.vscode.boot.java.requestmapping.WebfluxRouteHighlightProdivder;
import org.springframework.ide.vscode.boot.java.spel.SpelSemanticTokens;
import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
import org.springframework.ide.vscode.boot.java.utils.SpringLiveChangeDetectionWatchdog;
import org.springframework.ide.vscode.boot.java.value.ValueHoverProvider;
import org.springframework.ide.vscode.boot.java.value.ValuePropertyReferencesProvider;
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
@@ -111,7 +109,6 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
private final SpringProcessConnectorService liveDataService;
private final SpringLiveChangeDetectionWatchdog liveChangeDetectionWatchdog;
private final ProjectObserver projectObserver;
private final CompilationUnitCache cuCache;
private final ResponseModifier responseModifier;
@@ -179,14 +176,6 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
workspaceService.onWorkspaceSymbol(new BootJavaWorkspaceSymbolHandler(springSymbolIndex,
new LiveAppURLSymbolProvider(liveDataProvider)));
liveChangeDetectionWatchdog = new SpringLiveChangeDetectionWatchdog(
this,
server,
serverParams.projectObserver,
projectFinder,
Duration.ofSeconds(5),
sourceLinks);
spelSemanticTokens = appContext.getBean(SpelSemanticTokens.class);
codeLensHandler = createCodeLensEngine(springIndex, projectFinder, server, spelSemanticTokens);
@@ -211,14 +200,6 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
// live information data fetch params
liveDataService.setMaxRetryCount(config.getLiveInformationFetchDataMaxRetryCount());
liveDataService.setRetryDelayInSeconds(config.getLiveInformationFetchDataRetryDelayInSeconds());
// live change detection watchdog
if (config.isChangeDetectionEnabled()) {
liveChangeDetectionWatchdog.enableHighlights();
}
else {
liveChangeDetectionWatchdog.disableHighlights();
}
log.info("update live process tracker settings - done");
});
@@ -255,11 +236,9 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
}
private void initialized() {
this.liveChangeDetectionWatchdog.start();
}
private void shutdown() {
this.liveChangeDetectionWatchdog.shutdown();
this.cuCache.dispose();
}

View File

@@ -1,60 +0,0 @@
/*******************************************************************************
* Copyright (c) 2018 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.utils;
import java.util.ArrayList;
import java.util.List;
import org.springframework.ide.vscode.boot.java.livehover.v2.LiveBean;
/**
* @author Martin Lippert
*/
public class Change {
// private final SpringBootApp runningApp;
private List<LiveBean> newBeans;
private List<LiveBean> deletedBeans;
// public Change(SpringBootApp runningApp) {
// this.runningApp = runningApp;
// }
//
// public SpringBootApp getRunningApp() {
// return runningApp;
// }
//
public List<LiveBean> getNewBeans() {
return newBeans;
}
public List<LiveBean> getDeletedBeans() {
return deletedBeans;
}
public void addDeletedBean(LiveBean bean) {
if (deletedBeans == null) {
deletedBeans = new ArrayList<>();
}
deletedBeans.add(bean);
}
public void addNewBean(LiveBean bean) {
if (newBeans == null) {
newBeans = new ArrayList<>();
}
newBeans.add(bean);
}
}

View File

@@ -1,120 +0,0 @@
/*******************************************************************************
* Copyright (c) 2018 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.utils;
import java.util.HashMap;
import java.util.Map;
/**
* @author Martin Lippert
*/
public class ChangeDetectionHistory {
private Map<String, ChangeHistory> changeHistory;
public ChangeDetectionHistory() {
this.changeHistory = new HashMap<>();
}
// public Change[] checkForChanges(SpringBootApp[] runningApps) {
// List<Change> result = null;
//
// for (SpringBootApp runningApp : runningApps) {
// String virtualID = getVirtualAppID(runningApp);
//
// if (changeHistory.containsKey(virtualID)) {
// // the standard case
// ChangeHistory appHistory = changeHistory.get(virtualID);
// appHistory.updateProcess(runningApp);
//
// Change change = appHistory.checkForUpdates();
// if (change != null) {
// if (result == null) {
// result = new ArrayList<>();
// }
// result.add(change);
// }
// }
// else {
// String oldAppID = getOldApp(runningApp, runningApps);
// if (oldAppID != null) {
// ChangeHistory oldHistory = changeHistory.remove(oldAppID);
// oldHistory.updateProcess(runningApp);
// changeHistory.put(virtualID, oldHistory);
//
// Change change = oldHistory.checkForUpdates();
// if (change != null) {
// if (result == null) {
// result = new ArrayList<>();
// }
// result.add(change);
// }
// }
// else {
// ChangeHistory newHistory = new ChangeHistory();
// newHistory.updateProcess(runningApp);
// changeHistory.put(virtualID, newHistory);
//
// newHistory.checkForUpdates();
// }
// }
// }
//
// if (result != null) {
// return (Change[]) result.toArray(new Change[result.size()]);
// }
// else {
// return null;
// }
// }
//
// private String getVirtualAppID(SpringBootApp app) {
// return app.getProcessID();
// }
//
// private String getOldApp(SpringBootApp app, SpringBootApp[] allApps) {
// Set<String> histories = this.changeHistory.keySet();
//
// try {
// String commandLine = app.getJavaCommand();
// String[] classpath = app.getClasspath();
//
// for (String oldProcessID : histories) {
// if (this.changeHistory.get(oldProcessID).matchesProcess(commandLine, classpath)
// && processNotRunningAnymore(oldProcessID, allApps)) {
// return oldProcessID;
// }
// }
// }
// catch (Exception e) {
// e.printStackTrace();
// }
//
// return null;
// }
//
// private boolean processNotRunningAnymore(String oldProcessID, SpringBootApp[] allApps) {
// try {
// for (SpringBootApp app : allApps) {
// String id = getVirtualAppID(app);
// if (id != null && id.equals(oldProcessID)) {
// return false;
// }
// }
// }
// catch (Exception e) {
// e.printStackTrace();
// }
//
// return true;
// }
}

View File

@@ -1,128 +0,0 @@
/*******************************************************************************
* Copyright (c) 2018 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.utils;
/**
* @author Martin Lippert
*/
public class ChangeHistory {
// private static final List<LiveBean> EMPTY_BEANS_LIST = new ArrayList<>(0);
//
// private SpringBootApp associatedProcess;
// private String associatedProcessCommand;
// private String[] associatedProcessClasspath;
//
// private LiveBeansModel lastBeans;
//
// public ChangeHistory() {
// }
//
// public void updateProcess(SpringBootApp app) {
// if (this.associatedProcess != app) {
// this.associatedProcess = app;
//
// try {
// this.associatedProcessCommand = app.getJavaCommand();
// this.associatedProcessClasspath = app.getClasspath();
// }
// catch (Exception e) {
// e.printStackTrace();
// }
// }
// }
//
// public boolean matchesProcess(String commandLine, String[] classpath) {
// return this.associatedProcessCommand != null && this.associatedProcessCommand.equals(commandLine)
// && this.associatedProcessClasspath != null && Arrays.deepEquals(this.associatedProcessClasspath, classpath);
// }
//
// public Change checkForUpdates() {
// Change result = null;
//
//// LiveBeansModel currentBeans = this.associatedProcess.getBeans();
//// if (!currentBeans.isEmpty()) {
////
//// if (lastBeans == null) {
//// lastBeans = currentBeans;
//// }
//// else if (lastBeans != null && currentBeans != null) {
//// result = calculateBeansDiff(lastBeans, currentBeans, result);
//// lastBeans = currentBeans;
//// }
//// }
//
// return result;
// }
//
// private Change calculateBeansDiff(LiveBeansModel previous, LiveBeansModel current, Change result) {
// if (previous == current) {
// return result;
// }
//
// Set<String> currentNames = current.getBeanNames();
// Set<String> previousNames = previous.getBeanNames();
//
// Set<String> allNames = new HashSet<>(currentNames);
// allNames.addAll(previousNames);
//
// for (String name : allNames) {
// List<LiveBean> currentBeans = current.getBeansOfName(name);
// List<LiveBean> previousBeans = previous.getBeansOfName(name);
//
// result = calculateBeansDiff(previousBeans, currentBeans, result);
// }
//
// return result;
// }
//
// private Change calculateBeansDiff(List<LiveBean> previousBeans, List<LiveBean> currentBeans, Change result) {
// if (currentBeans == null) currentBeans = EMPTY_BEANS_LIST;
// if (previousBeans == null) previousBeans = EMPTY_BEANS_LIST;
//
// for (LiveBean bean : previousBeans) {
// if (!contains(currentBeans, bean)) {
//
// if (result == null) {
// result = new Change(associatedProcess);
// }
//
// result.addDeletedBean(bean);
// }
// }
//
// for (LiveBean bean : currentBeans) {
// if (!contains(previousBeans, bean)) {
//
// if (result == null) {
// result = new Change(associatedProcess);
// }
//
// result.addNewBean(bean);
// }
// }
//
// return result;
// }
//
// private boolean contains(List<LiveBean> beans, LiveBean bean) {
// for (LiveBean beansFromList : beans) {
// if (StringUtils.equals(beansFromList.getId(), bean.getId())
// && StringUtils.equals(beansFromList.getType(true), bean.getType(true))
// && StringUtils.equals(beansFromList.getResource(), bean.getResource())) {
// return true;
// }
// }
//
// return false;
// }
}

View File

@@ -1,262 +0,0 @@
/*******************************************************************************
* Copyright (c) 2018, 2023 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.utils;
import java.net.URI;
import java.time.Duration;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents;
import org.springframework.ide.vscode.boot.java.links.SourceLinks;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver.Listener;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
/**
* @author Martin Lippert
*/
public class SpringLiveChangeDetectionWatchdog {
public static final Duration DEFAULT_INTERVAL = Duration.ofMillis(5000);
Logger logger = LoggerFactory.getLogger(SpringLiveChangeDetectionWatchdog.class);
private final long POLLING_INTERVAL_MILLISECONDS;
private final SimpleLanguageServer server;
private final SourceLinks sourceLinks;
private final ChangeDetectionHistory changeHistory;
private final Set<URI> observedProjects;
private boolean changeDetectionEnabled = false;
private ScheduledThreadPoolExecutor timer;
public SpringLiveChangeDetectionWatchdog(
BootJavaLanguageServerComponents bootJavaLanguageServerComponents,
SimpleLanguageServer server,
ProjectObserver projectObserver,
JavaProjectFinder projectFinder,
Duration pollingInterval,
SourceLinks sourceLinks
) {
this.observedProjects = new HashSet<URI>();
this.server = server;
this.POLLING_INTERVAL_MILLISECONDS = pollingInterval == null ? DEFAULT_INTERVAL.toMillis() : pollingInterval.toMillis();
this.changeHistory = new ChangeDetectionHistory();
this.sourceLinks = sourceLinks;
if (projectObserver != null) {
projectObserver.addListener(new Listener() {
@Override
public void deleted(IJavaProject project) {
observedProjects.remove(project.getLocationUri());
}
@Override
public void created(IJavaProject project) {
observedProjects.add(project.getLocationUri());
}
@Override
public void changed(IJavaProject project) {
// do nothing
}
});
}
}
public synchronized void start() {
if (changeDetectionEnabled && timer == null) {
logger.debug("Starting SpringLiveChangeDetectionWatchdog");
this.timer = new ScheduledThreadPoolExecutor(1);
this.timer.scheduleWithFixedDelay(() -> this.update(), 0, POLLING_INTERVAL_MILLISECONDS, TimeUnit.MILLISECONDS);
}
}
public synchronized void shutdown() {
if (timer != null) {
logger.info("Shutting down SpringLiveChangeDetectionWatchdog");
timer.shutdown();
timer = null;
}
}
public void update() {
if (changeDetectionEnabled) {
// try {
// SpringBootApp[] runningBootApps = runningAppProvider.getAllRunningSpringApps().toArray(new SpringBootApp[0]);
// Change[] changes = changeHistory.checkForChanges(runningBootApps);
// if (changes != null && changes.length > 0) {
// for (Change change : changes) {
// publishDetectedChange(change);
// }
// }
// for (SpringBootApp app : runningBootApps) {
// updateApp(app);
// }
// } catch (Exception e) {
// logger.error("", e);
// }
}
}
private void publishDetectedChange(Change change) {
// Map<String, List<Diagnostic>> diagnostics = new HashMap<>();
//
// IJavaProject[] projects = findProjectsFor(change.getRunningApp());
//
// List<LiveBean> deletedBeans = change.getDeletedBeans();
// if (deletedBeans != null) {
// for (LiveBean liveBean : deletedBeans) {
// Diagnostic diag = new Diagnostic();
// diag.setSeverity(DiagnosticSeverity.Information);
// diag.setRange(new Range(new Position(0, 0), new Position(0, 0)));
// diag.setSource("Spring Boot Change Detection Mechanism");
//
// diag.setMessage("bean removed from app: " + liveBean.getId());
//
// String docURI = getDocURI(liveBean, projects);
// if (docURI != null) {
// List<Diagnostic> diags = diagnostics.computeIfAbsent(docURI, (s) -> new ArrayList<>());
// diags.add(diag);
// }
// else {
// logger.info("deleted bean could not be associated with a doc URI: " + liveBean.getId());
// }
// }
// }
//
// List<LiveBean> newBeans = change.getNewBeans();
// if (newBeans != null) {
// for (LiveBean liveBean : newBeans) {
// Diagnostic diag = new Diagnostic();
// diag.setSeverity(DiagnosticSeverity.Information);
// diag.setRange(new Range(new Position(0, 0), new Position(0, 0)));
// diag.setSource("Spring Boot Change Detection Mechanism");
//
// diag.setMessage("new bean detected: " + liveBean.getId());
//
// String docURI = getDocURI(liveBean, projects);
// if (docURI != null) {
// List<Diagnostic> diags = diagnostics.computeIfAbsent(docURI, (s) -> new ArrayList<>());
// diags.add(diag);
// }
// else {
// logger.info("new bean could not be associated with a doc URI: " + liveBean.getId());
// }
// }
// }
//
// for (String docURI : diagnostics.keySet()) {
// PublishDiagnosticsParams params = new PublishDiagnosticsParams(docURI, diagnostics.get(docURI));
// server.getClient().publishDiagnostics(params);
// }
}
// private IJavaProject[] findProjectsFor(SpringBootApp app) {
// List<IJavaProject> result = new ArrayList<>();
//
// try {
// Set<String> runningClasspath = new HashSet<>();
// Collections.addAll(runningClasspath, app.getClasspath());
//
// for (IJavaProject project : this.observedProjects) {
// if (RunningAppMatcher.doesClasspathMatch(runningClasspath, project)) {
// result.add(project);
// break;
// }
// }
// }
// catch (Exception e) {
// logger.error("find projects failed with: ", e);
// }
//
// return (IJavaProject[]) result.toArray(new IJavaProject[result.size()]);
// }
//
// private String getDocURI(LiveBean liveBean, IJavaProject[] projects) {
// String result = null;
//
// String resource = liveBean.getResource();
// if (resource != null) {
//
// Pattern BRACKETS = Pattern.compile("\\[[^\\]]*\\]");
//
// Matcher matcher = BRACKETS.matcher(resource);
// if (matcher.find()) {
// String type = resource.substring(0, matcher.start()).trim();
// String path = resource.substring(matcher.start()+1, matcher.end()-1);
//
// for (IJavaProject project : projects) {
// if (SpringResource.FILE.equals(type) || SpringResource.URL.equals(type)) {
// result = sourceLinks.sourceLinkUrlForClasspathResource(path).get();
// if (result == null) {
// result = sourceLinks.sourceLinkForResourcePath(Paths.get(path)).get();
// }
// break;
// }
// else if (SpringResource.CLASS_PATH_RESOURCE.equals(type)) {
// int idx = path.lastIndexOf(SourceLinks.CLASS);
// if (idx >= 0) {
// Path p = Paths.get(path.substring(0, idx));
// result = sourceLinks.sourceLinkUrlForFQName(project, p.toString().replace(File.separator, ".")).get();
// }
// break;
// }
// }
// }
//
// if (result != null) {
// int position = result.lastIndexOf('#');
// if (position > 0) {
// result = result.substring(0, position);
// }
// }
// }
// return result;
// }
public synchronized void enableHighlights() {
if (!changeDetectionEnabled) {
changeDetectionEnabled = true;
refreshEnablement();
}
}
public synchronized void disableHighlights() {
if (changeDetectionEnabled) {
changeDetectionEnabled = false;
refreshEnablement();
}
}
private void refreshEnablement() {
if (changeDetectionEnabled) {
start();
} else {
shutdown();
}
}
}

View File

@@ -358,11 +358,6 @@
"default": true,
"description": "Show CRON expressions inlay-hints"
},
"boot-java.change-detection.on": {
"type": "boolean",
"default": false,
"description": "Enable/Disable detecting changes of running Spring Boot applications"
},
"boot-java.java.completions.inject-bean": {
"type": "boolean",
"default": true,