/* * Copyright 2000-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.refactoring.extractMethodObject; import com.intellij.lang.ContextAwareActionHandler; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pass; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.source.PostprocessReformattingAspect; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.extractMethod.ExtractMethodHandler; import com.intellij.refactoring.extractMethod.PrepareFailedException; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.refactoring.util.duplicates.DuplicatesImpl; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; public class ExtractMethodObjectHandler implements RefactoringActionHandler, ContextAwareActionHandler { private static final Logger LOG = Logger.getInstance(ExtractMethodObjectHandler.class); public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file, final DataContext dataContext) { ExtractMethodHandler.selectAndPass(project, editor, file, new Pass<PsiElement[]>() { public void pass(final PsiElement[] selectedValue) { invokeOnElements(project, editor, file, selectedValue); } }); } @Override public boolean isAvailableForQuickList(@NotNull Editor editor, @NotNull PsiFile file, @NotNull DataContext dataContext) { final PsiElement[] elements = ExtractMethodHandler.getElements(file.getProject(), editor, file); return elements != null && elements.length > 0; } private static void invokeOnElements(@NotNull final Project project, @NotNull final Editor editor, @NotNull PsiFile file, @NotNull PsiElement[] elements) { if (elements.length == 0) { String message = RefactoringBundle .getCannotRefactorMessage(RefactoringBundle.message("selected.block.should.represent.a.set.of.statements.or.an.expression")); CommonRefactoringUtil.showErrorHint(project, editor, message, ExtractMethodObjectProcessor.REFACTORING_NAME, HelpID.EXTRACT_METHOD_OBJECT); return; } try { extractMethodObject(project, editor, new ExtractMethodObjectProcessor(project, editor, elements, "")); } catch (PrepareFailedException e) { CommonRefactoringUtil.showErrorHint(project, editor, e.getMessage(), ExtractMethodObjectProcessor.REFACTORING_NAME, HelpID.EXTRACT_METHOD_OBJECT); ExtractMethodHandler.highlightPrepareError(e, file, editor, project); } } static void extractMethodObject(Project project, Editor editor, ExtractMethodObjectProcessor processor) throws PrepareFailedException { final ExtractMethodObjectProcessor.MyExtractMethodProcessor extractProcessor = processor.getExtractProcessor(); if (!extractProcessor.prepare()) return; if (!CommonRefactoringUtil.checkReadOnlyStatus(project, extractProcessor.getTargetClass().getContainingFile())) return; if (extractProcessor.showDialog()) { run(project, editor, processor, extractProcessor); } } public static void run(@NotNull final Project project, final Editor editor, @NotNull final ExtractMethodObjectProcessor processor, @NotNull final ExtractMethodObjectProcessor.MyExtractMethodProcessor extractProcessor) { final RangeMarker marker; if (editor != null) { final int offset = editor.getCaretModel().getOffset(); marker = editor.getDocument().createRangeMarker(offset, offset); } else { marker = null; } CommandProcessor.getInstance().executeCommand(project, () -> PostprocessReformattingAspect.getInstance(project).postponeFormattingInside(() -> { try { ApplicationManager.getApplication().runWriteAction(() -> extractProcessor.doRefactoring()); processor.run(); ApplicationManager.getApplication().runWriteAction(() -> processor.runChangeSignature()); } catch (IncorrectOperationException e) { LOG.error(e); } PsiDocumentManager.getInstance(project).commitAllDocuments(); if (processor.isCreateInnerClass()) { processor.moveUsedMethodsToInner(); PsiDocumentManager.getInstance(project).commitAllDocuments(); if (editor != null) { DuplicatesImpl.processDuplicates(extractProcessor, project, editor); } } ApplicationManager.getApplication().runWriteAction(() -> { if (processor.isCreateInnerClass()) { processor.changeInstanceAccess(project); } final PsiElement method = processor.getMethod(); LOG.assertTrue(method != null); method.delete(); }); }), ExtractMethodObjectProcessor.REFACTORING_NAME, ExtractMethodObjectProcessor.REFACTORING_NAME); if (editor != null) { editor.getCaretModel().moveToOffset(marker.getStartOffset()); marker.dispose(); editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); } } public void invoke(@NotNull final Project project, @NotNull final PsiElement[] elements, final DataContext dataContext) { throw new UnsupportedOperationException(); } }