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 15, 2024
1 parent 185a7cd commit d866d75
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,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 @@ -307,8 +307,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 @@ -326,10 +324,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 @@ -562,7 +565,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,27 @@ 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
}

}
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 @@ -505,14 +505,24 @@ public IStatus runInWorkspace(IProgressMonitor monitor) {
return status;
}
};
waitForUpdateJobs();
job.schedule();
return job;
}

private void waitForUpdateJobs() {
int maxThread = preferenceManager.getPreferences().getMaxConcurrentBuilds();
Job[] jobs = Job.getJobManager().find(IConstants.UPDATE_PROJECT_FAMILY);
if (jobs != null && jobs.length > maxThread) {
JobHelpers.waitForJobs(IConstants.UPDATE_PROJECT_FAMILY, null);
}
}

@Override
public Job updateProjects(Collection<IProject> projects, boolean force) {
JavaLanguageServerPlugin.sendStatus(ServiceStatus.Message, "Updating project configurations...");
UpdateProjectsWorkspaceJob job = new UpdateProjectsWorkspaceJob(projects, force);
waitForUpdateJobs();
job.schedule();
return job;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,19 @@ 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;

@Override
public boolean shouldUpdateProjects() {
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 +314,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 +329,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 +360,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 +400,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 +667,22 @@ public void projectsImported(IProgressMonitor monitor) {
androidSupport.onDidProjectsImported(monitor);
this.preferenceManager.getPreferences().updateAnnotationNullAnalysisOptions();
}

@Override
public void projectsBuildFinished(IProgressMonitor monitor) {
this.buildFinished = true;
if (this.shouldUpdateProjects) {
for (IProject project : ProjectUtils.getAllProjects()) {
if (ProjectUtils.isMavenProject(project)) {
updateProject(project, true);
}
}
this.shouldUpdateProjects = false;
}
}

@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 All @@ -52,7 +54,6 @@
*
*/
public class StandardPreferenceManager extends PreferenceManager {
private static final String TRUE = "true";
private static final String JAVALS_PROFILE = "javals.profile";
public static final String M2E_DISABLE_TEST_CLASSPATH_FLAG = "m2e.disableTestClasspathFlag";
private static final String M2E_APT_ID = MavenJdtAptPlugin.PLUGIN_ID;
Expand Down Expand Up @@ -122,26 +123,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 +143,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 +192,23 @@ 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()) {
for (IProject project : ProjectUtils.getAllProjects()) {
if (ProjectUtils.isMavenProject(project)) {
projectManager.updateProject(project, true);
}
}
} else {
boolean hasMavenProjects = false;
for (IProject project : ProjectUtils.getAllProjects()) {
if (ProjectUtils.isMavenProject(project)) {
hasMavenProjects = true;
break;
}
}
projectManager.setShouldUpdateProjects(hasMavenProjects);
}
}
}
Expand Down
Loading

0 comments on commit d866d75

Please sign in to comment.