Skip to content

Commit

Permalink
VSCode JLS error when loading project with lot of Maven sub modules
Browse files Browse the repository at this point in the history
Signed-off-by: Snjezana Peco <[email protected]>
  • Loading branch information
snjeza committed May 6, 2024
1 parent d6bc183 commit cfb076c
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,9 @@ public void triggerInitialization(Collection<IPath> roots) {
Job.getJobManager().wakeUp(ResourcesPlugin.FAMILY_AUTO_BUILD);
IWorkspace workspace = ResourcesPlugin.getWorkspace();
if (workspace instanceof Workspace workspaceImpl) {
workspaceImpl.getBuildManager().waitForAutoBuildOff();
if (!Job.getJobManager().isSuspended()) {
workspaceImpl.getBuildManager().waitForAutoBuildOff();
}
}
Job job = new WorkspaceJob("Initialize Workspace") {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,6 @@ public IStatus run(IProgressMonitor monitor) {
classpathUpdateHandler.addElementChangeListener();
SourceAttachUpdateHandler attachListener = new SourceAttachUpdateHandler(client);
attachListener.addElementChangeListener();
pm.registerWatchers();
debugTrace(">> watchers registered");

registerCapabilities();
// we do not have the user setting initialized yet at this point but we should
Expand All @@ -328,10 +326,15 @@ public IStatus run(IProgressMonitor monitor) {
IndexUtils.copyIndexesToSharedLocation();
JobHelpers.waitForBuildJobs(60 * 60 * 1000); // 1 hour
logInfo(">> build jobs finished");
// https://github.com/redhat-developer/vscode-java/issues/3637 - delay registerWatchers
pm.registerWatchers();
debugTrace(">> watchers registered");
pm.projectsBuildFinished(monitor);
telemetryManager.onBuildFinished(System.currentTimeMillis());
workspaceDiagnosticsHandler.publishDiagnostics(monitor);
} catch (OperationCanceledException | CoreException e) {
logException(e.getMessage(), e);
pm.projectsBuildFinished(monitor);
return Status.CANCEL_STATUS;
}
return Status.OK_STATUS;
Expand Down Expand Up @@ -577,7 +580,7 @@ public void didChangeConfiguration(DidChangeConfigurationParams params) {
try {
boolean isAutobuildEnabled = preferenceManager.getPreferences().isAutobuildEnabled();
boolean autoBuildChanged = ProjectsManager.setAutoBuilding(isAutobuildEnabled);
if (jvmChanged || nullAnalysisOptionsUpdated && isAutobuildEnabled) {
if ((jvmChanged || nullAnalysisOptionsUpdated) && isAutobuildEnabled) {
buildWorkspace(Either.forLeft(true));
} else if (autoBuildChanged && isAutobuildEnabled) {
buildWorkspace(Either.forLeft(false));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ public WorkspaceEventsHandler(ProjectsManager projects, JavaClientConnection con
Thread eventThread = new Thread(() -> {
while(true) {
try {
// https://github.com/redhat-developer/vscode-java/issues/3637
while (!pm.isBuildFinished()) {
Thread.sleep(200);
}
FileEvent event = queue.take();
handleFileEvent(event);
} catch (InterruptedException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,30 @@ default void unregisterListeners() {
default void projectsImported(IProgressMonitor monitor) {
// do nothing
}

/**
* Executed after the projects are imported and finished.
*/
default void projectsBuildFinished(IProgressMonitor monitor) {
// do nothing
}

/**
* Check whether the build is finished
*/
default boolean isBuildFinished() {
return true;
};

default boolean shouldUpdateProjects() {
return false;
}

default void setShouldUpdateProjects(boolean update) {
// do nothing
}

default void updateMavenProjects(IProgressMonitor monitor) {
// do nothing
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.apache.commons.lang3.StringUtils;
import org.eclipse.core.internal.resources.Workspace;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
Expand Down Expand Up @@ -288,15 +289,18 @@ private void updateProjects(Collection<IProject> projects, long lastWorkspaceSta
while (iterator.hasNext()) {
IProject project = iterator.next();
project.open(monitor);
IFile pomFile = project.getFile(POM_FILE);
pomFile.refreshLocal(IResource.DEPTH_ZERO, monitor);
if (!needsMavenUpdate(pomFile, lastWorkspaceStateSaved)) {
iterator.remove();
continue;
}
if (Platform.OS_WIN32.equals(Platform.getOS())) {
project.refreshLocal(IResource.DEPTH_ONE, monitor);
((Workspace) ResourcesPlugin.getWorkspace()).getRefreshManager().refresh(project);
} else {
project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
}
if (!needsMavenUpdate(project, lastWorkspaceStateSaved)) {
iterator.remove();
}
}
if (projects.isEmpty()) {
return;
Expand All @@ -318,8 +322,8 @@ public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
}.schedule();
}

private boolean needsMavenUpdate(IProject project, long lastWorkspaceStateSaved) {
return project.getFile(POM_FILE).getLocalTimeStamp() > lastWorkspaceStateSaved;
private boolean needsMavenUpdate(IResource pomFile, long lastWorkspaceStateSaved) {
return pomFile.getLocalTimeStamp() > lastWorkspaceStateSaved;
}

private Set<MavenProjectInfo> getMavenProjects(File directory, MavenModelManager modelManager, IProgressMonitor monitor) throws OperationCanceledException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,18 @@ public class StandardProjectsManager extends ProjectsManager {
protected static final String BUILD_SUPPORT_EXTENSION_POINT_ID = "buildSupport";
private static final Set<String> watchers = new LinkedHashSet<>();
private PreferenceManager preferenceManager;
private boolean buildFinished;
private boolean shouldUpdateProjects;

public boolean isShouldUpdateProjects() {
return shouldUpdateProjects;
}

@Override
public void setShouldUpdateProjects(boolean shouldUpdateProjects) {
this.shouldUpdateProjects = shouldUpdateProjects;
}

//@formatter:off
private static final List<String> basicWatchers = Arrays.asList(
"**/*.java",
Expand Down Expand Up @@ -301,6 +313,10 @@ public static void configureSettings(Preferences preferences) {

public static void configureSettings(Preferences preferences, boolean cleanWorkspace) {
URI settingsUri = preferences.getSettingsAsURI();
URI formatterUri = preferences.getFormatterAsURI();
if (settingsUri == null && formatterUri == null && !cleanWorkspace) {
return;
}
Properties properties = null;
if (settingsUri != null) {
try (InputStream inputStream = settingsUri.toURL().openStream()) {
Expand All @@ -312,7 +328,6 @@ public static void configureSettings(Preferences preferences, boolean cleanWorks
}
}
initializeDefaultOptions(preferences);
URI formatterUri = preferences.getFormatterAsURI();
Map<String, String> formatterOptions = null;
if (formatterUri != null) {
try (InputStream inputStream = formatterUri.toURL().openStream()) {
Expand Down Expand Up @@ -344,7 +359,9 @@ public static void configureSettings(Preferences preferences, boolean cleanWorks
}
});
}
JavaCore.setOptions(javaOptions);
if (!Objects.equals(javaOptions, JavaCore.getOptions())) {
JavaCore.setOptions(javaOptions);
}
if (cleanWorkspace && preferences.isAutobuildEnabled()) {
new WorkspaceJob("Clean workspace...") {

Expand Down Expand Up @@ -382,6 +399,7 @@ public Optional<IBuildSupport> getBuildSupport(IProject project) {
return buildSupports().filter(bs -> bs.applies(project)).findFirst();
}

@Override
protected Stream<IBuildSupport> buildSupports() {
Map<Integer, IBuildSupport> supporters = new TreeMap<>();
IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(IConstants.PLUGIN_ID, BUILD_SUPPORT_EXTENSION_POINT_ID);
Expand Down Expand Up @@ -648,4 +666,32 @@ public void projectsImported(IProgressMonitor monitor) {
androidSupport.onDidProjectsImported(monitor);
this.preferenceManager.getPreferences().updateAnnotationNullAnalysisOptions();
}

@Override
public void projectsBuildFinished(IProgressMonitor monitor) {
this.buildFinished = true;
if (this.shouldUpdateProjects) {
updateMavenProjects(monitor);
this.shouldUpdateProjects = false;
}
}

@Override
public void updateMavenProjects(IProgressMonitor monitor) {
int threads = 0;
for (IProject project : ProjectUtils.getAllProjects()) {
if (ProjectUtils.isMavenProject(project)) {
updateProject(project, true);
if (threads++ > 3) {
JobHelpers.waitForJobs(IConstants.UPDATE_PROJECT_FAMILY, monitor);
threads = 0;
}
}
}
}

@Override
public boolean isBuildFinished() {
return buildFinished;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,9 @@ public static void initializeJavaCoreOptions() {
// workaround for https://github.com/redhat-developer/vscode-java/issues/718
javaCoreOptions.put(JavaCore.CORE_CIRCULAR_CLASSPATH, JavaCore.WARNING);
javaCoreOptions.put(JavaCore.COMPILER_IGNORE_UNNAMED_MODULE_FOR_SPLIT_PACKAGE, JavaCore.ENABLED);
JavaCore.setOptions(javaCoreOptions);
if (!Objects.equals(javaCoreOptions, JavaCore.getOptions())) {
JavaCore.setOptions(javaCoreOptions);
}
}

private static void reloadTemplateStore() {
Expand Down Expand Up @@ -226,7 +228,9 @@ public void update(Preferences preferences) {
}
Hashtable<String, String> options = JavaCore.getOptions();
preferences.updateTabSizeInsertSpaces(options);
JavaCore.setOptions(options);
if (!Objects.equals(options, JavaCore.getOptions())) {
JavaCore.setOptions(options);
}
List<String> resourceFilters = preferences.getResourceFilters();
IEclipsePreferences eclipsePreferences = InstanceScope.INSTANCE.getNode(IConstants.PLUGIN_ID);
// add the resourceFilters preference; the org.eclipse.jdt.ls.filesystem plugin uses it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

import org.apache.maven.settings.Activation;
Expand All @@ -30,8 +29,10 @@
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.ls.core.internal.IConstants;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
import org.eclipse.jdt.ls.core.internal.ProjectUtils;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.eclipse.m2e.apt.MavenJdtAptPlugin;
import org.eclipse.m2e.apt.preferences.PreferencesConstants;
import org.eclipse.m2e.core.MavenPlugin;
Expand All @@ -43,6 +44,7 @@
import org.eclipse.m2e.core.internal.preferences.MavenPreferenceConstants;
import org.eclipse.m2e.core.internal.preferences.ProblemSeverity;
import org.eclipse.m2e.core.lifecyclemapping.model.PluginExecutionAction;
import org.osgi.service.prefs.BackingStoreException;

/**
* Preference manager
Expand Down Expand Up @@ -122,26 +124,10 @@ public void update(Preferences preferences) {
}
try {
Settings mavenSettings = MavenPlugin.getMaven().getSettings();
boolean oldDisableTest = false;
String systemMmpd = System.getProperty(MAVEN_MULTI_MODULE_PROJECT_DIRECTORY);
String oldMultiModuleProjectDirectory = systemMmpd;
List<String> activeProfilesIds = mavenSettings.getActiveProfiles();
for (org.apache.maven.settings.Profile settingsProfile : mavenSettings.getProfiles()) {
if ((settingsProfile.getActivation() != null && settingsProfile.getActivation().isActiveByDefault()) || activeProfilesIds.contains(settingsProfile.getId())) {
if (TRUE.equals(settingsProfile.getProperties().get(M2E_DISABLE_TEST_CLASSPATH_FLAG))) {
oldDisableTest = true;
}
if (systemMmpd == null) {
Object mmpd = settingsProfile.getProperties().get(MAVEN_MULTI_MODULE_PROJECT_DIRECTORY);
if (mmpd instanceof String s) {
oldMultiModuleProjectDirectory = s;
}
}
if (oldDisableTest && oldMultiModuleProjectDirectory != null) {
break;
}
}
}
IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(IConstants.PLUGIN_ID);
boolean oldDisableTest = prefs.getBoolean(M2E_DISABLE_TEST_CLASSPATH_FLAG, false);
String oldMultiModuleProjectDirectory = prefs.get(MAVEN_MULTI_MODULE_PROJECT_DIRECTORY, null);
String multiModuleProjectDirectory = systemMmpd;
if (multiModuleProjectDirectory == null) {
if (preferences.getRootPaths() != null) {
Expand All @@ -158,23 +144,32 @@ public void update(Preferences preferences) {
}
}
}
if (!Objects.equals(multiModuleProjectDirectory, oldMultiModuleProjectDirectory) || (oldDisableTest != preferences.isMavenDisableTestClasspathFlag())) {
mavenSettings.getProfiles().removeIf(p -> JAVALS_PROFILE.equals(p.getId()));
if (preferences.isMavenDisableTestClasspathFlag() || multiModuleProjectDirectory != null) {
Profile profile = new Profile();
profile.setId(JAVALS_PROFILE);
Activation activation = new Activation();
activation.setActiveByDefault(true);
profile.setActivation(activation);
profile.getProperties().put(M2E_DISABLE_TEST_CLASSPATH_FLAG, String.valueOf(preferences.isMavenDisableTestClasspathFlag()));
if (multiModuleProjectDirectory != null) {
profile.getProperties().put(MAVEN_MULTI_MODULE_PROJECT_DIRECTORY, multiModuleProjectDirectory);
} else {
profile.getProperties().remove(MAVEN_MULTI_MODULE_PROJECT_DIRECTORY);
}
mavenSettings.addProfile(profile);
mavenSettings.addActiveProfile(profile.getId());
updateMavenProjects = true;
updateMavenProjects = updateMavenProjects || !Objects.equals(multiModuleProjectDirectory, oldMultiModuleProjectDirectory) || (oldDisableTest != preferences.isMavenDisableTestClasspathFlag());
mavenSettings.getProfiles().removeIf(p -> JAVALS_PROFILE.equals(p.getId()));
if (preferences.isMavenDisableTestClasspathFlag() || multiModuleProjectDirectory != null) {
Profile profile = new Profile();
profile.setId(JAVALS_PROFILE);
Activation activation = new Activation();
activation.setActiveByDefault(true);
profile.setActivation(activation);
profile.getProperties().put(M2E_DISABLE_TEST_CLASSPATH_FLAG, String.valueOf(preferences.isMavenDisableTestClasspathFlag()));
if (multiModuleProjectDirectory != null) {
profile.getProperties().put(MAVEN_MULTI_MODULE_PROJECT_DIRECTORY, multiModuleProjectDirectory);
} else {
profile.getProperties().remove(MAVEN_MULTI_MODULE_PROJECT_DIRECTORY);
}
mavenSettings.addProfile(profile);
mavenSettings.addActiveProfile(profile.getId());
prefs.putBoolean(M2E_DISABLE_TEST_CLASSPATH_FLAG, preferences.isMavenDisableTestClasspathFlag());
if (multiModuleProjectDirectory != null) {
prefs.put(MAVEN_MULTI_MODULE_PROJECT_DIRECTORY, multiModuleProjectDirectory);
} else {
prefs.remove(MAVEN_MULTI_MODULE_PROJECT_DIRECTORY);
}
try {
prefs.flush();
} catch (BackingStoreException e) {
JavaLanguageServerPlugin.logException(e.getMessage(), e);
}
}
} catch (CoreException e) {
Expand All @@ -198,9 +193,19 @@ public void update(Preferences preferences) {
updateMavenProjects = true;
}
if (updateMavenProjects) {
for (IProject project : ProjectUtils.getAllProjects()) {
if (ProjectUtils.isMavenProject(project)) {
JavaLanguageServerPlugin.getProjectsManager().updateProject(project, true);
ProjectsManager projectManager = JavaLanguageServerPlugin.getProjectsManager();
if (projectManager != null) {
if (projectManager.isBuildFinished()) {
projectManager.updateMavenProjects(null);
} else {
boolean hasMavenProjects = false;
for (IProject project : ProjectUtils.getAllProjects()) {
if (ProjectUtils.isMavenProject(project)) {
hasMavenProjects = true;
break;
}
}
projectManager.setShouldUpdateProjects(hasMavenProjects);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ public void setup() throws Exception {
server = new JDTLanguageServer(projectsManager, preferenceManager, commandHandler);
server.connectClient(client);
JavaLanguageServerPlugin.getInstance().setProtocol(server);
JobHelpers.waitForJobsToComplete(monitor);
}

@After
Expand Down Expand Up @@ -319,6 +320,7 @@ public void testWatchers() throws Exception {
importProjects(Arrays.asList("maven/salut", "gradle/simple-gradle"));
newEmptyProject();
List<FileSystemWatcher> watchers = projectsManager.registerWatchers();
projectsManager.projectsBuildFinished(null);
// 8 basic + 3 project roots
assertEquals("Unexpected watchers:\n" + toString(watchers), 12, watchers.size());
List<FileSystemWatcher> projectWatchers = watchers.subList(9, 12);
Expand Down

0 comments on commit cfb076c

Please sign in to comment.