4646public class CodeAnalysisService
4747{
4848
49+ private final java .util .concurrent .ConcurrentHashMap <org .eclipse .core .runtime .IPath , Object > fileLocks = new java .util .concurrent .ConcurrentHashMap <>();
50+
4951 @ Inject
5052 ILog logger ;
5153
@@ -758,27 +760,42 @@ public String executeQuickFix(long markerId, int proposalIndex)
758760 return "Error: Marker with ID " + markerId + " not found. It may have been resolved already." ;
759761 }
760762
761- List <QuickFix > fixes = collectQuickFixes (marker );
762- if (fixes .isEmpty ())
763- {
764- return "Error: No quick fix proposals available for marker " + markerId + "." ;
765- }
766- if (proposalIndex < 0 || proposalIndex >= fixes .size ())
763+ Object lock = (marker .getResource () instanceof IFile file )
764+ ? fileLocks .computeIfAbsent (file .getFullPath (), k -> new Object ())
765+ : new Object ();
766+
767+ synchronized (lock )
767768 {
768- return "Error: Proposal index " + proposalIndex + " is out of range (0-" + (fixes .size () - 1 ) + ")." ;
769- }
769+ marker = findMarkerById (markerId );
770+ if (marker == null )
771+ {
772+ return "Error: Marker with ID " + markerId + " not found. It may have been resolved already." ;
773+ }
770774
771- QuickFix fix = fixes .get (proposalIndex );
772- fix .apply (marker );
775+ List <QuickFix > fixes = collectQuickFixes (marker );
776+ if (fixes .isEmpty ())
777+ {
778+ return "Error: No quick fix proposals available for marker " + markerId + "." ;
779+ }
780+ if (proposalIndex < 0 || proposalIndex >= fixes .size ())
781+ {
782+ return "Error: Proposal index " + proposalIndex + " is out of range (0-" + (fixes .size () - 1 ) + ")." ;
783+ }
773784
774- if (marker .getResource () instanceof IFile file )
775- {
776- saveFileBuffer (file );
777- file .refreshLocal (IResource .DEPTH_ZERO , new NullProgressMonitor ());
778- }
785+ QuickFix fix = fixes .get (proposalIndex );
786+ fix .apply (marker );
787+
788+ if (marker .getResource () instanceof IFile f )
789+ {
790+ saveFileBuffer (f );
791+ f .refreshLocal (IResource .DEPTH_ZERO , new NullProgressMonitor ());
792+ }
779793
780- String status = marker .exists () ? "applied (marker still present)" : "applied and marker resolved" ;
781- return "Quick fix applied: \" " + fix .label () + "\" on marker " + markerId + " - " + status ;
794+ waitForAutoBuild ();
795+
796+ String status = marker .exists () ? "applied (marker still present)" : "applied and marker resolved" ;
797+ return "Quick fix applied: \" " + fix .label () + "\" on marker " + markerId + " - " + status ;
798+ }
782799 }
783800 catch (Exception e )
784801 {
@@ -971,6 +988,28 @@ private void saveFileBuffer(IFile file)
971988 }
972989 }
973990
991+ /**
992+ * Waits for Eclipse's auto-build to complete so that markers are refreshed
993+ * with correct offsets before the next quick fix is applied.
994+ */
995+ private void waitForAutoBuild ()
996+ {
997+ try
998+ {
999+ org .eclipse .core .runtime .jobs .Job .getJobManager ()
1000+ .join (ResourcesPlugin .FAMILY_AUTO_BUILD , new NullProgressMonitor ());
1001+ }
1002+ catch (InterruptedException e )
1003+ {
1004+ Thread .currentThread ().interrupt ();
1005+ }
1006+ catch (Exception e )
1007+ {
1008+ // best-effort
1009+ }
1010+ }
1011+
1012+
9741013
9751014 /** Reads the raw problem arguments from a marker. */
9761015 private String [] readMarkerArguments (IMarker marker )
@@ -1149,4 +1188,4 @@ private List<IJavaProject> getAvailableJavaProjects()
11491188 return javaProjects ;
11501189 }
11511190
1152- }
1191+ }
0 commit comments