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)) {