diff --git a/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.java b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.java
index b329d1942ac..a24aac6d5bf 100644
--- a/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.java
+++ b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.java
@@ -27,6 +27,8 @@ private FixMessages() {
}
public static String CleanUpPostSaveListener_name;
+ public static String CleanUpPostSaveListener_CalculatingChanges_taskName;
+ public static String CleanUpPostSaveListener_CreatingAST_taskName;
public static String CleanUpPostSaveListener_SaveAction_ChangeName;
public static String CleanUpPostSaveListener_SlowCleanUpDialog_link;
public static String CleanUpPostSaveListener_SlowCleanUpDialog_title;
diff --git a/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.properties b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.properties
index cc36c3ed22d..2b68f38b283 100644
--- a/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.properties
+++ b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/fix/FixMessages.properties
@@ -116,6 +116,8 @@ PrimitiveComparisonFix_convert_compareTo_to_primitive_comparison=Convert compare
PrimitiveRatherThanWrapperFix_description=Primitive type rather then wrapper class
CleanUpPostSaveListener_name=Code Clean Up
+CleanUpPostSaveListener_CalculatingChanges_taskName=Calculating changes for save actions...
+CleanUpPostSaveListener_CreatingAST_taskName=Calculating AST for save actions...
CleanUpPostSaveListener_SaveAction_ChangeName=Save Actions
CleanUpPostSaveListener_SlowCleanUpDialog_link=If this happens again we recommend to disable the corresponding save actions on the 'Save Actions' preference page.
CleanUpPostSaveListener_SlowCleanUpDialog_title=Slow Save Actions
diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/CleanUpPostSaveListener.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/CleanUpPostSaveListener.java
index c1dd98262fd..27ca2f79732 100644
--- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/CleanUpPostSaveListener.java
+++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/CleanUpPostSaveListener.java
@@ -13,12 +13,14 @@
*******************************************************************************/
package org.eclipse.jdt.internal.corext.fix;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
@@ -39,6 +41,7 @@
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
@@ -60,6 +63,7 @@
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.text.BadLocationException;
@@ -71,7 +75,9 @@
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
+import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.eclipse.ui.progress.IProgressService;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.CompositeChange;
@@ -362,7 +368,15 @@ public void saved(ICompilationUnit unit, IRegion[] changedRegions, IProgressMoni
CompilationUnit ast= null;
if (requiresAST(cleanUps)) {
- ast= createAst(unit, options, Progress.subMonitor(monitor, 10));
+ AtomicReference ref = new AtomicReference<>();
+ runUsingProgressService(m -> {
+ m.beginTask(FixMessages.CleanUpPostSaveListener_CreatingAST_taskName, IProgressMonitor.UNKNOWN);
+ ref.set(createAst(unit, options, m));
+ });
+ ast= ref.get();
+ if (ast == null) {
+ return;
+ }
}
CleanUpContext context;
@@ -373,7 +387,21 @@ public void saved(ICompilationUnit unit, IRegion[] changedRegions, IProgressMoni
}
ArrayList undoneCleanUps= new ArrayList<>();
- CleanUpChange change= CleanUpRefactoring.calculateChange(context, cleanUps, undoneCleanUps, slowCleanUps);
+
+ AtomicReference ref= new AtomicReference<>();
+ ICleanUp[] cleanUpsCopy = new ICleanUp[cleanUps.length];
+ System.arraycopy(cleanUps, 0, cleanUpsCopy, 0, cleanUps.length);
+
+ runUsingProgressService(m -> {
+ m.beginTask(FixMessages.CleanUpPostSaveListener_CalculatingChanges_taskName, IProgressMonitor.UNKNOWN);
+ try {
+ ref.set(CleanUpRefactoring.calculateChange(context, cleanUpsCopy, undoneCleanUps, slowCleanUps));
+ } catch (CoreException e) {
+ // "e" will be unpacked and rethrown
+ throw new InvocationTargetException(e);
+ }
+ });
+ CleanUpChange change= ref.get();
RefactoringStatus postCondition= new RefactoringStatus();
for (ICleanUp cleanUp : cleanUps) {
@@ -570,6 +598,29 @@ private boolean requiresChangedRegions(ICleanUp[] cleanUps) {
return false;
}
+ private static void runUsingProgressService(IRunnableWithProgress runnable) throws CoreException {
+ try {
+ IProgressService progressService= PlatformUI.getWorkbench().getProgressService();
+ progressService.run(true, false, runnable);
+ } catch (InvocationTargetException e) {
+ if (e.getCause() instanceof OperationCanceledException) {
+ return;
+ }
+ if (e.getCause() instanceof RuntimeException rte) {
+ throw rte;
+ }
+ if (e.getCause() instanceof CoreException ce) {
+ throw ce;
+ }
+ // Other kind of exceptions are simply logged
+ JavaPlugin.log(e);
+ } catch (InterruptedException e) {
+ // This currently doesn't happen since canceling the monitor does not throw an OperationCanceledException.
+ // ... but better safe than sorry, so log it.
+ JavaPlugin.log(e);
+ }
+ }
+
private CompilationUnit createAst(ICompilationUnit unit, Map cleanUpOptions, IProgressMonitor monitor) {
IJavaProject project= unit.getJavaProject();
if (compatibleOptions(project, cleanUpOptions)) {