package jetbrains.mps.ide.platform.actions.core; /*Generated by MPS */ import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import jetbrains.mps.baseLanguage.tuples.runtime.Tuples; import java.util.List; import jetbrains.mps.refactoring.participant.RefactoringParticipant; import jetbrains.mps.ide.findusages.model.SearchTask; import jetbrains.mps.refactoring.participant.RefactoringUI; import org.jetbrains.mps.openapi.module.SRepository; import org.jetbrains.mps.openapi.module.SearchScope; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.ArrayList; import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.internal.collections.runtime.ITranslator2; import jetbrains.mps.internal.collections.runtime.ISelector; import jetbrains.mps.ide.findusages.model.SearchResults; import org.jetbrains.mps.openapi.module.ModelAccess; import org.jetbrains.mps.openapi.util.ProgressMonitor; import org.jetbrains.mps.openapi.util.SubProgressKind; import org.apache.log4j.Level; import jetbrains.mps.baseLanguage.tuples.runtime.MultiTuple; import jetbrains.mps.project.MPSProject; import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; import java.util.Map; import jetbrains.mps.refactoring.participant.RefactoringSession; import jetbrains.mps.project.Project; import jetbrains.mps.util.annotation.ToRemove; import org.jetbrains.annotations.Nullable; import jetbrains.mps.refactoring.participant.RefactoringSessionImpl; import jetbrains.mps.internal.collections.runtime.MapSequence; public class RefactoringProcessor { private static final Logger LOG = LogManager.getLogger(RefactoringProcessor.class); public static <IP, FP, IS, FS> Tuples._2<List<RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IS, FS>>, SearchTask> askParticipantChanges(final RefactoringParticipant.ParticipantStateFactory<IP, FP, IS, FS> factory, RefactoringUI refactoringUI, final SRepository repository, final SearchScope searchScope, final Iterable<? extends RefactoringParticipant<?, ?, IP, FP>> participants, final List<IS> nodes) { final List<RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IS, FS>> participantStates = ListSequence.fromList(new ArrayList<RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IS, FS>>()); final Wrappers._T<List<RefactoringParticipant.Option>> options = new Wrappers._T<List<RefactoringParticipant.Option>>(); refactoringUI.prepare(new Runnable() { public void run() { for (RefactoringParticipant<?, ?, IP, FP> participant : Sequence.fromIterable(participants)) { ListSequence.fromList(participantStates).addElement(RefactoringParticipant.ParticipantApplied.create(factory, participant, nodes)); } options.value = ListSequence.fromList(participantStates).translate(new ITranslator2<RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IS, FS>, RefactoringParticipant.Option>() { public Iterable<RefactoringParticipant.Option> translate(RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IS, FS> it) { return it.getAvaliableOptions(repository); } }).distinct().sort(new ISelector<RefactoringParticipant.Option, String>() { public String select(RefactoringParticipant.Option it) { return it.getDescription(); } }, true).toListSequence(); } }); final List<RefactoringParticipant.Option> selectedOptions = refactoringUI.selectParticipants(options.value); if (selectedOptions == null) { return null; } SearchTask searchTask = new SearchTask() { public boolean canExecute() { return true; } public SearchResults execute(ModelAccess modelAccess, final ProgressMonitor progressMonitor) { final Wrappers._boolean cancelled = new Wrappers._boolean(false); modelAccess.runReadAction(new Runnable() { public void run() { int steps = ListSequence.fromList(participantStates).count(); progressMonitor.start("Searching for usages", steps); for (RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IS, FS> participantState : ListSequence.fromList(participantStates)) { try { participantState.findChanges(repository, selectedOptions, searchScope, progressMonitor.subTask(1, SubProgressKind.AS_COMMENT)); } catch (RuntimeException e) { if (LOG.isEnabledFor(Level.ERROR)) { LOG.error("Exception during usages search", e); } cancelled.value = true; break; } if (progressMonitor.isCanceled()) { cancelled.value = true; break; } } progressMonitor.done(); } }); if (cancelled.value) { return null; } SearchResults searchResults = new SearchResults(); for (RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IS, FS> participantState : ListSequence.fromList(participantStates)) { List<? extends List<? extends RefactoringParticipant.Change<?, ?>>> participantChanges = participantState.getChanges(); for (List<? extends RefactoringParticipant.Change<?, ?>> nodeChanges : ListSequence.fromList(participantChanges)) { for (RefactoringParticipant.Change<?, ?> change : ListSequence.fromList(nodeChanges)) { searchResults.addAll(change.getSearchResults()); } } } return searchResults; } }; return MultiTuple.<List<RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IS, FS>>,SearchTask>from(participantStates, searchTask); } public static <IP, FP> void performRefactoringUserInteractive(MPSProject project, String refactoringName, Iterable<? extends RefactoringParticipant<?, ?, IP, FP>> participants, final List<IP> initialStates, final _FunctionTypes._return_P2_E0<? extends Map<IP, FP>, ? super Iterable<RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IP, FP>>, ? super RefactoringSession> doRefactor) { performRefactoringInProject(project, new DefaultRefactoringUI(project), refactoringName, participants, initialStates, doRefactor, null); } /** * * @see jetbrains.mps.ide.platform.actions.core.RefactoringProcessor#performRefactoringInProject(Project, RefactoringUI, String, Iterable<? extends RefactoringParticipant<?, ?, IP, FP>>, List<IP>, _FunctionTypes._return_P2_E0<? extends Map<IP, FP>, ? super Iterable<RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IP, FP>>, ? super RefactoringSession>, _FunctionTypes._void_P1_E0<? super RefactoringSession>) * @deprecated */ @Deprecated @ToRemove(version = 3.5) public static <IP, FP> void performRefactoringUserInteractive(MPSProject project, String refactoringName, Iterable<? extends RefactoringParticipant<?, ?, IP, FP>> participants, final List<IP> initialStates, final _FunctionTypes._return_P2_E0<? extends Map<IP, FP>, ? super Iterable<RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IP, FP>>, ? super RefactoringSession> doRefactor, _FunctionTypes._void_P1_E0<? super RefactoringSession> doCleanup) { performRefactoringInProject(project, new DefaultRefactoringUI(project), refactoringName, participants, initialStates, doRefactor, doCleanup); } /** * Update usages during refactoring. * For calling not in migration assistant but in interactive enviromnent, so performs all in single refactoring session with project scope. * * @see jetbrains.mps.refactoring.participant.RefactoringParticipant.KeepOldNodes * @param doRefactor callback that performs refactoring itself (e.g. moves or renames smth) * @param doCleanup cleanup that should be performed after all usages are updated (e.g. deletion of old code that can be used by participants), used only because of POSTPONE_REMOVE option */ public static <IP, FP> void performRefactoringInProject(Project project, RefactoringUI refactoringUI, String refactoringName, Iterable<? extends RefactoringParticipant<?, ?, IP, FP>> participants, final List<IP> initialStates, final _FunctionTypes._return_P2_E0<? extends Map<IP, FP>, ? super Iterable<RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IP, FP>>, ? super RefactoringSession> doRefactor, @Nullable final _FunctionTypes._void_P1_E0<? super RefactoringSession> doCleanup) { final RefactoringSessionImpl refactoringSession = new RefactoringSessionImpl(); performRefactoring(new RefactoringParticipant.CollectingParticipantStateFactory<IP, FP>(), refactoringUI, refactoringSession, project.getRepository(), project.getScope(), refactoringName, participants, initialStates, new _FunctionTypes._return_P1_E0<Map<IP, FP>, Iterable<RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IP, FP>>>() { public Map<IP, FP> invoke(Iterable<RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IP, FP>> participantStates) { return doRefactor.invoke(participantStates, refactoringSession); } }, new _FunctionTypes._void_P0_E0() { public void invoke() { refactoringSession.performAllRegistered(); if (doCleanup != null) { doCleanup.invoke(refactoringSession); } } }); } /** * Update usages during refactoring. * For calling from both 'during refactoring' and migration context. */ public static <IP, FP, IS, FS> void performRefactoring(final RefactoringParticipant.ParticipantStateFactory<IP, FP, IS, FS> factory, RefactoringUI refactoringUI, final RefactoringSession refactoringSession, final SRepository repository, SearchScope scope, String refactoringName, Iterable<? extends RefactoringParticipant<?, ?, IP, FP>> participants, final List<IS> initialStates, final _FunctionTypes._return_P1_E0<? extends Map<IS, FS>, ? super Iterable<RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IS, FS>>> doRefactor, @Nullable final _FunctionTypes._void_P0_E0 doCleanup) { final Tuples._2<List<RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IS, FS>>, SearchTask> participantChanges = askParticipantChanges(factory, refactoringUI, repository, scope, participants, initialStates); if (participantChanges == null) { return; } final Wrappers._T<SearchResults> searchResults = new Wrappers._T<SearchResults>(); refactoringUI.runSearch(new _FunctionTypes._void_P1_E0<ProgressMonitor>() { public void invoke(ProgressMonitor progressMonitor) { searchResults.value = participantChanges._1().execute(repository.getModelAccess(), progressMonitor); } }); if (searchResults.value == null) { return; } refactoringUI.showRefactoringView(new Runnable() { public void run() { final Map<IS, FS> getFinalObject = doRefactor.invoke(participantChanges._0()); if (getFinalObject == null) { return; } for (RefactoringParticipant.ParticipantApplied<?, ?, IP, FP, IS, FS> participantState : ListSequence.fromList(participantChanges._0())) { participantState.doRefactor(ListSequence.fromList(initialStates).select(new ISelector<IS, FS>() { public FS select(IS it) { return MapSequence.fromMap(getFinalObject).get(it); } }).toListSequence(), repository, refactoringSession, factory); } if (doCleanup != null) { doCleanup.invoke(); } } }, refactoringName, searchResults.value, participantChanges._1(), refactoringSession); } }