1717import java .util .HashSet ;
1818import java .util .Set ;
1919
20- import org .eclipse .core .resources .IProject ;
2120import org .eclipse .core .resources .WorkspaceJob ;
2221import org .eclipse .core .runtime .IProgressMonitor ;
2322import org .eclipse .core .runtime .IStatus ;
2423import org .eclipse .core .runtime .Status ;
2524import org .eclipse .core .runtime .jobs .Job ;
2625import org .eclipse .jdt .core .ElementChangedEvent ;
26+ import org .eclipse .jdt .core .ICompilationUnit ;
2727import org .eclipse .jdt .core .IElementChangedListener ;
2828import org .eclipse .jdt .core .IJavaElement ;
2929import org .eclipse .jdt .core .IJavaElementDelta ;
3030import org .eclipse .jdt .core .IJavaProject ;
3131import org .eclipse .jdt .core .JavaCore ;
32+ import org .eclipse .jdt .core .JavaModelException ;
3233import org .eclipse .jdt .ls .core .internal .BuildWorkspaceStatus ;
3334import org .eclipse .jdt .ls .core .internal .EventNotification ;
3435import org .eclipse .jdt .ls .core .internal .EventType ;
4142import org .eclipse .lsp4j .extended .ProjectBuildParams ;
4243
4344public class ClasspathUpdateHandler implements IElementChangedListener {
44-
4545 private final JavaClientConnection connection ;
46+ private final BaseDocumentLifeCycleHandler lifeCycleHandler ;
4647
4748 public ClasspathUpdateHandler (JavaClientConnection client ) {
49+ this (client , null );
50+ }
51+
52+ public ClasspathUpdateHandler (JavaClientConnection client , BaseDocumentLifeCycleHandler lifeCycleHandler ) {
4853 this .connection = client ;
54+ this .lifeCycleHandler = lifeCycleHandler ;
4955 }
5056
5157 @ Override
5258 public void elementChanged (ElementChangedEvent event ) {
5359 // Collect project names which have classpath changed.
54- Set <String > uris = processDelta (event .getDelta (), null );
55- if (connection != null && uris != null && !uris .isEmpty ()) {
56- for (String uri : uris ) {
60+ Set <IJavaProject > projects = new HashSet <>();
61+ processDelta (event .getDelta (), projects );
62+ if (connection != null && projects != null && !projects .isEmpty ()) {
63+ for (IJavaProject javaProject : projects ) {
64+ String uri = ProjectUtils .getProjectRealFolder (javaProject .getProject ()).toFile ().toURI ().toString ();
5765 PreferenceManager preferenceManager = JavaLanguageServerPlugin .getPreferencesManager ();
58- if (preferenceManager .getPreferences ().getNullAnalysisMode ().equals (FeatureStatus .automatic )) {
59- IProject project = ProjectUtils .getProjectFromUri (uri );
60- if (project != null ) {
61- IJavaProject javaProject = ProjectUtils .getJavaProject (project );
62- if (javaProject != null ) {
63- WorkspaceJob job = new WorkspaceJob ("Classpath Update Job" ) {
64- @ Override
65- public IStatus runInWorkspace (IProgressMonitor monitor ) {
66- if (!preferenceManager .getPreferences ().updateAnnotationNullAnalysisOptions (javaProject , true ) || !preferenceManager .getPreferences ().isAutobuildEnabled ()) {
67- // When the project's compiler options didn't change or auto build is disabled, rebuilding is not required.
68- return Status .OK_STATUS ;
69- }
70- BuildWorkspaceHandler buildWorkspaceHandler = new BuildWorkspaceHandler (JavaLanguageServerPlugin .getProjectsManager ());
71- ProjectBuildParams params = new ProjectBuildParams (Arrays .asList (new TextDocumentIdentifier (uri )), true );
72- BuildWorkspaceStatus status = buildWorkspaceHandler .buildProjects (params , monitor );
73- switch (status ) {
74- case FAILED :
75- case WITH_ERROR :
76- return Status .error ("error occurs during building project" );
77- case SUCCEED :
78- return Status .OK_STATUS ;
79- case CANCELLED :
80- return Status .CANCEL_STATUS ;
81- default :
82- return Status .OK_STATUS ;
83- }
66+ if (!preferenceManager .getPreferences ().isAutobuildEnabled ()) {
67+ if (lifeCycleHandler != null ) {
68+ for (ICompilationUnit unit : JavaCore .getWorkingCopies (null )) {
69+ if (unit .getJavaProject ().equals (javaProject )) {
70+ try {
71+ lifeCycleHandler .triggerValidation (unit );
72+ } catch (JavaModelException e ) {
73+ JavaLanguageServerPlugin .logException ("Failed to revalidate document after classpath change: " + unit .getPath (), e );
8474 }
85- };
86- job .setPriority (Job .SHORT );
87- job .setRule (project );
88- job .schedule ();
75+ }
8976 }
9077 }
78+ } else if (preferenceManager .getPreferences ().getNullAnalysisMode ().equals (FeatureStatus .automatic )) {
79+ WorkspaceJob job = new WorkspaceJob ("Classpath Update Job" ) {
80+ @ Override
81+ public IStatus runInWorkspace (IProgressMonitor monitor ) {
82+ if (!preferenceManager .getPreferences ().updateAnnotationNullAnalysisOptions (javaProject , true )) {
83+ // When the project's compiler options didn't change, rebuilding is not required.
84+ return Status .OK_STATUS ;
85+ }
86+ BuildWorkspaceHandler buildWorkspaceHandler = new BuildWorkspaceHandler (JavaLanguageServerPlugin .getProjectsManager ());
87+ ProjectBuildParams params = new ProjectBuildParams (Arrays .asList (new TextDocumentIdentifier (uri )), true );
88+ BuildWorkspaceStatus status = buildWorkspaceHandler .buildProjects (params , monitor );
89+ switch (status ) {
90+ case FAILED :
91+ case WITH_ERROR :
92+ return Status .error ("error occurs during building project" );
93+ case SUCCEED :
94+ return Status .OK_STATUS ;
95+ case CANCELLED :
96+ return Status .CANCEL_STATUS ;
97+ default :
98+ return Status .OK_STATUS ;
99+ }
100+ }
101+ };
102+ job .setPriority (Job .SHORT );
103+ job .setRule (javaProject .getProject ());
104+ job .schedule ();
91105 }
92106 EventNotification notification = new EventNotification ().withType (EventType .ClasspathUpdated ).withData (uri );
93107 this .connection .sendEventNotification (notification );
@@ -103,32 +117,27 @@ public void removeElementChangeListener() {
103117 JavaCore .removeElementChangedListener (this );
104118 }
105119
106- private Set < String > processDeltaChildren (IJavaElementDelta delta , Set <String > uris ) {
120+ private void processDeltaChildren (IJavaElementDelta delta , Set <IJavaProject > projects ) {
107121 for (IJavaElementDelta c : delta .getAffectedChildren ()) {
108- uris = processDelta (c , uris );
122+ processDelta (c , projects );
109123 }
110- return uris ;
111124 }
112125
113- private Set < String > processDelta (IJavaElementDelta delta , Set <String > uris ) {
126+ private void processDelta (IJavaElementDelta delta , Set <IJavaProject > projects ) {
114127 IJavaElement element = delta .getElement ();
115128 switch (element .getElementType ()) {
116129 case IJavaElement .JAVA_MODEL :
117- uris = processDeltaChildren (delta , uris );
130+ processDeltaChildren (delta , projects );
118131 break ;
119132 case IJavaElement .JAVA_PROJECT :
120133 if (isClasspathChanged (delta .getFlags ())) {
121- if (uris == null ) {
122- uris = new HashSet <String >();
123- }
124134 IJavaProject javaProject = (IJavaProject ) element ;
125- uris .add (ProjectUtils . getProjectRealFolder ( javaProject . getProject ()). toFile (). toURI (). toString () );
135+ projects .add (javaProject );
126136 }
127137 break ;
128138 default :
129139 break ;
130140 }
131- return uris ;
132141 }
133142
134143 private boolean isClasspathChanged (int flags ) {
0 commit comments