From 9276acd240850646da8d4f9ca5eb87f5548062b4 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Mon, 16 Jan 2012 13:50:30 +0400 Subject: [PATCH 1/7] move ExtractMethodRefactoring to extract.method package --- .../GroovyRefactoringBundle.properties | 1 + .../GroovyRefactoringSupportProvider.java | 4 +- .../plugins/groovy/refactoring/HelpID.java | 3 +- .../ExtractUtil.java} | 50 +++++------ .../ParameterInfo.java | 4 +- .../ParameterTablePanel.java | 37 ++++----- .../method}/ExtractMethodInfoHelper.java | 11 +-- .../method}/ExtractMethodSettings.java | 4 +- .../method}/GroovyExtractMethodDialog.form | 77 +++++++---------- .../method}/GroovyExtractMethodDialog.java | 20 +++-- .../method}/GroovyExtractMethodHandler.java | 82 +++++++++---------- .../method}/VisibilityPanel.java | 15 +--- .../method}/ExtractMethodTest.java | 5 +- 13 files changed, 145 insertions(+), 168 deletions(-) rename plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/{extractMethod/ExtractMethodUtil.java => extract/ExtractUtil.java} (90%) rename plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/{extractMethod => extract}/ParameterInfo.java (94%) rename plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/{extractMethod => extract}/ParameterTablePanel.java (92%) rename plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/{extractMethod => extract/method}/ExtractMethodInfoHelper.java (94%) rename plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/{extractMethod => extract/method}/ExtractMethodSettings.java (87%) rename plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/{extractMethod => extract/method}/GroovyExtractMethodDialog.form (52%) rename plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/{extractMethod => extract/method}/GroovyExtractMethodDialog.java (91%) rename plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/{extractMethod => extract/method}/GroovyExtractMethodHandler.java (82%) rename plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/{extractMethod => extract/method}/VisibilityPanel.java (85%) rename plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/{extractMethod => extract/method}/ExtractMethodTest.java (97%) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties index ca361727d6f6..eabb9abf1f80 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties @@ -165,3 +165,4 @@ change.usages.of.var=Change usages of variable ''{0}''? reference.to.accessor.0.is.used=Reference to accessor {0} cannot be inlined. variable.is.accessed.for.writing=Variable ''{0}'' is accessed for writing introduce.closure.parameter.elements.header=Adding parameter to a closure +extract.closure.title=Extract closure diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java index 49a320410131..bbf10fd7c6ca 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -28,7 +28,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.refactoring.changeSignature.GrChangeSignatureHandler; -import org.jetbrains.plugins.groovy.refactoring.extractMethod.GroovyExtractMethodHandler; +import org.jetbrains.plugins.groovy.refactoring.extract.method.GroovyExtractMethodHandler; import org.jetbrains.plugins.groovy.refactoring.introduce.constant.GrIntroduceConstantHandler; import org.jetbrains.plugins.groovy.refactoring.introduce.field.GrIntroduceFieldHandler; import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GrIntroduceParameterHandler; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/HelpID.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/HelpID.java index 96e0c6238211..7910c41fad60 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/HelpID.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/HelpID.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -20,4 +20,5 @@ package org.jetbrains.plugins.groovy.refactoring; */ public interface HelpID { String GROOVY_INTRODUCE_PARAMETER = "refactoring.introduceParameter.groovy"; + String GROOVY_EXTRACT_CLOSURE = "refactoring.extractClosure.groovy"; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/ExtractMethodUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java similarity index 90% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/ExtractMethodUtil.java rename to plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java index aa0cf3eb81d2..7f9385a89b66 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/ExtractMethodUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.plugins.groovy.refactoring.extractMethod; +package org.jetbrains.plugins.groovy.refactoring.extract; import com.intellij.openapi.project.Project; import com.intellij.psi.*; @@ -54,6 +54,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; +import org.jetbrains.plugins.groovy.refactoring.extract.method.ExtractMethodInfoHelper; import org.jetbrains.plugins.groovy.refactoring.inline.GroovyInlineMethodUtil; import java.util.*; @@ -61,13 +62,13 @@ import java.util.*; /** * @author ilyas */ -public class ExtractMethodUtil { +public class ExtractUtil { - private ExtractMethodUtil() { + private ExtractUtil() { } @Nullable - static PsiElement calculateAnchorToInsertBefore(GrMemberOwner owner, PsiElement startElement) { + public static PsiElement calculateAnchorToInsertBefore(GrMemberOwner owner, PsiElement startElement) { while (startElement != null && !isEnclosingDefinition(owner, startElement)) { if (startElement.getParent() instanceof GroovyFile) { return startElement.getNextSibling(); @@ -94,7 +95,7 @@ public class ExtractMethodUtil { } @NotNull - static GrStatement[] createResultStatement(ExtractMethodInfoHelper helper, @NotNull String methodName) { + public static GrStatement[] createResultStatement(ExtractMethodInfoHelper helper, @NotNull String methodName) { VariableInfo[] outputVars = helper.getOutputNames(); PsiType type = helper.getOutputType(); @@ -114,8 +115,7 @@ public class ExtractMethodUtil { return new GrStatement[]{createAssignment(outputVars, callExpression, helper)}; } if (mustAdd.size() == outputVars.length && outputVars.length == 1) { - final GrVariableDeclaration decl = factory.createVariableDeclaration(ArrayUtil.EMPTY_STRING_ARRAY, callExpression, - outputVars[0].getType(), outputVars[0].getName()); + final GrVariableDeclaration decl = factory.createVariableDeclaration(ArrayUtil.EMPTY_STRING_ARRAY, callExpression, outputVars[0].getType(), outputVars[0].getName()); return new GrVariableDeclaration[]{decl}; } List result = generateVarDeclarations(mustAdd, helper.getProject(), null); @@ -174,7 +174,7 @@ public class ExtractMethodUtil { return GroovyPsiElementFactory.getInstance(helper.getProject()).createExpressionFromText(text.toString()); } - static boolean validateMethod(GrMethod method, ExtractMethodInfoHelper helper) { + public static boolean validateMethod(GrMethod method, ExtractMethodInfoHelper helper) { ArrayList conflicts = new ArrayList(); GrMemberOwner owner = helper.getOwner(); PsiMethod[] methods = ArrayUtil.mergeArrays(owner.getAllMethods(), new PsiMethod[]{method}, PsiMethod.ARRAY_FACTORY); @@ -213,7 +213,7 @@ public class ExtractMethodUtil { } - static void removeOldStatements(GrStatementOwner owner, ExtractMethodInfoHelper helper) throws IncorrectOperationException { + public static void removeOldStatements(GrStatementOwner owner, ExtractMethodInfoHelper helper) throws IncorrectOperationException { owner.removeElements(helper.getInnerElements()); } @@ -258,7 +258,7 @@ public class ExtractMethodUtil { return false; } - static void renameParameterOccurrences(GrMethod method, ExtractMethodInfoHelper helper) throws IncorrectOperationException { + public static void renameParameterOccurrences(GrMethod method, ExtractMethodInfoHelper helper) throws IncorrectOperationException { GrOpenBlock block = method.getBlock(); if (block == null) return; GrStatement[] statements = block.getStatements(); @@ -289,7 +289,7 @@ public class ExtractMethodUtil { } } - static GrMethod createMethodByHelper(@NotNull String name, ExtractMethodInfoHelper helper) { + public static GrMethod createMethodByHelper(@NotNull String name, ExtractMethodInfoHelper helper) { StringBuilder buffer = new StringBuilder(); //Add signature @@ -364,7 +364,7 @@ public class ExtractMethodUtil { return method; } - static String[] getParameterString(ExtractMethodInfoHelper helper) { + public static String[] getParameterString(ExtractMethodInfoHelper helper) { int i = 0; ParameterInfo[] infos = helper.getParameterInfos(); int number = 0; @@ -385,12 +385,12 @@ public class ExtractMethodUtil { return ArrayUtil.toStringArray(params); } - static String getTypeString(ExtractMethodInfoHelper helper, boolean forPresentation, String modifier) { + public static String getTypeString(ExtractMethodInfoHelper helper, boolean forPresentation, String modifier) { PsiType type = helper.getOutputType(); final PsiPrimitiveType outUnboxed = PsiPrimitiveType.getUnboxedType(type); if (outUnboxed != null) type = outUnboxed; String typeText = forPresentation ? type.getPresentableText() : type.getCanonicalText(); - String returnType = typeText == null || typeText.equals("void") || typeText.equals("Object") || !helper.specifyType() ? "" : typeText; + String returnType = typeText == null || !helper.specifyType() ? "" : typeText; if (returnType.length() == 0) { if (modifier.length() == 0) { typeText = "def "; @@ -405,7 +405,7 @@ public class ExtractMethodUtil { return typeText; } - static GrStatement[] getStatementsByElements(PsiElement[] elements) { + public static GrStatement[] getStatementsByElements(PsiElement[] elements) { ArrayList statementList = new ArrayList(); for (PsiElement element : elements) { if (element instanceof GrStatement) { @@ -415,7 +415,7 @@ public class ExtractMethodUtil { return statementList.toArray(new GrStatement[statementList.size()]); } - static PsiElement[] getElementsInOffset(PsiFile file, int startOffset, int endOffset) { + public static PsiElement[] getElementsInOffset(PsiFile file, int startOffset, int endOffset) { PsiElement[] elements; GrExpression expr = GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, GrExpression.class); @@ -432,7 +432,7 @@ public class ExtractMethodUtil { } @Nullable - static GrMemberOwner getMemberOwner(GrStatement statement) { + public static GrMemberOwner getMemberOwner(GrStatement statement) { PsiElement parent = statement.getParent(); while (parent != null && !(parent instanceof GrMemberOwner)) { if (parent instanceof GroovyFileBase) return (GrMemberOwner) ((GroovyFileBase) parent).getScriptClass(); @@ -442,17 +442,17 @@ public class ExtractMethodUtil { } @Nullable - static GrStatementOwner getDeclarationOwner(GrStatement statement) { + public static GrStatementOwner getDeclarationOwner(GrStatement statement) { PsiElement parent = statement.getParent(); return parent instanceof GrStatementOwner ? ((GrStatementOwner) parent) : null; } - static boolean isSingleExpression(GrStatement[] statements) { + public static boolean isSingleExpression(GrStatement[] statements) { return statements.length == 1 && statements[0] instanceof GrExpression && !(statements[0].getParent() instanceof GrVariableDeclarationOwner && statements[0] instanceof GrAssignmentExpression); } - static GrMethodCallExpression createMethodCallByHelper(@NotNull String name, ExtractMethodInfoHelper helper) { + public static GrMethodCallExpression createMethodCallByHelper(@NotNull String name, ExtractMethodInfoHelper helper) { StringBuilder buffer = new StringBuilder(); buffer.append(name).append("("); int number = 0; @@ -479,7 +479,7 @@ public class ExtractMethodUtil { return ((GrMethodCallExpression) expr); } - static int getCaretOffset(@NotNull GrStatement statement) { + public static int getCaretOffset(@NotNull GrStatement statement) { if (statement instanceof GrVariableDeclaration) { GrVariable[] variables = ((GrVariableDeclaration) statement).getVariables(); if (variables.length > 0) { @@ -498,7 +498,7 @@ public class ExtractMethodUtil { return statement.getTextOffset(); } - static boolean canBeStatic(GrStatement statement) { + public static boolean canBeStatic(GrStatement statement) { PsiElement parent = statement.getParent(); while (parent != null && !(parent instanceof PsiFile)) { if (parent instanceof GrMethod) { @@ -509,14 +509,14 @@ public class ExtractMethodUtil { return false; } - static String getModifierString(ExtractMethodInfoHelper helper) { + public static String getModifierString(ExtractMethodInfoHelper helper) { String visibility = helper.getVisibility(); assert visibility != null && visibility.length() > 0; visibility = visibility.equals(PsiModifier.PUBLIC) ? "" : visibility + " "; return visibility + (helper.isStatic() ? "static " : ""); } - static boolean isReturnStatement(GrStatement statement, Collection returnStatements) { + public static boolean isReturnStatement(GrStatement statement, Collection returnStatements) { if (statement instanceof GrReturnStatement) return true; if (statement instanceof GrIfStatement) { boolean checked = GroovyInlineMethodUtil.checkTailIfStatement(((GrIfStatement) statement), returnStatements); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/ParameterInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterInfo.java similarity index 94% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/ParameterInfo.java rename to plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterInfo.java index 3674b192beba..0b05c58d0168 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/ParameterInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.plugins.groovy.refactoring.extractMethod; +package org.jetbrains.plugins.groovy.refactoring.extract; import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/ParameterTablePanel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java similarity index 92% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/ParameterTablePanel.java rename to plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java index 5ccf9ceb4a1f..b4413e5d0bd3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/ParameterTablePanel.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -14,8 +14,9 @@ * limitations under the License. */ -package org.jetbrains.plugins.groovy.refactoring.extractMethod; +package org.jetbrains.plugins.groovy.refactoring.extract; +import com.intellij.ide.ui.ListCellRendererWrapper; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiManager; import com.intellij.psi.PsiPrimitiveType; @@ -26,11 +27,13 @@ import com.intellij.ui.BooleanTableCellRenderer; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.TableUtil; +import com.intellij.ui.table.JBTable; import com.intellij.util.ui.AbstractTableCellEditor; -import com.intellij.util.ui.Table; import org.jetbrains.annotations.NonNls; import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; +import org.jetbrains.plugins.groovy.refactoring.extract.method.ExtractMethodInfoHelper; +import org.jetbrains.plugins.groovy.refactoring.extract.method.GroovyExtractMethodDialog; import javax.swing.*; import javax.swing.event.ListSelectionEvent; @@ -48,12 +51,11 @@ import java.awt.event.KeyEvent; */ public class ParameterTablePanel extends JPanel { - private Project myProject; private ParameterInfo[] myParameterInfos; private TypeSelector[] myParameterTypeSelectors; private GroovyExtractMethodDialog myDialog; - private Table myTable; + private JBTable myTable; private MyTableModel myTableModel; private JButton myUpButton; private JButton myDownButton; @@ -63,16 +65,15 @@ public class ParameterTablePanel extends JPanel { super(new BorderLayout()); } - void init(GroovyExtractMethodDialog dialog, ExtractMethodInfoHelper helper) { + public void init(GroovyExtractMethodDialog dialog, ExtractMethodInfoHelper helper) { setBorder(IdeBorderFactory.createTitledBorder(GroovyRefactoringBundle.message("parameters.border.title"), false, false, true)); myDialog = dialog; - myProject = helper.getProject(); myParameterInfos = helper.getParameterInfos(); myTableModel = new MyTableModel(); - myTable = new Table(myTableModel); + myTable = new JBTable(myTableModel); DefaultCellEditor defaultEditor = (DefaultCellEditor) myTable.getDefaultEditor(Object.class); defaultEditor.setClickCountToStart(1); @@ -89,14 +90,15 @@ public class ParameterTablePanel extends JPanel { } }); - PsiManager manager = PsiManager.getInstance(myProject); - GlobalSearchScope scope = GlobalSearchScope.allScope(myProject); + Project project = helper.getProject(); + PsiManager manager = PsiManager.getInstance(project); + GlobalSearchScope scope = GlobalSearchScope.allScope(project); myParameterTypeSelectors = new TypeSelector[myParameterInfos.length]; for (int i = 0; i < myParameterTypeSelectors.length; i++) { -// final GrExpression[] occurrences = ExtractMethodUtil.findVariableOccurrences(helper.getStatements(), myParameterInfos[i].getName()); +// final GrExpression[] occurrences = ExtractUtil.findVariableOccurrences(helper.getStatements(), myParameterInfos[i].getName()); // final TypeSelectorManager manager = new TypeSelectorManagerImpl(myProject, myParameterInfos[i].getType(), occurrences, areTypesDirected()); PsiType type = myParameterInfos[i].getType(); - myParameterTypeSelectors[i] = new TypeSelector(type != null ? type : PsiType.getJavaLangObject(manager, scope), myProject); + myParameterTypeSelectors[i] = new TypeSelector(type != null ? type : PsiType.getJavaLangObject(manager, scope), project); // myParameterInfos[i].setTypeName(myParameterTypeSelectors[i].getSelectedType()); } @@ -104,16 +106,13 @@ public class ParameterTablePanel extends JPanel { myTypeRendererCombo.setOpaque(true); myTypeRendererCombo.setBorder(null); - myTypeRendererCombo.setRenderer(new DefaultListCellRenderer() { - - public Component getListCellRendererComponent(final JList list, - final Object value, - final int index, final boolean isSelected, final boolean cellHasFocus) { - PsiType type = ((ParameterInfo) value).getType(); + myTypeRendererCombo.setRenderer(new ListCellRendererWrapper(myTypeRendererCombo.getRenderer()) { + @Override + public void customize(JList list, ParameterInfo info, int index, boolean selected, boolean hasFocus) { + PsiType type = info.getType(); PsiPrimitiveType unboxed = PsiPrimitiveType.getUnboxedType(type); type = unboxed != null ? unboxed : type; setText(type != null ? type.getPresentableText() : ""); - return this; } }); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/ExtractMethodInfoHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java similarity index 94% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/ExtractMethodInfoHelper.java rename to plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java index 827f4b35a2cc..15440ba51754 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/ExtractMethodInfoHelper.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.plugins.groovy.refactoring.extractMethod; +package org.jetbrains.plugins.groovy.refactoring.extract.method; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; @@ -28,6 +28,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; +import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil; +import org.jetbrains.plugins.groovy.refactoring.extract.ParameterInfo; import java.util.*; @@ -42,7 +44,7 @@ public class ExtractMethodInfoHelper { private final GrMemberOwner myTargetClass; private final boolean myIsStatic; private final boolean myIsReturnStatement; - private boolean mySpecifyType; + private boolean mySpecifyType = true; private final PsiElement[] myInnerElements; private String myVisibility; private final Project myProject; @@ -86,7 +88,7 @@ public class ExtractMethodInfoHelper { outputType = JavaPsiFacade.getElementFactory(myProject).createTypeFromText(CommonClassNames.JAVA_UTIL_LIST, myTargetClass); } } - else if (ExtractMethodUtil.isSingleExpression(statements)) { + else if (ExtractUtil.isSingleExpression(statements)) { final GrStatement lastExpr = statements[statements.length - 1]; if (!(lastExpr.getParent() instanceof GrCodeBlock)) { outputType = ((GrExpression)lastExpr).getType(); @@ -111,7 +113,6 @@ public class ExtractMethodInfoHelper { } } myOutputType = outputType != null ? outputType : PsiType.VOID; - mySpecifyType = !(PsiType.VOID.equals(outputType) || myOutputType.equalsToText("java.lang.Object")); } @NotNull diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/ExtractMethodSettings.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodSettings.java similarity index 87% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/ExtractMethodSettings.java rename to plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodSettings.java index f5cdc4e88389..a5a381e2df07 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/ExtractMethodSettings.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodSettings.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.plugins.groovy.refactoring.extractMethod; +package org.jetbrains.plugins.groovy.refactoring.extract.method; import org.jetbrains.annotations.NotNull; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/GroovyExtractMethodDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.form similarity index 52% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/GroovyExtractMethodDialog.form rename to plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.form index 11ea95b9d2ca..f6e377893239 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/GroovyExtractMethodDialog.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.form @@ -1,6 +1,6 @@ -
- + + @@ -8,49 +8,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -75,25 +36,49 @@ - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/GroovyExtractMethodDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java similarity index 91% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/GroovyExtractMethodDialog.java rename to plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java index 2edec74bdd9d..f6632083aaf0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/GroovyExtractMethodDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.plugins.groovy.refactoring.extractMethod; +package org.jetbrains.plugins.groovy.refactoring.extract.method; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.event.DocumentListener; @@ -30,6 +30,8 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil; +import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil; +import org.jetbrains.plugins.groovy.refactoring.extract.ParameterTablePanel; import org.jetbrains.plugins.groovy.settings.GroovyApplicationSettings; import javax.swing.*; @@ -78,8 +80,8 @@ public class GroovyExtractMethodDialog extends DialogWrapper { protected void doOKAction() { String name = getEnteredName(); if (name == null) return; - GrMethod method = ExtractMethodUtil.createMethodByHelper(name, myHelper); - if (method != null && !ExtractMethodUtil.validateMethod(method, myHelper)) { + GrMethod method = ExtractUtil.createMethodByHelper(name, myHelper); + if (method != null && !ExtractUtil.validateMethod(method, myHelper)) { return; } if (myCbSpecifyType.isEnabled()) { @@ -209,16 +211,16 @@ public class GroovyExtractMethodDialog extends DialogWrapper { /* Update signature text area */ - void updateSignature() { + public void updateSignature() { if (mySignatureArea == null) return; @NonNls StringBuilder buffer = new StringBuilder(); - String modifier = ExtractMethodUtil.getModifierString(myHelper); + String modifier = ExtractUtil.getModifierString(myHelper); buffer.append(modifier); - buffer.append(ExtractMethodUtil.getTypeString(myHelper, true, modifier)); + buffer.append(ExtractUtil.getTypeString(myHelper, true, modifier)); String name = getEnteredName() == null ? "" : getEnteredName(); buffer.append(name); buffer.append("("); - String[] params = ExtractMethodUtil.getParameterString(myHelper); + String[] params = ExtractUtil.getParameterString(myHelper); if (params.length > 0) { String INDENT = " "; buffer.append("\n"); @@ -230,7 +232,7 @@ public class GroovyExtractMethodDialog extends DialogWrapper { mySignatureArea.setText(buffer.toString()); } - ExtractMethodSettings getSettings() { + public ExtractMethodSettings getSettings() { return new MyExtractMethodSettings(this); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/GroovyExtractMethodHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java similarity index 82% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/GroovyExtractMethodHandler.java rename to plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java index d66220101e80..91579bdb4ea7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/GroovyExtractMethodHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.plugins.groovy.refactoring.extractMethod; +package org.jetbrains.plugins.groovy.refactoring.extract.method; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.application.Application; @@ -58,6 +58,7 @@ import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; +import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil; import java.util.ArrayList; import java.util.List; @@ -68,7 +69,7 @@ import java.util.Set; */ public class GroovyExtractMethodHandler implements RefactoringActionHandler { - private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.refactoring.extractMethod.GroovyExtractMethodHandler"); + private static final Logger LOG = Logger.getInstance(GroovyExtractMethodHandler.class); protected static String REFACTORING_NAME = GroovyRefactoringBundle.message("extract.method.title"); private String myInvokeResult = "ok"; @@ -105,12 +106,12 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { int endOffset = selectionModel.getSelectionEnd(); PsiDocumentManager.getInstance(project).commitAllDocuments(); - PsiElement[] elements = ExtractMethodUtil.getElementsInOffset(file, startOffset, endOffset); + PsiElement[] elements = ExtractUtil.getElementsInOffset(file, startOffset, endOffset); if (elements.length == 1 && elements[0] instanceof GrExpression) { selectionModel.setSelection(startOffset, elements[0].getTextRange().getEndOffset()); } - GrStatement[] statements = ExtractMethodUtil.getStatementsByElements(elements); + GrStatement[] statements = ExtractUtil.getStatementsByElements(elements); if (statements.length == 0) { String message = RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("selected.block.should.represent.a.statement.set")); @@ -128,17 +129,17 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { } GrStatement statement0 = statements[0]; - GrMemberOwner owner = ExtractMethodUtil.getMemberOwner(statement0); - GrStatementOwner declarationOwner = ExtractMethodUtil.getDeclarationOwner(statement0); - if (owner == null || - (declarationOwner == null && !ExtractMethodUtil.isSingleExpression(statements))) { + GrMemberOwner owner = ExtractUtil.getMemberOwner(statement0); + GrStatementOwner declarationOwner = ExtractUtil.getDeclarationOwner(statement0); + if (owner == null || declarationOwner == null && !ExtractUtil.isSingleExpression(statements)) { String message = RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("refactoring.is.not.supported.in.the.current.context")); showErrorMessage(message, project, editor); return false; } if (declarationOwner == null && - ExtractMethodUtil.isSingleExpression(statements) && - statement0 instanceof GrExpression && PsiType.VOID.equals(((GrExpression)statement0).getType())) { + ExtractUtil.isSingleExpression(statements) && + statement0 instanceof GrExpression && + PsiType.VOID.equals(((GrExpression)statement0).getType())) { String message = RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("selected.expression.has.void.type")); showErrorMessage(message, project, editor); return false; @@ -166,8 +167,7 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { FragmentVariableInfos fragmentVariableInfos = ReachingDefinitionsCollector.obtainVariableFlowInformation(statement0, statements[statements.length - 1]); VariableInfo[] inputInfos = fragmentVariableInfos.getInputVariableNames(); VariableInfo[] outputInfos = fragmentVariableInfos.getOutputVariableNames(); - if (/*outputInfos.length > 1 ||*/ - outputInfos.length == 1 && returnStatements.size() > 0) { + if (outputInfos.length == 1 && returnStatements.size() > 0) { String message = GroovyRefactoringBundle.message("multiple.output.values"); showErrorMessage(message, project, editor); return false; @@ -176,17 +176,15 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { boolean hasInterruptingStatements = false; for (GrStatement statement : statements) { - if (hasInterruptingStatements = - GroovyRefactoringUtil.hasWrongBreakStatements(statement) || - GroovyRefactoringUtil.haswrongContinueStatements(statement)) { - break; - } + hasInterruptingStatements = GroovyRefactoringUtil.hasWrongBreakStatements(statement) || GroovyRefactoringUtil.haswrongContinueStatements(statement); + if (hasInterruptingStatements) break; } + // must be replaced by return statement boolean hasReturns = returnStatements.size() > 0; List returnStatementsCopy = new ArrayList(returnStatements.size()); returnStatementsCopy.addAll(returnStatements); - boolean isReturnStatement = ExtractMethodUtil.isReturnStatement(statements[statements.length - 1], returnStatementsCopy); + boolean isReturnStatement = ExtractUtil.isReturnStatement(statements[statements.length - 1], returnStatementsCopy); boolean isLastStatementOfMethod = isLastStatementOfMethodOrClosure(statements); if (hasReturns && !isLastStatementOfMethod && !isReturnStatement || hasInterruptingStatements) { String message = GroovyRefactoringBundle.message("refactoring.is.not.supported.when.return.statement.interrupts.the.execution.flow"); @@ -194,7 +192,7 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { return false; } - boolean canBeStatic = ExtractMethodUtil.canBeStatic(statement0); + boolean canBeStatic = ExtractUtil.canBeStatic(statement0); ExtractMethodInfoHelper helper = new ExtractMethodInfoHelper(inputInfos, outputInfos, elements, statements, owner, canBeStatic, returnStatements); @@ -207,7 +205,8 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { ExtractMethodSettings settings = dialog.getSettings(); methodName = settings.getEnteredName(); helper = settings.getHelper(); - } else { + } + else { methodName = "testMethod"; } @@ -239,19 +238,19 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { final Editor editor, final PsiElement startElement) { - final GrMethod method = ExtractMethodUtil.createMethodByHelper(methodName, helper); + final GrMethod method = ExtractUtil.createMethodByHelper(methodName, helper); final Runnable runnable = new Runnable() { public void run() { try { - PsiElement anchor = ExtractMethodUtil.calculateAnchorToInsertBefore(owner, startElement); + PsiElement anchor = ExtractUtil.calculateAnchorToInsertBefore(owner, startElement); GrMethod newMethod = owner.addMemberDeclaration(method, anchor); - ExtractMethodUtil.renameParameterOccurrences(newMethod, helper); + ExtractUtil.renameParameterOccurrences(newMethod, helper); GrReferenceAdjuster.shortenReferences(newMethod); GrStatement realStatement; - if (declarationOwner != null && !ExtractMethodUtil.isSingleExpression(helper.getStatements())) { + if (declarationOwner != null && !ExtractUtil.isSingleExpression(helper.getStatements())) { // Replace set of statements - final GrStatement[] newStatement = ExtractMethodUtil.createResultStatement(helper, methodName); + final GrStatement[] newStatement = ExtractUtil.createResultStatement(helper, methodName); // add call statement final GrStatement[] statements = helper.getStatements(); assert statements.length > 0; @@ -261,12 +260,13 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { } assert realStatement != null; // remove old statements - ExtractMethodUtil.removeOldStatements(declarationOwner, helper); + ExtractUtil.removeOldStatements(declarationOwner, helper); PsiImplUtil.removeNewLineAfter(realStatement); - } else { + } + else { // Expression call replace - GrExpression methodCall = ExtractMethodUtil.createMethodCallByHelper(methodName, helper); - GrExpression oldExpr = (GrExpression) helper.getStatements()[0]; + GrExpression methodCall = ExtractUtil.createMethodCallByHelper(methodName, helper); + GrExpression oldExpr = (GrExpression)helper.getStatements()[0]; realStatement = oldExpr.replaceWithExpression(methodCall, true); } GrReferenceAdjuster.shortenReferences(realStatement); @@ -280,26 +280,22 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { // move to offset if (editor != null) { PsiDocumentManager.getInstance(helper.getProject()).commitDocument(editor.getDocument()); - editor.getCaretModel().moveToOffset(ExtractMethodUtil.getCaretOffset(realStatement)); + editor.getCaretModel().moveToOffset(ExtractUtil.getCaretOffset(realStatement)); } - - } catch (IncorrectOperationException e) { + } + catch (IncorrectOperationException e) { LOG.error(e); } } }; Project project = helper.getProject(); - CommandProcessor.getInstance().executeCommand( - project, - new Runnable() { - public void run() { - ApplicationManager.getApplication().runWriteAction(runnable); - editor.getSelectionModel().removeSelection(); - } - }, REFACTORING_NAME, null); - - + CommandProcessor.getInstance().executeCommand(project, new Runnable() { + public void run() { + ApplicationManager.getApplication().runWriteAction(runnable); + editor.getSelectionModel().removeSelection(); + } + }, REFACTORING_NAME, null); } private static GroovyExtractMethodDialog getDialog(@NotNull final ExtractMethodInfoHelper helper) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/VisibilityPanel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/VisibilityPanel.java similarity index 85% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/VisibilityPanel.java rename to plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/VisibilityPanel.java index 407a17fac6f8..f0e4e487f82e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extractMethod/VisibilityPanel.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/VisibilityPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.plugins.groovy.refactoring.extractMethod; +package org.jetbrains.plugins.groovy.refactoring.extract.method; import com.intellij.psi.PsiModifier; import com.intellij.ui.IdeBorderFactory; @@ -83,18 +83,9 @@ public class VisibilityPanel extends JPanel { if (myRbProtected.isSelected()) { return PsiModifier.PROTECTED; } - if (myRbPrivate.isSelected()) { - return PsiModifier.PRIVATE; - } return PsiModifier.PRIVATE; } - public void setVisibilityEnabled(String visibility, boolean value) { - if(PsiModifier.PRIVATE.equals(visibility)) myRbPrivate.setEnabled(value); - else if(PsiModifier.PROTECTED.equals(visibility)) myRbProtected.setEnabled(value); - else if(PsiModifier.PUBLIC.equals(visibility)) myRbPublic.setEnabled(value); - } - public void setVisibility(String visibility) { if (PsiModifier.PUBLIC.equals(visibility)) { myRbPublic.setSelected(true); @@ -107,7 +98,7 @@ public class VisibilityPanel extends JPanel { } } - public static interface VisibilityStateChanged extends EventListener { + public interface VisibilityStateChanged extends EventListener { void visibilityChanged(String newVisibility); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extractMethod/ExtractMethodTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.java similarity index 97% rename from plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extractMethod/ExtractMethodTest.java rename to plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.java index d27423497c2a..0d1f0908d7c2 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extractMethod/ExtractMethodTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.java @@ -1,5 +1,6 @@ /* - * Copyright 2000-2007 JetBrains s.r.o. + * Copyright 2000-2012 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 @@ -13,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.plugins.groovy.refactoring.extractMethod; +package org.jetbrains.plugins.groovy.refactoring.extract.method; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.impl.source.PostprocessReformattingAspect; From 02023fa13a2134b02da4980d8b0cf55fd9db4d92 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Mon, 16 Jan 2012 16:09:42 +0400 Subject: [PATCH 2/7] extract ExtractHandlerBase --- .../refactoring/extract/ExtractException.java | 25 ++ .../extract/ExtractHandlerBase.java | 186 +++++++++++++++ .../extract/ExtractInfoHelper.java | 53 +++++ .../extract/ExtractInitialInfo.java | 192 +++++++++++++++ .../refactoring/extract/ExtractUtil.java | 4 +- .../extract/ParameterTablePanel.java | 3 +- .../method/ExtractMethodInfoHelper.java | 150 ++++-------- .../method/GroovyExtractMethodDialog.java | 40 ++-- .../method/GroovyExtractMethodHandler.java | 224 +++--------------- .../extract/method/ExtractMethodTest.java | 4 +- .../refactoring/extractMethod/forIn.test | 4 +- 11 files changed, 568 insertions(+), 317 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractException.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractHandlerBase.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelper.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInitialInfo.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractException.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractException.java new file mode 100644 index 000000000000..06cd73ebd018 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractException.java @@ -0,0 +1,25 @@ +/* + * Copyright 2000-2012 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 org.jetbrains.plugins.groovy.refactoring.extract; + +/** + * @author Max Medvedev + */ +public class ExtractException extends RuntimeException { + public ExtractException(String message) { + super(message); + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractHandlerBase.java new file mode 100644 index 000000000000..df659404b69e --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractHandlerBase.java @@ -0,0 +1,186 @@ +/* + * Copyright 2000-2012 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 org.jetbrains.plugins.groovy.refactoring.extract; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.SelectionModel; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiType; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.refactoring.RefactoringActionHandler; +import com.intellij.refactoring.RefactoringBundle; +import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.HashSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; +import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner; +import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.FragmentVariableInfos; +import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.ReachingDefinitionsCollector; +import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * @author Max Medvedev + */ +public abstract class ExtractHandlerBase implements RefactoringActionHandler { + private static final Logger LOG = Logger.getInstance(ExtractHandlerBase.class); + + public void invokeOnEditor(Project project, Editor editor, PsiFile file, int start, int end) throws ExtractException { + /*// trim it if it's necessary + GroovyRefactoringUtil.trimSpacesAndComments(editor, file, false);*/ + + if (!(file instanceof GroovyFileBase)) { + String message = RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("only.in.groovy.files")); + throw new ExtractException(message); + } + + SelectionModel selectionModel = editor.getSelectionModel(); + PsiDocumentManager.getInstance(project).commitAllDocuments(); + + PsiElement[] elements = ExtractUtil.getElementsInOffset(file, start, end); + if (elements.length == 1 && elements[0] instanceof GrExpression) { + selectionModel.setSelection(start, elements[0].getTextRange().getEndOffset()); + } + + GrStatement[] statements = ExtractUtil.getStatementsByElements(elements); + + if (statements.length == 0) { + String message = + RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("selected.block.should.represent.a.statement.set")); + throw new ExtractException(message); + } + + for (GrStatement statement : statements) { + if (GroovyRefactoringUtil.isSuperOrThisCall(statement, true, true)) { + String message = RefactoringBundle + .getCannotRefactorMessage(GroovyRefactoringBundle.message("selected.block.contains.invocation.of.another.class.constructor")); + throw new ExtractException(message); + } + } + + GrStatement statement0 = statements[0]; + GrMemberOwner owner = ExtractUtil.getMemberOwner(statement0); + GrStatementOwner declarationOwner = ExtractUtil.getDeclarationOwner(statement0); + if (owner == null || declarationOwner == null && !ExtractUtil.isSingleExpression(statements)) { + String message = + RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("refactoring.is.not.supported.in.the.current.context")); + throw new ExtractException(message); + } + if (declarationOwner == null && + ExtractUtil.isSingleExpression(statements) && + statement0 instanceof GrExpression && + PsiType.VOID.equals(((GrExpression)statement0).getType())) { + String message = RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("selected.expression.has.void.type")); + throw new ExtractException(message); + } + + + // collect information about return statements in selected statement set + + Set allReturnStatements = new HashSet(); + GrControlFlowOwner controlFlowOwner = ControlFlowUtils.findControlFlowOwner(statement0); + assert controlFlowOwner != null; + allReturnStatements.addAll(ControlFlowUtils.collectReturns(controlFlowOwner, true)); + + ArrayList returnStatements = new ArrayList(); + for (GrStatement returnStatement : allReturnStatements) { + for (GrStatement statement : statements) { + if (PsiTreeUtil.isAncestor(statement, returnStatement, false)) { + returnStatements.add(returnStatement); + break; + } + } + } + + // collect information about variables in selected block + FragmentVariableInfos + fragmentVariableInfos = ReachingDefinitionsCollector.obtainVariableFlowInformation(statement0, statements[statements.length - 1]); + VariableInfo[] inputInfos = fragmentVariableInfos.getInputVariableNames(); + VariableInfo[] outputInfos = fragmentVariableInfos.getOutputVariableNames(); + if (outputInfos.length == 1 && returnStatements.size() > 0) { + String message = GroovyRefactoringBundle.message("multiple.output.values"); + throw new ExtractException(message); + } + + boolean hasInterruptingStatements = false; + + for (GrStatement statement : statements) { + hasInterruptingStatements = + GroovyRefactoringUtil.hasWrongBreakStatements(statement) || GroovyRefactoringUtil.haswrongContinueStatements(statement); + if (hasInterruptingStatements) break; + } + + // must be replaced by return statement + boolean hasReturns = returnStatements.size() > 0; + List returnStatementsCopy = new ArrayList(returnStatements.size()); + returnStatementsCopy.addAll(returnStatements); + boolean isReturnStatement = ExtractUtil.isReturnStatement(statements[statements.length - 1], returnStatementsCopy); + boolean isLastStatementOfMethod = isLastStatementOfMethodOrClosure(statements); + if (hasReturns && !isLastStatementOfMethod && !isReturnStatement || hasInterruptingStatements) { + String message = GroovyRefactoringBundle.message("refactoring.is.not.supported.when.return.statement.interrupts.the.execution.flow"); + throw new ExtractException(message); + } + + ExtractInitialInfo info = new ExtractInitialInfo(inputInfos, outputInfos, elements, statements, owner, returnStatements); + + InfoHelper helper = getSettings(info); + if (helper == null) return; + + performRefactoring(helper, owner, declarationOwner, editor, statement0); + } + + private static boolean isLastStatementOfMethodOrClosure(GrStatement[] statements) { + final GrStatement statement0 = statements[0]; + + PsiElement returnFrom = PsiTreeUtil.getParentOfType(statement0, GrMethod.class, GrClosableBlock.class, GroovyFile.class); + if (returnFrom instanceof GrMethod) { + returnFrom = ((GrMethod)returnFrom).getBlock(); + } + LOG.assertTrue(returnFrom instanceof GrStatementOwner); + + final GrStatement[] blockStatements = ((GrStatementOwner)returnFrom).getStatements(); + final GrStatement lastFromBlock = ArrayUtil.getLastElement(blockStatements); + final GrStatement lastStatement = ArrayUtil.getLastElement(statements); + return statement0.getManager().areElementsEquivalent(lastFromBlock, lastStatement); + } + + @Nullable + public abstract InfoHelper getSettings(@NotNull final ExtractInitialInfo initialInfo); + + public abstract void performRefactoring(@NotNull final InfoHelper helper, + @NotNull final GrMemberOwner owner, + final GrStatementOwner declarationOwner, + final Editor editor, + final PsiElement startElement); +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelper.java new file mode 100644 index 000000000000..2da2a3ddc24c --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelper.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2012 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 org.jetbrains.plugins.groovy.refactoring.extract; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; +import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; + +/** + * @author Max Medvedev + */ +public interface ExtractInfoHelper { + @NotNull + Project getProject(); + + @NotNull + ParameterInfo[] getParameterInfos(); + + @NotNull + VariableInfo[] getOutputNames(); + + @NotNull + String[] getArgumentNames(); + + @NotNull + PsiType getOutputType(); + + @NotNull + PsiElement[] getInnerElements(); + + @NotNull + GrStatement[] getStatements(); + + @NotNull + GrMemberOwner getOwner(); +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInitialInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInitialInfo.java new file mode 100644 index 000000000000..96937108b4f4 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInitialInfo.java @@ -0,0 +1,192 @@ +/* + * Copyright 2000-2012 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 org.jetbrains.plugins.groovy.refactoring.extract; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; +import com.intellij.psi.CommonClassNames; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiType; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; +import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; + +import java.util.*; + +/** + * @author Max Medvedev + */ +public class ExtractInitialInfo implements ExtractInfoHelper { + private final Map myInputNamesMap = new HashMap(); + private final VariableInfo[] myOutputNames; + private final PsiType myOutputType; + private final GrMemberOwner myTargetClass; + private final PsiElement[] myInnerElements; + private final Project myProject; + private final GrStatement[] myStatements; + private final boolean myHasReturnValue; + + public ExtractInitialInfo(VariableInfo[] inputInfos, + VariableInfo[] outputInfos, + PsiElement[] innerElements, + GrStatement[] statements, + GrMemberOwner targetClass, + ArrayList returnStatements) { + myInnerElements = innerElements; + myStatements = statements; + myTargetClass = targetClass; + myOutputNames = outputInfos; + + myHasReturnValue = ContainerUtil.find(returnStatements, new Condition() { + @Override + public boolean value(GrStatement statement) { + return statement instanceof GrReturnStatement && ((GrReturnStatement)statement).getReturnValue() != null; + } + }) != null; + + assert myStatements.length > 0; + myProject = myStatements[0].getProject(); + int i = 0; + for (VariableInfo info : inputInfos) { + PsiType type = info.getType(); + ParameterInfo pInfo = new ParameterInfo(info.getName(), i, type); + myInputNamesMap.put(info.getName(), pInfo); + i++; + } + + PsiType outputType = inferOutputType(outputInfos, statements, targetClass, returnStatements, myHasReturnValue); + myOutputType = outputType != null ? outputType : PsiType.VOID; + } + + @Nullable + private PsiType inferOutputType(VariableInfo[] outputInfos, + GrStatement[] statements, + GrMemberOwner targetClass, + ArrayList returnStatements, boolean hasReturnValue) { + PsiType outputType = PsiType.VOID; + if (outputInfos.length > 0) { + if (outputInfos.length == 1) { + outputType = outputInfos[0].getType(); + } + else { + outputType = JavaPsiFacade.getElementFactory(myProject).createTypeFromText(CommonClassNames.JAVA_UTIL_LIST, myTargetClass); + } + } + else if (ExtractUtil.isSingleExpression(statements)) { + final GrStatement single = statements[0]; + if (!(single.getParent() instanceof GrCodeBlock)) { + outputType = ((GrExpression)single).getType(); + } + } + else if (hasReturnValue) { + assert returnStatements.size() > 0; + List types = new ArrayList(returnStatements.size()); + for (GrStatement statement : returnStatements) { + if (statement instanceof GrReturnStatement) { + GrExpression returnValue = ((GrReturnStatement)statement).getReturnValue(); + if (returnValue != null) { + types.add(returnValue.getType()); + } + } + else if (statement instanceof GrExpression) { + types.add(((GrExpression)statement).getType()); + } + } + outputType = TypesUtil.getLeastUpperBoundNullable(types, targetClass.getManager()); + } + + return outputType; + } + + @Override + @NotNull + public Project getProject() { + return myProject; + } + + @NotNull + @Override + public ParameterInfo[] getParameterInfos() { + Collection collection = myInputNamesMap.values(); + ParameterInfo[] infos = new ParameterInfo[collection.size()]; + for (ParameterInfo info : collection) { + int position = info.getPosition(); + assert position < infos.length && infos[position] == null; + infos[position] = info; + } + return infos; + } + + @Override + @NotNull + public VariableInfo[] getOutputNames() { + return myOutputNames; + } + + /** + * Get old names of parameters to be pasted as method call arguments + * + * @return array of argument names + */ + @NotNull + @Override + public String[] getArgumentNames() { + Collection infos = myInputNamesMap.values(); + String[] argNames = new String[infos.size()]; + for (ParameterInfo info : infos) { + int position = info.getPosition(); + assert position < argNames.length; + argNames[position] = info.passAsParameter() ? info.getOldName() : ""; + } + return argNames; + } + + @Override + @NotNull + public PsiType getOutputType() { + return myOutputType; + } + + @Override + @NotNull + public PsiElement[] getInnerElements() { + return myInnerElements; + } + + @Override + @NotNull + public GrStatement[] getStatements() { + return myStatements; + } + + @Override + @NotNull + public GrMemberOwner getOwner() { + return myTargetClass; + } + + public boolean hasReturnValue() { + return myHasReturnValue; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java index 7f9385a89b66..0aa400e6b910 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java @@ -102,9 +102,9 @@ public class ExtractUtil { GrStatement[] statements = helper.getStatements(); GrMethodCallExpression callExpression = createMethodCallByHelper(methodName, helper); - if ((outputVars.length == 0 || PsiType.VOID.equals(type)) && !helper.isReturnStatement()) return new GrStatement[]{callExpression}; + if ((outputVars.length == 0 || PsiType.VOID.equals(type)) && !helper.hasReturnValue()) return new GrStatement[]{callExpression}; GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(helper.getProject()); - if (helper.isReturnStatement()) { + if (helper.hasReturnValue()) { return new GrStatement[]{factory.createStatementFromText("return " + callExpression.getText())}; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java index b4413e5d0bd3..fc85f7f8739b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java @@ -32,7 +32,6 @@ import com.intellij.util.ui.AbstractTableCellEditor; import org.jetbrains.annotations.NonNls; import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; -import org.jetbrains.plugins.groovy.refactoring.extract.method.ExtractMethodInfoHelper; import org.jetbrains.plugins.groovy.refactoring.extract.method.GroovyExtractMethodDialog; import javax.swing.*; @@ -65,7 +64,7 @@ public class ParameterTablePanel extends JPanel { super(new BorderLayout()); } - public void init(GroovyExtractMethodDialog dialog, ExtractMethodInfoHelper helper) { + public void init(GroovyExtractMethodDialog dialog, ExtractInitialInfo helper) { setBorder(IdeBorderFactory.createTitledBorder(GroovyRefactoringBundle.message("parameters.border.title"), false, false, true)); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java index 15440ba51754..a602782dc6e3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java @@ -17,123 +17,54 @@ package org.jetbrains.plugins.groovy.refactoring.extract.method; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Condition; -import com.intellij.psi.*; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiModifier; +import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; -import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; +import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInfoHelper; +import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInitialInfo; import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil; import org.jetbrains.plugins.groovy.refactoring.extract.ParameterInfo; -import java.util.*; - /** * @author ilyas */ -public class ExtractMethodInfoHelper { +public class ExtractMethodInfoHelper implements ExtractInfoHelper { + private final ExtractInitialInfo myInitialInfo; - private final Map myInputNamesMap = new HashMap(); - private final VariableInfo[] myOutputNames; - private final PsiType myOutputType; - private final GrMemberOwner myTargetClass; private final boolean myIsStatic; - private final boolean myIsReturnStatement; private boolean mySpecifyType = true; - private final PsiElement[] myInnerElements; private String myVisibility; - private final Project myProject; - private final GrStatement[] myStatements; + private String myName; + + public ExtractMethodInfoHelper(ExtractInitialInfo initialInfo, String name) { + myInitialInfo = initialInfo; - public ExtractMethodInfoHelper(VariableInfo[] inputInfos, - VariableInfo[] outputInfos, - PsiElement[] innerElements, - GrStatement[] statements, - GrMemberOwner targetClass, - boolean isStatic, - ArrayList returnStatements) { - myInnerElements = innerElements; - myStatements = statements; - myTargetClass = targetClass; - myIsStatic = isStatic; - myIsReturnStatement = ContainerUtil.find(returnStatements, new Condition() { - @Override - public boolean value(GrStatement statement) { - return statement instanceof GrReturnStatement && ((GrReturnStatement)statement).getReturnValue() != null; - } - }) != null; myVisibility = PsiModifier.PRIVATE; - assert myStatements.length > 0; - myProject = myStatements[0].getProject(); - int i = 0; - for (VariableInfo info : inputInfos) { - PsiType type = info.getType(); - ParameterInfo pInfo = new ParameterInfo(info.getName(), i, type); - myInputNamesMap.put(info.getName(), pInfo); - i++; - } + myName = name; - PsiType outputType = PsiType.VOID; - myOutputNames = outputInfos; - if (outputInfos.length > 0) { - if (outputInfos.length == 1) { - outputType = outputInfos[0].getType(); - } - else { - outputType = JavaPsiFacade.getElementFactory(myProject).createTypeFromText(CommonClassNames.JAVA_UTIL_LIST, myTargetClass); - } - } - else if (ExtractUtil.isSingleExpression(statements)) { - final GrStatement lastExpr = statements[statements.length - 1]; - if (!(lastExpr.getParent() instanceof GrCodeBlock)) { - outputType = ((GrExpression)lastExpr).getType(); - } - } - else { - if (myIsReturnStatement) { - assert returnStatements.size() > 0; - List types = new ArrayList(returnStatements.size()); - for (GrStatement statement : returnStatements) { - if (statement instanceof GrReturnStatement) { - GrExpression returnValue = ((GrReturnStatement)statement).getReturnValue(); - if (returnValue != null) { - types.add(returnValue.getType()); - } - } - else if (statement instanceof GrExpression) { - types.add(((GrExpression)statement).getType()); - } - } - outputType = TypesUtil.getLeastUpperBoundNullable(types, targetClass.getManager()); - } - } - myOutputType = outputType != null ? outputType : PsiType.VOID; + myIsStatic = ExtractUtil.canBeStatic(initialInfo.getStatements()[0]); } + @Override @NotNull public Project getProject() { - return myProject; - } - - public ParameterInfo[] getParameterInfos() { - Collection collection = myInputNamesMap.values(); - ParameterInfo[] infos = new ParameterInfo[collection.size()]; - for (ParameterInfo info : collection) { - int position = info.getPosition(); - assert position < infos.length && infos[position] == null; - infos[position] = info; - } - return infos; + return myInitialInfo.getProject(); } + @NotNull + @Override + public ParameterInfo[] getParameterInfos() { + return myInitialInfo.getParameterInfos(); + } + + @Override @NotNull public VariableInfo[] getOutputNames() { - return myOutputNames; + return myInitialInfo.getOutputNames(); } /** @@ -141,30 +72,28 @@ public class ExtractMethodInfoHelper { * * @return array of argument names */ + @NotNull + @Override public String[] getArgumentNames() { - Collection infos = myInputNamesMap.values(); - String[] argNames = new String[infos.size()]; - for (ParameterInfo info : infos) { - int position = info.getPosition(); - assert position < argNames.length; - argNames[position] = info.passAsParameter() ? info.getOldName() : ""; - } - return argNames; + return myInitialInfo.getArgumentNames(); } + @Override @NotNull public PsiType getOutputType() { - return myOutputType; + return myInitialInfo.getOutputType(); } + @Override @NotNull public PsiElement[] getInnerElements() { - return myInnerElements; + return myInitialInfo.getInnerElements(); } + @Override @NotNull public GrStatement[] getStatements() { - return myStatements; + return myInitialInfo.getStatements(); } public boolean isStatic() { @@ -187,12 +116,21 @@ public class ExtractMethodInfoHelper { mySpecifyType = specifyType; } + @Override @NotNull public GrMemberOwner getOwner() { - return myTargetClass; + return myInitialInfo.getOwner(); } - public boolean isReturnStatement() { - return myIsReturnStatement; + public boolean hasReturnValue() { + return myInitialInfo.hasReturnValue(); + } + + public String getName() { + return myName; + } + + public void setName(String name) { + myName = name; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java index f6632083aaf0..9e00c8151408 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java @@ -30,6 +30,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil; +import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInitialInfo; import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil; import org.jetbrains.plugins.groovy.refactoring.extract.ParameterTablePanel; import org.jetbrains.plugins.groovy.settings.GroovyApplicationSettings; @@ -49,8 +50,9 @@ import java.util.EventListener; */ public class GroovyExtractMethodDialog extends DialogWrapper { + private final ExtractInitialInfo myInfo; private final ExtractMethodInfoHelper myHelper; - private final Project myProject; + private final EventListenerList myListenerList = new EventListenerList(); private JPanel contentPane; @@ -60,17 +62,18 @@ public class GroovyExtractMethodDialog extends DialogWrapper { private JTextArea mySignatureArea; private VisibilityPanel myVisibilityPanel; private ParameterTablePanel myParameterTablePanel; -// private JButton buttonOK; + private final Project myProject; + + public GroovyExtractMethodDialog(ExtractInitialInfo info) { + super(info.getProject(), true); + myProject = info.getProject(); + myInfo = info; + myHelper = new ExtractMethodInfoHelper(info, ""); - public GroovyExtractMethodDialog(ExtractMethodInfoHelper helper, Project project) { - super(project, true); - myProject = project; - myHelper = helper; setUpNameField(); - myParameterTablePanel.init(this, myHelper); + myParameterTablePanel.init(this, myInfo); setModal(true); -// getRootPane().setDefaultButton(buttonOK); setTitle(GroovyExtractMethodHandler.REFACTORING_NAME); init(); setUpDialog(); @@ -94,9 +97,8 @@ public class GroovyExtractMethodDialog extends DialogWrapper { private void setUpDialog() { myCbSpecifyType.setMnemonic(KeyEvent.VK_T); myCbSpecifyType.setFocusable(false); - myCbSpecifyType.setEnabled(myHelper.specifyType()); - myCbSpecifyType.setSelected(myHelper.specifyType()); - if (myCbSpecifyType.isEnabled() && GroovyApplicationSettings.getInstance().EXTRACT_METHOD_SPECIFY_TYPE != null) { + myCbSpecifyType.setSelected(true); + if (GroovyApplicationSettings.getInstance().EXTRACT_METHOD_SPECIFY_TYPE != null) { myCbSpecifyType.setSelected(GroovyApplicationSettings.getInstance().EXTRACT_METHOD_SPECIFY_TYPE); } @@ -148,6 +150,7 @@ public class GroovyExtractMethodDialog extends DialogWrapper { private void update() { String text = getEnteredName(); + myHelper.setName(text); updateSignature(); setOKActionEnabled(GroovyNamesUtil.isIdentifier(text)); } @@ -157,7 +160,8 @@ public class GroovyExtractMethodDialog extends DialogWrapper { String text = myNameField.getText(); if (text != null && text.trim().length() > 0) { return text.trim(); - } else { + } + else { return null; } } @@ -203,7 +207,7 @@ public class GroovyExtractMethodDialog extends DialogWrapper { Object[] list = myListenerList.getListenerList(); for (Object aList : list) { if (aList instanceof DataChangedListener) { - ((DataChangedListener) aList).dataChanged(); + ((DataChangedListener)aList).dataChanged(); } } } @@ -246,12 +250,12 @@ public class GroovyExtractMethodDialog extends DialogWrapper { } @NotNull - public ExtractMethodInfoHelper getHelper() { - return myHelper; - } + public ExtractMethodInfoHelper getHelper() { + return myHelper; + } public String getEnteredName() { - return myEnteredName; - } + return myEnteredName; + } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java index 91579bdb4ea7..1e22a071c5a3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java @@ -17,7 +17,6 @@ package org.jetbrains.plugins.groovy.refactoring.extract.method; import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; @@ -25,219 +24,62 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.refactoring.HelpID; import com.intellij.refactoring.RefactoringActionHandler; -import com.intellij.refactoring.RefactoringBundle; -import com.intellij.refactoring.util.CommonRefactoringUtil; -import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; import org.jetbrains.plugins.groovy.lang.GrReferenceAdjuster; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; -import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner; -import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; -import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner; -import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.FragmentVariableInfos; -import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.ReachingDefinitionsCollector; -import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; -import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; +import org.jetbrains.plugins.groovy.refactoring.extract.ExtractException; +import org.jetbrains.plugins.groovy.refactoring.extract.ExtractHandlerBase; +import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInitialInfo; import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - /** * @author ilyas */ -public class GroovyExtractMethodHandler implements RefactoringActionHandler { +public class GroovyExtractMethodHandler extends ExtractHandlerBase implements RefactoringActionHandler { private static final Logger LOG = Logger.getInstance(GroovyExtractMethodHandler.class); protected static String REFACTORING_NAME = GroovyRefactoringBundle.message("extract.method.title"); private String myInvokeResult = "ok"; - protected void showErrorMessage(String message, final Project project, Editor editor) { - Application application = ApplicationManager.getApplication(); - myInvokeResult = message; - if (!application.isUnitTestMode()) { - CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.EXTRACT_METHOD); - } + public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { + invoke(project, editor, file); } - public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { + void invoke(Project project, Editor editor, PsiFile file) { editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); // select editor text fragment - if (!editor.getSelectionModel().hasSelection()) { - editor.getSelectionModel().selectLineAtCaret(); + final SelectionModel model = editor.getSelectionModel(); + if (!model.hasSelection()) { + model.selectLineAtCaret(); + } + + try { + invokeOnEditor(project, editor, file, model.getSelectionStart(), model.getSelectionEnd()); + } + catch (ExtractException e) { + myInvokeResult = e.getMessage(); } - invokeOnEditor(project, editor, file); } - boolean invokeOnEditor(Project project, Editor editor, PsiFile file) { - // trim it if it's necessary - GroovyRefactoringUtil.trimSpacesAndComments(editor, file, false); - - //todo implement in GSP files - if (!(file instanceof GroovyFileBase /* || file instanceof GspFile*/)) { - String message = RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("only.in.groovy.files")); - showErrorMessage(message, project, editor); - return false; - } - - SelectionModel selectionModel = editor.getSelectionModel(); - int startOffset = selectionModel.getSelectionStart(); - int endOffset = selectionModel.getSelectionEnd(); - PsiDocumentManager.getInstance(project).commitAllDocuments(); - - PsiElement[] elements = ExtractUtil.getElementsInOffset(file, startOffset, endOffset); - if (elements.length == 1 && elements[0] instanceof GrExpression) { - selectionModel.setSelection(startOffset, elements[0].getTextRange().getEndOffset()); - } - - GrStatement[] statements = ExtractUtil.getStatementsByElements(elements); - - if (statements.length == 0) { - String message = RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("selected.block.should.represent.a.statement.set")); - showErrorMessage(message, project, editor); - return false; - } - - // test for this or super constructor calls - for (GrStatement statement : statements) { - if (GroovyRefactoringUtil.isSuperOrThisCall(statement, true, true)) { - String message = RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("selected.block.contains.invocation.of.another.class.constructor")); - showErrorMessage(message, project, editor); - return false; - } - } - - GrStatement statement0 = statements[0]; - GrMemberOwner owner = ExtractUtil.getMemberOwner(statement0); - GrStatementOwner declarationOwner = ExtractUtil.getDeclarationOwner(statement0); - if (owner == null || declarationOwner == null && !ExtractUtil.isSingleExpression(statements)) { - String message = RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("refactoring.is.not.supported.in.the.current.context")); - showErrorMessage(message, project, editor); - return false; - } - if (declarationOwner == null && - ExtractUtil.isSingleExpression(statements) && - statement0 instanceof GrExpression && - PsiType.VOID.equals(((GrExpression)statement0).getType())) { - String message = RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("selected.expression.has.void.type")); - showErrorMessage(message, project, editor); - return false; - } - - - // collect information about return statements in selected statement set - - Set allReturnStatements = new HashSet(); - GrControlFlowOwner controlFlowOwner = ControlFlowUtils.findControlFlowOwner(statement0); - assert controlFlowOwner != null; - allReturnStatements.addAll(ControlFlowUtils.collectReturns(controlFlowOwner, true)); - - ArrayList returnStatements = new ArrayList(); - for (GrStatement returnStatement : allReturnStatements) { - for (GrStatement statement : statements) { - if (PsiTreeUtil.isAncestor(statement, returnStatement, false)) { - returnStatements.add(returnStatement); - break; - } - } - } - - // collect information about variables in selected block - FragmentVariableInfos fragmentVariableInfos = ReachingDefinitionsCollector.obtainVariableFlowInformation(statement0, statements[statements.length - 1]); - VariableInfo[] inputInfos = fragmentVariableInfos.getInputVariableNames(); - VariableInfo[] outputInfos = fragmentVariableInfos.getOutputVariableNames(); - if (outputInfos.length == 1 && returnStatements.size() > 0) { - String message = GroovyRefactoringBundle.message("multiple.output.values"); - showErrorMessage(message, project, editor); - return false; - } - - boolean hasInterruptingStatements = false; - - for (GrStatement statement : statements) { - hasInterruptingStatements = GroovyRefactoringUtil.hasWrongBreakStatements(statement) || GroovyRefactoringUtil.haswrongContinueStatements(statement); - if (hasInterruptingStatements) break; - } - - // must be replaced by return statement - boolean hasReturns = returnStatements.size() > 0; - List returnStatementsCopy = new ArrayList(returnStatements.size()); - returnStatementsCopy.addAll(returnStatements); - boolean isReturnStatement = ExtractUtil.isReturnStatement(statements[statements.length - 1], returnStatementsCopy); - boolean isLastStatementOfMethod = isLastStatementOfMethodOrClosure(statements); - if (hasReturns && !isLastStatementOfMethod && !isReturnStatement || hasInterruptingStatements) { - String message = GroovyRefactoringBundle.message("refactoring.is.not.supported.when.return.statement.interrupts.the.execution.flow"); - showErrorMessage(message, project, editor); - return false; - } - - boolean canBeStatic = ExtractUtil.canBeStatic(statement0); - - ExtractMethodInfoHelper helper = new ExtractMethodInfoHelper(inputInfos, outputInfos, elements, statements, owner, canBeStatic, returnStatements); - - final String methodName; - if (!ApplicationManager.getApplication().isUnitTestMode()) { - GroovyExtractMethodDialog dialog = getDialog(helper); - if (!dialog.isOK()) { - return false; - } - ExtractMethodSettings settings = dialog.getSettings(); - methodName = settings.getEnteredName(); - helper = settings.getHelper(); - } - else { - methodName = "testMethod"; - } - - assert methodName != null; - runRefactoring(methodName, helper, owner, declarationOwner, editor, statement0); - - return true; - } - - private static boolean isLastStatementOfMethodOrClosure(GrStatement[] statements) { - final GrStatement statement0 = statements[0]; - - PsiElement returnFrom = PsiTreeUtil.getParentOfType(statement0, GrMethod.class, GrClosableBlock.class, GroovyFile.class); - if (returnFrom instanceof GrMethod) { - returnFrom = ((GrMethod)returnFrom).getBlock(); - } - LOG.assertTrue(returnFrom instanceof GrStatementOwner); - - final GrStatement[] blockStatements = ((GrStatementOwner)returnFrom).getStatements(); - final GrStatement lastFromBlock = ArrayUtil.getLastElement(blockStatements); - final GrStatement lastStatement = ArrayUtil.getLastElement(statements); - return statement0.getManager().areElementsEquivalent(lastFromBlock, lastStatement); - } - - private static void runRefactoring(final String methodName, - @NotNull final ExtractMethodInfoHelper helper, - @NotNull final GrMemberOwner owner, - final GrStatementOwner declarationOwner, - final Editor editor, - final PsiElement startElement) { + public void performRefactoring(@NotNull final ExtractMethodInfoHelper helper, + @NotNull final GrMemberOwner owner, + final GrStatementOwner declarationOwner, + final Editor editor, + final PsiElement startElement) { + final String methodName = helper.getName(); final GrMethod method = ExtractUtil.createMethodByHelper(methodName, helper); final Runnable runnable = new Runnable() { public void run() { @@ -298,10 +140,22 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { }, REFACTORING_NAME, null); } - private static GroovyExtractMethodDialog getDialog(@NotNull final ExtractMethodInfoHelper helper) { - GroovyExtractMethodDialog dialog = new GroovyExtractMethodDialog(helper, helper.getProject()); + @Override + public ExtractMethodInfoHelper getSettings(@NotNull ExtractInitialInfo initialInfo) { + if (ApplicationManager.getApplication().isUnitTestMode()) { + final ExtractMethodInfoHelper helper = new ExtractMethodInfoHelper(initialInfo, "testMethod"); + final PsiType type = helper.getOutputType(); + if (type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) || type.equalsToText("void")) { + helper.setSpecifyType(false); + } + return helper; + } + + GroovyExtractMethodDialog dialog = new GroovyExtractMethodDialog(initialInfo); dialog.show(); - return dialog; + if (!dialog.isOK()) return null; + + return dialog.getHelper(); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.java index 0d1f0908d7c2..ca9a658db497 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.java @@ -35,7 +35,7 @@ public class ExtractMethodTest extends LightGroovyTestCase { private void doAntiTest(String errorMessage) throws Exception { GroovyExtractMethodHandler handler = configureFromText(readInput().get(0)); - assertFalse(handler.invokeOnEditor(getProject(), myFixture.getEditor(), myFixture.getFile())); + handler.invoke(getProject(), myFixture.getEditor(), myFixture.getFile()); assertEquals(errorMessage, handler.getInvokeResult()); } @@ -46,7 +46,7 @@ public class ExtractMethodTest extends LightGroovyTestCase { private void doTest() { final List data = readInput(); GroovyExtractMethodHandler handler = configureFromText(data.get(0)); - assertTrue(handler.invokeOnEditor(getProject(), myFixture.getEditor(), myFixture.getFile())); + handler.invoke(getProject(), myFixture.getEditor(), myFixture.getFile()); PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting(); myFixture.checkResult(StringUtil.trimEnd(data.get(1), "\n")); } diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/forIn.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/forIn.test index a25df26b9779..3c6fde91bc6d 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/forIn.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/forIn.test @@ -7,11 +7,11 @@ void aaa(Map map) { ----- void aaa(Map map) { for (Map.Entry versionEntry in map.entrySet()) { - testMethod(versionEntry); + testMethod(versionEntry) } } private testMethod(Map.Entry versionEntry) { String name = versionEntry.getKey(); - System.out.println(name) + System.out.println(name); } From 964394ccd7791a6d83a87bb76d77dcc3abf243bb Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Tue, 17 Jan 2012 23:38:53 +0400 Subject: [PATCH 3/7] Improve Extract method dialog for Groovy --- .../extract/ExtractHandlerBase.java | 4 +- .../refactoring/extract/ExtractUtil.java | 13 +- ...tractInitialInfo.java => InitialInfo.java} | 14 +- .../extract/ParameterTablePanel.java | 152 ++++-------------- .../method/ExtractMethodInfoHelper.java | 6 +- .../method/GroovyExtractMethodDialog.form | 87 ++++++---- .../method/GroovyExtractMethodDialog.java | 42 +++-- .../method/GroovyExtractMethodHandler.java | 4 +- .../extract/method/VisibilityPanel.java | 119 -------------- .../ui/GroovyComboboxVisibilityPanel.java | 38 +++++ 10 files changed, 170 insertions(+), 309 deletions(-) rename plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/{ExtractInitialInfo.java => InitialInfo.java} (93%) delete mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/VisibilityPanel.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GroovyComboboxVisibilityPanel.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractHandlerBase.java index df659404b69e..3f6a56b4b6e6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractHandlerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractHandlerBase.java @@ -152,7 +152,7 @@ public abstract class ExtractHandlerBase i throw new ExtractException(message); } - ExtractInitialInfo info = new ExtractInitialInfo(inputInfos, outputInfos, elements, statements, owner, returnStatements); + InitialInfo info = new InitialInfo(inputInfos, outputInfos, elements, statements, owner, returnStatements); InfoHelper helper = getSettings(info); if (helper == null) return; @@ -176,7 +176,7 @@ public abstract class ExtractHandlerBase i } @Nullable - public abstract InfoHelper getSettings(@NotNull final ExtractInitialInfo initialInfo); + public abstract InfoHelper getSettings(@NotNull final InitialInfo initialInfo); public abstract void performRefactoring(@NotNull final InfoHelper helper, @NotNull final GrMemberOwner owner, diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java index 0aa400e6b910..c89e133b7141 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java @@ -302,7 +302,7 @@ public class ExtractUtil { buffer.append(typeText); buffer.append(name); buffer.append("("); - for (String param : getParameterString(helper)) { + for (String param : getParameterString(helper, true)) { buffer.append(param); } buffer.append(") { \n"); @@ -364,7 +364,7 @@ public class ExtractUtil { return method; } - public static String[] getParameterString(ExtractMethodInfoHelper helper) { + public static String[] getParameterString(ExtractMethodInfoHelper helper, boolean useCanonicalText) { int i = 0; ParameterInfo[] infos = helper.getParameterInfos(); int number = 0; @@ -377,7 +377,14 @@ public class ExtractUtil { PsiType paramType = info.getType(); final PsiPrimitiveType unboxed = PsiPrimitiveType.getUnboxedType(paramType); if (unboxed != null) paramType = unboxed; - String paramTypeText = paramType == null || paramType.equalsToText("java.lang.Object") ? "" : paramType.getCanonicalText() + " "; + String paramTypeText; + + if (paramType == null || paramType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) { + paramTypeText = ""; + } + else { + paramTypeText = (useCanonicalText ? paramType.getCanonicalText() : paramType.getPresentableText()) + " "; + } params.add(paramTypeText + info.getName() + (i < number - 1 ? ", " : "")); i++; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInitialInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java similarity index 93% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInitialInfo.java rename to plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java index 96937108b4f4..6067446caf81 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInitialInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java @@ -37,7 +37,7 @@ import java.util.*; /** * @author Max Medvedev */ -public class ExtractInitialInfo implements ExtractInfoHelper { +public class InitialInfo implements ExtractInfoHelper { private final Map myInputNamesMap = new HashMap(); private final VariableInfo[] myOutputNames; private final PsiType myOutputType; @@ -47,12 +47,12 @@ public class ExtractInitialInfo implements ExtractInfoHelper { private final GrStatement[] myStatements; private final boolean myHasReturnValue; - public ExtractInitialInfo(VariableInfo[] inputInfos, - VariableInfo[] outputInfos, - PsiElement[] innerElements, - GrStatement[] statements, - GrMemberOwner targetClass, - ArrayList returnStatements) { + public InitialInfo(VariableInfo[] inputInfos, + VariableInfo[] outputInfos, + PsiElement[] innerElements, + GrStatement[] statements, + GrMemberOwner targetClass, + ArrayList returnStatements) { myInnerElements = innerElements; myStatements = statements; myTargetClass = targetClass; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java index fc85f7f8739b..21f352a118cd 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java @@ -25,24 +25,22 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.ui.TypeSelector; import com.intellij.ui.BooleanTableCellRenderer; import com.intellij.ui.IdeBorderFactory; -import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.TableUtil; +import com.intellij.ui.ToolbarDecorator; import com.intellij.ui.table.JBTable; import com.intellij.util.ui.AbstractTableCellEditor; +import com.intellij.util.ui.EditableModel; import org.jetbrains.annotations.NonNls; import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; import org.jetbrains.plugins.groovy.refactoring.extract.method.GroovyExtractMethodDialog; import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellEditor; import java.awt.*; import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.KeyEvent; /** @@ -56,15 +54,13 @@ public class ParameterTablePanel extends JPanel { private JBTable myTable; private MyTableModel myTableModel; - private JButton myUpButton; - private JButton myDownButton; private JComboBox myTypeRendererCombo; public ParameterTablePanel() { super(new BorderLayout()); } - public void init(GroovyExtractMethodDialog dialog, ExtractInitialInfo helper) { + public void init(GroovyExtractMethodDialog dialog, InitialInfo helper) { setBorder(IdeBorderFactory.createTitledBorder(GroovyRefactoringBundle.message("parameters.border.title"), false, false, true)); @@ -214,124 +210,8 @@ public class ParameterTablePanel extends JPanel { } }); - JPanel listPanel = new JPanel(new BorderLayout()); - JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTable); - listPanel.add(scrollPane, BorderLayout.CENTER); - listPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); + JPanel listPanel = ToolbarDecorator.createDecorator(myTable).disableAddAction().disableRemoveAction().createPanel(); add(listPanel, BorderLayout.CENTER); - - JPanel buttonsPanel = new JPanel(); - buttonsPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); - add(buttonsPanel, BorderLayout.EAST); - - buttonsPanel.setLayout(new GridBagLayout()); - GridBagConstraints gbConstraints = new GridBagConstraints(); - gbConstraints.gridwidth = GridBagConstraints.REMAINDER; - gbConstraints.fill = GridBagConstraints.HORIZONTAL; - gbConstraints.insets = new Insets(2, 4, 2, 4); - - myUpButton = new JButton(); - myUpButton.setText(GroovyRefactoringBundle.message("row.move.up")); - myUpButton.setDefaultCapable(false); - myUpButton.setMnemonic(KeyEvent.VK_U); - buttonsPanel.add(myUpButton, gbConstraints); - - myDownButton = new JButton(); - myDownButton.setText(GroovyRefactoringBundle.message("row.move.down")); - myDownButton.setMnemonic(KeyEvent.VK_D); - myDownButton.setDefaultCapable(false); - buttonsPanel.add(myDownButton, gbConstraints); - - gbConstraints.weighty = 1; - buttonsPanel.add(new JPanel(), gbConstraints); - - myUpButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (myTable.isEditing()) { - final boolean isStopped = myTable.getCellEditor().stopCellEditing(); - if (!isStopped) return; - } - moveSelectedItem(-1); - updateSignature(); - myTable.requestFocus(); - } - }); - - myDownButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (myTable.isEditing()) { - final boolean isStopped = myTable.getCellEditor().stopCellEditing(); - if (!isStopped) return; - } - moveSelectedItem(+1); - updateSignature(); - myTable.requestFocus(); - } - }); - - myTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - public void valueChanged(ListSelectionEvent e) { - updateMoveButtons(); - } - }); - if (myParameterInfos.length <= 1) { - myUpButton.setEnabled(false); - myDownButton.setEnabled(false); - } - else { - myTable.getSelectionModel().setSelectionInterval(0, 0); - } - updateMoveButtons(); - } - - private void updateMoveButtons() { - int row = myTable.getSelectedRow(); - if (0 <= row && row < myParameterInfos.length) { - myUpButton.setEnabled(row > 0); - myDownButton.setEnabled(row < myParameterInfos.length - 1); - } - else { - myUpButton.setEnabled(false); - myDownButton.setEnabled(false); - } - } - - public void setEnabled(boolean enabled) { - myTable.setEnabled(enabled); - if (!enabled) { - myUpButton.setEnabled(false); - myDownButton.setEnabled(false); - } - else { - updateMoveButtons(); - } - super.setEnabled(enabled); - } - - - private void moveSelectedItem(int moveIncrement) { - int row = myTable.getSelectedRow(); - if (row < 0 || row >= myParameterInfos.length) return; - int targetRow = row + moveIncrement; - if (targetRow < 0 || targetRow >= myParameterInfos.length) return; - - ParameterInfo currentItem = myParameterInfos[row]; - int currentPosition = currentItem.getPosition(); - ParameterInfo targetItem = myParameterInfos[targetRow]; - - // Change real parameter position - currentItem.setPosition(targetItem.getPosition()); - targetItem.setPosition(currentPosition); - - myParameterInfos[row] = targetItem; - myParameterInfos[targetRow] = currentItem; - - TypeSelector currentSelector = myParameterTypeSelectors[row]; - myParameterTypeSelectors[row] = myParameterTypeSelectors[targetRow]; - myParameterTypeSelectors[targetRow] = currentSelector; - myTypeRendererCombo.setModel(new DefaultComboBoxModel(myParameterInfos)); - myTableModel.fireTableRowsUpdated(Math.min(targetRow, row), Math.max(targetRow, row)); - myTable.getSelectionModel().setSelectionInterval(targetRow, targetRow); } protected void updateSignature(){ @@ -346,11 +226,33 @@ public class ParameterTablePanel extends JPanel { myDialog.doCancelAction(); } - private class MyTableModel extends AbstractTableModel { + private class MyTableModel extends AbstractTableModel implements EditableModel { public static final int CHECKMARK_COLUMN = 0; public static final int PARAMETER_TYPE_COLUMN = 1; public static final int PARAMETER_NAME_COLUMN = 2; + @Override + public void addRow() { + throw new IllegalAccessError("Not implemented"); + } + + @Override + public void removeRow(int index) { + throw new IllegalAccessError("Not implemented"); + } + + @Override + public void exchangeRows(int oldIndex, int newIndex) { + if (oldIndex<0 || newIndex<0) return; + if (oldIndex>=myParameterInfos.length || newIndex>=myParameterInfos.length) return; + + final ParameterInfo old = myParameterInfos[oldIndex]; + myParameterInfos[oldIndex] = myParameterInfos[newIndex]; + myParameterInfos[newIndex] = old; + fireTableRowsUpdated(Math.min(oldIndex, newIndex), Math.max(oldIndex, newIndex)); + updateSignature(); + } + public int getRowCount() { return myParameterInfos.length; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java index a602782dc6e3..a45ab8e3542e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java @@ -25,22 +25,22 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInfoHelper; -import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInitialInfo; import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil; +import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo; import org.jetbrains.plugins.groovy.refactoring.extract.ParameterInfo; /** * @author ilyas */ public class ExtractMethodInfoHelper implements ExtractInfoHelper { - private final ExtractInitialInfo myInitialInfo; + private final InitialInfo myInitialInfo; private final boolean myIsStatic; private boolean mySpecifyType = true; private String myVisibility; private String myName; - public ExtractMethodInfoHelper(ExtractInitialInfo initialInfo, String name) { + public ExtractMethodInfoHelper(InitialInfo initialInfo, String name) { myInitialInfo = initialInfo; myVisibility = PsiModifier.PRIVATE; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.form index f6e377893239..dd89443258c5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.form @@ -1,6 +1,6 @@
- + @@ -11,7 +11,7 @@ - + @@ -19,34 +19,24 @@ - + - - - - - + - + - + - - - - - - @@ -55,30 +45,61 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java index 9e00c8151408..1d4d07acc645 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java @@ -16,6 +16,7 @@ package org.jetbrains.plugins.groovy.refactoring.extract.method; +import com.intellij.ide.highlighter.JavaFileType; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.help.HelpManager; @@ -23,6 +24,8 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.psi.PsiModifier; import com.intellij.refactoring.HelpID; +import com.intellij.refactoring.ui.ComboBoxVisibilityPanel; +import com.intellij.refactoring.ui.MethodSignatureComponent; import com.intellij.ui.EditorTextField; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -30,15 +33,17 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil; -import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInitialInfo; import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil; +import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo; import org.jetbrains.plugins.groovy.refactoring.extract.ParameterTablePanel; +import org.jetbrains.plugins.groovy.refactoring.ui.GroovyComboboxVisibilityPanel; import org.jetbrains.plugins.groovy.settings.GroovyApplicationSettings; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.EventListenerList; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; @@ -49,8 +54,6 @@ import java.util.EventListener; * @author ilyas */ public class GroovyExtractMethodDialog extends DialogWrapper { - - private final ExtractInitialInfo myInfo; private final ExtractMethodInfoHelper myHelper; private final EventListenerList myListenerList = new EventListenerList(); @@ -59,19 +62,18 @@ public class GroovyExtractMethodDialog extends DialogWrapper { private EditorTextField myNameField; private JCheckBox myCbSpecifyType; private JLabel myNameLabel; - private JTextArea mySignatureArea; - private VisibilityPanel myVisibilityPanel; + private MethodSignatureComponent mySignature; + private ComboBoxVisibilityPanel myVisibilityPanel; private ParameterTablePanel myParameterTablePanel; private final Project myProject; - public GroovyExtractMethodDialog(ExtractInitialInfo info) { + public GroovyExtractMethodDialog(InitialInfo info) { super(info.getProject(), true); myProject = info.getProject(); - myInfo = info; myHelper = new ExtractMethodInfoHelper(info, ""); setUpNameField(); - myParameterTablePanel.init(this, myInfo); + myParameterTablePanel.init(this, info); setModal(true); setTitle(GroovyExtractMethodHandler.REFACTORING_NAME); @@ -179,17 +181,27 @@ public class GroovyExtractMethodDialog extends DialogWrapper { } private void createUIComponents() { + mySignature = new MethodSignatureComponent("", myProject, JavaFileType.INSTANCE) { + @Override + protected String getFileName() { + return "dummy." + GroovyFileType.GROOVY_FILE_TYPE.getDefaultExtension(); + } + }; + mySignature.setPreferredSize(new Dimension(500, 100)); + mySignature.setMinimumSize(new Dimension(500, 100)); + myNameField = new EditorTextField("", myProject, GroovyFileType.GROOVY_FILE_TYPE); - myVisibilityPanel = new VisibilityPanel(); + myVisibilityPanel = new GroovyComboboxVisibilityPanel(); String visibility = GroovyApplicationSettings.getInstance().EXTRACT_METHOD_VISIBILITY; if (visibility == null) { visibility = PsiModifier.PRIVATE; } myVisibilityPanel.setVisibility(visibility); - myVisibilityPanel.addStateChangedListener(new VisibilityPanel.VisibilityStateChanged() { - public void visibilityChanged(String newVisibility) { - myHelper.setVisibility(newVisibility); + myVisibilityPanel.addListener(new ChangeListener(){ + @Override + public void stateChanged(ChangeEvent e) { + myHelper.setVisibility(myVisibilityPanel.getVisibility()); updateSignature(); } }); @@ -216,7 +228,7 @@ public class GroovyExtractMethodDialog extends DialogWrapper { Update signature text area */ public void updateSignature() { - if (mySignatureArea == null) return; + if (mySignature == null) return; @NonNls StringBuilder buffer = new StringBuilder(); String modifier = ExtractUtil.getModifierString(myHelper); buffer.append(modifier); @@ -224,7 +236,7 @@ public class GroovyExtractMethodDialog extends DialogWrapper { String name = getEnteredName() == null ? "" : getEnteredName(); buffer.append(name); buffer.append("("); - String[] params = ExtractUtil.getParameterString(myHelper); + String[] params = ExtractUtil.getParameterString(myHelper, false); if (params.length > 0) { String INDENT = " "; buffer.append("\n"); @@ -233,7 +245,7 @@ public class GroovyExtractMethodDialog extends DialogWrapper { } } buffer.append(")"); - mySignatureArea.setText(buffer.toString()); + mySignature.setSignature(buffer.toString()); } public ExtractMethodSettings getSettings() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java index 1e22a071c5a3..ec50b31297f3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java @@ -41,8 +41,8 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; import org.jetbrains.plugins.groovy.refactoring.extract.ExtractException; import org.jetbrains.plugins.groovy.refactoring.extract.ExtractHandlerBase; -import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInitialInfo; import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil; +import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo; /** * @author ilyas @@ -141,7 +141,7 @@ public class GroovyExtractMethodHandler extends ExtractHandlerBase Date: Wed, 18 Jan 2012 11:15:26 +0400 Subject: [PATCH 4/7] update on order change of parameters --- .../extract/ExtractInfoHelperBase.java | 119 ++++++++++++++++++ .../refactoring/extract/ExtractUtil.java | 2 +- .../refactoring/extract/InitialInfo.java | 36 ++---- .../extract/ParameterTablePanel.java | 42 +++---- .../method/ExtractMethodInfoHelper.java | 72 +---------- .../method/GroovyExtractMethodDialog.java | 25 ++-- .../ui/GrMethodSignatureComponent.java | 37 ++++++ 7 files changed, 208 insertions(+), 125 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelperBase.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrMethodSignatureComponent.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelperBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelperBase.java new file mode 100644 index 000000000000..c253ceb53596 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelperBase.java @@ -0,0 +1,119 @@ +/* + * Copyright 2000-2012 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 org.jetbrains.plugins.groovy.refactoring.extract; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; +import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Max Medvedev + */ +public class ExtractInfoHelperBase implements ExtractInfoHelper { + protected final InitialInfo myInitialInfo; + protected final Map myInputNamesMap; + + public ExtractInfoHelperBase( + InitialInfo initialInfo) { + myInitialInfo = initialInfo; + + final ParameterInfo[] infos = initialInfo.getParameterInfos(); + myInputNamesMap = new HashMap(infos.length); + for (ParameterInfo info : infos) { + myInputNamesMap.put(info.getName(), info); + } + } + + @Override + @NotNull + public Project getProject() { + return myInitialInfo.getProject(); + } + + @NotNull + @Override + public ParameterInfo[] getParameterInfos() { + Collection collection = myInputNamesMap.values(); + ParameterInfo[] infos = new ParameterInfo[collection.size()]; + for (ParameterInfo info : collection) { + int position = info.getPosition(); + assert position < infos.length && infos[position] == null; + infos[position] = info; + } + return infos; + } + + @Override + @NotNull + public VariableInfo[] getOutputNames() { + return myInitialInfo.getOutputNames(); + } + + /** + * Get old names of parameters to be pasted as method call arguments + * + * @return array of argument names + */ + @NotNull + @Override + public String[] getArgumentNames() { + Collection infos = myInputNamesMap.values(); + String[] argNames = new String[infos.size()]; + for (ParameterInfo info : infos) { + int position = info.getPosition(); + assert position < argNames.length; + argNames[position] = info.passAsParameter() ? info.getOldName() : ""; + } + return argNames; + + } + + @Override + @NotNull + public PsiType getOutputType() { + return myInitialInfo.getOutputType(); + } + + @Override + @NotNull + public PsiElement[] getInnerElements() { + return myInitialInfo.getInnerElements(); + } + + @Override + @NotNull + public GrStatement[] getStatements() { + return myInitialInfo.getStatements(); + } + + @Override + @NotNull + public GrMemberOwner getOwner() { + return myInitialInfo.getOwner(); + } + + public boolean hasReturnValue() { + return myInitialInfo.hasReturnValue(); + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java index c89e133b7141..26db5d4ee16e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java @@ -364,7 +364,7 @@ public class ExtractUtil { return method; } - public static String[] getParameterString(ExtractMethodInfoHelper helper, boolean useCanonicalText) { + public static String[] getParameterString(ExtractInfoHelper helper, boolean useCanonicalText) { int i = 0; ParameterInfo[] infos = helper.getParameterInfos(); int number = 0; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java index 6067446caf81..f25d36007bb9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java @@ -32,13 +32,14 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwne import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; -import java.util.*; +import java.util.ArrayList; +import java.util.List; /** * @author Max Medvedev */ public class InitialInfo implements ExtractInfoHelper { - private final Map myInputNamesMap = new HashMap(); + private final ParameterInfo[] myParameterInfos; private final VariableInfo[] myOutputNames; private final PsiType myOutputType; private final GrMemberOwner myTargetClass; @@ -46,6 +47,7 @@ public class InitialInfo implements ExtractInfoHelper { private final Project myProject; private final GrStatement[] myStatements; private final boolean myHasReturnValue; + private String[] myArgumentNames; public InitialInfo(VariableInfo[] inputInfos, VariableInfo[] outputInfos, @@ -67,12 +69,14 @@ public class InitialInfo implements ExtractInfoHelper { assert myStatements.length > 0; myProject = myStatements[0].getProject(); - int i = 0; - for (VariableInfo info : inputInfos) { + + myParameterInfos = new ParameterInfo[inputInfos.length]; + myArgumentNames = new String[inputInfos.length]; + for (int i = 0; i < inputInfos.length; i++) { + VariableInfo info = inputInfos[i]; PsiType type = info.getType(); - ParameterInfo pInfo = new ParameterInfo(info.getName(), i, type); - myInputNamesMap.put(info.getName(), pInfo); - i++; + myParameterInfos[i] = new ParameterInfo(info.getName(), i, type); + myArgumentNames[i] = info.getName(); } PsiType outputType = inferOutputType(outputInfos, statements, targetClass, returnStatements, myHasReturnValue); @@ -128,14 +132,7 @@ public class InitialInfo implements ExtractInfoHelper { @NotNull @Override public ParameterInfo[] getParameterInfos() { - Collection collection = myInputNamesMap.values(); - ParameterInfo[] infos = new ParameterInfo[collection.size()]; - for (ParameterInfo info : collection) { - int position = info.getPosition(); - assert position < infos.length && infos[position] == null; - infos[position] = info; - } - return infos; + return myParameterInfos; } @Override @@ -152,14 +149,7 @@ public class InitialInfo implements ExtractInfoHelper { @NotNull @Override public String[] getArgumentNames() { - Collection infos = myInputNamesMap.values(); - String[] argNames = new String[infos.size()]; - for (ParameterInfo info : infos) { - int position = info.getPosition(); - assert position < argNames.length; - argNames[position] = info.passAsParameter() ? info.getOldName() : ""; - } - return argNames; + return myArgumentNames; } @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java index 21f352a118cd..4929f120083c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java @@ -33,7 +33,6 @@ import com.intellij.util.ui.EditableModel; import org.jetbrains.annotations.NonNls; import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; -import org.jetbrains.plugins.groovy.refactoring.extract.method.GroovyExtractMethodDialog; import javax.swing.*; import javax.swing.table.AbstractTableModel; @@ -46,11 +45,10 @@ import java.awt.event.KeyEvent; /** * @author ilyas */ -public class ParameterTablePanel extends JPanel { +public abstract class ParameterTablePanel extends JPanel { private ParameterInfo[] myParameterInfos; private TypeSelector[] myParameterTypeSelectors; - private GroovyExtractMethodDialog myDialog; private JBTable myTable; private MyTableModel myTableModel; @@ -60,16 +58,15 @@ public class ParameterTablePanel extends JPanel { super(new BorderLayout()); } - public void init(GroovyExtractMethodDialog dialog, InitialInfo helper) { + public void init(ExtractInfoHelper helper) { setBorder(IdeBorderFactory.createTitledBorder(GroovyRefactoringBundle.message("parameters.border.title"), false, false, true)); - myDialog = dialog; myParameterInfos = helper.getParameterInfos(); myTableModel = new MyTableModel(); myTable = new JBTable(myTableModel); - DefaultCellEditor defaultEditor = (DefaultCellEditor) myTable.getDefaultEditor(Object.class); + DefaultCellEditor defaultEditor = (DefaultCellEditor)myTable.getDefaultEditor(Object.class); defaultEditor.setClickCountToStart(1); myTable.setTableHeader(null); @@ -113,6 +110,7 @@ public class ParameterTablePanel extends JPanel { myTable.getColumnModel().getColumn(MyTableModel.PARAMETER_TYPE_COLUMN).setCellEditor(new AbstractTableCellEditor() { TypeSelector myCurrentSelector; + public Object getCellEditorValue() { return myCurrentSelector.getSelectedType(); } @@ -214,17 +212,11 @@ public class ParameterTablePanel extends JPanel { add(listPanel, BorderLayout.CENTER); } - protected void updateSignature(){ - myDialog.updateSignature(); - } + protected abstract void updateSignature(); - protected void doEnterAction(){ - myDialog.clickDefaultButton(); - } + protected abstract void doEnterAction(); - protected void doCancelAction(){ - myDialog.doCancelAction(); - } + protected abstract void doCancelAction(); private class MyTableModel extends AbstractTableModel implements EditableModel { public static final int CHECKMARK_COLUMN = 0; @@ -243,12 +235,16 @@ public class ParameterTablePanel extends JPanel { @Override public void exchangeRows(int oldIndex, int newIndex) { - if (oldIndex<0 || newIndex<0) return; - if (oldIndex>=myParameterInfos.length || newIndex>=myParameterInfos.length) return; + if (oldIndex < 0 || newIndex < 0) return; + if (oldIndex >= myParameterInfos.length || newIndex >= myParameterInfos.length) return; final ParameterInfo old = myParameterInfos[oldIndex]; myParameterInfos[oldIndex] = myParameterInfos[newIndex]; myParameterInfos[newIndex] = old; + + myParameterInfos[oldIndex].setPosition(oldIndex); + myParameterInfos[newIndex].setPosition(newIndex); + fireTableRowsUpdated(Math.min(oldIndex, newIndex), Math.max(oldIndex, newIndex)); updateSignature(); } @@ -281,7 +277,7 @@ public class ParameterTablePanel extends JPanel { public void setValueAt(Object aValue, int rowIndex, int columnIndex) { switch (columnIndex) { case CHECKMARK_COLUMN: { - myParameterInfos[rowIndex].setPassAsParameter((Boolean) aValue); + myParameterInfos[rowIndex].setPassAsParameter((Boolean)aValue); fireTableRowsUpdated(rowIndex, rowIndex); myTable.getSelectionModel().setSelectionInterval(rowIndex, rowIndex); updateSignature(); @@ -289,7 +285,7 @@ public class ParameterTablePanel extends JPanel { } case PARAMETER_NAME_COLUMN: { ParameterInfo info = myParameterInfos[rowIndex]; - String name = (String) aValue; + String name = (String)aValue; if (GroovyNamesUtil.isIdentifier(name)) { info.setNewName(name); } @@ -298,7 +294,7 @@ public class ParameterTablePanel extends JPanel { } case PARAMETER_TYPE_COLUMN: { ParameterInfo info = myParameterInfos[rowIndex]; - info.setType((PsiType) aValue); + info.setType((PsiType)aValue); updateSignature(); break; } @@ -312,7 +308,9 @@ public class ParameterTablePanel extends JPanel { case PARAMETER_NAME_COLUMN: return isEnabled() && myParameterInfos[rowIndex].passAsParameter(); case PARAMETER_TYPE_COLUMN: - return isEnabled() && myParameterInfos[rowIndex].passAsParameter() && !(myParameterTypeSelectors[rowIndex].getComponent() instanceof JLabel); + return isEnabled() && + myParameterInfos[rowIndex].passAsParameter() && + !(myParameterTypeSelectors[rowIndex].getComponent() instanceof JLabel); default: return false; } @@ -333,6 +331,4 @@ public class ParameterTablePanel extends JPanel { return rendererComponent; } } - - } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java index a45ab8e3542e..ed87a8dd84a5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java @@ -16,24 +16,15 @@ package org.jetbrains.plugins.groovy.refactoring.extract.method; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiModifier; -import com.intellij.psi.PsiType; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; -import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; -import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInfoHelper; +import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInfoHelperBase; import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil; import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo; -import org.jetbrains.plugins.groovy.refactoring.extract.ParameterInfo; /** * @author ilyas */ -public class ExtractMethodInfoHelper implements ExtractInfoHelper { - private final InitialInfo myInitialInfo; +public class ExtractMethodInfoHelper extends ExtractInfoHelperBase { private final boolean myIsStatic; private boolean mySpecifyType = true; @@ -41,7 +32,7 @@ public class ExtractMethodInfoHelper implements ExtractInfoHelper { private String myName; public ExtractMethodInfoHelper(InitialInfo initialInfo, String name) { - myInitialInfo = initialInfo; + super(initialInfo); myVisibility = PsiModifier.PRIVATE; myName = name; @@ -49,53 +40,6 @@ public class ExtractMethodInfoHelper implements ExtractInfoHelper { myIsStatic = ExtractUtil.canBeStatic(initialInfo.getStatements()[0]); } - @Override - @NotNull - public Project getProject() { - return myInitialInfo.getProject(); - } - - @NotNull - @Override - public ParameterInfo[] getParameterInfos() { - return myInitialInfo.getParameterInfos(); - } - - @Override - @NotNull - public VariableInfo[] getOutputNames() { - return myInitialInfo.getOutputNames(); - } - - /** - * Get old names of parameters to be pasted as method call arguments - * - * @return array of argument names - */ - @NotNull - @Override - public String[] getArgumentNames() { - return myInitialInfo.getArgumentNames(); - } - - @Override - @NotNull - public PsiType getOutputType() { - return myInitialInfo.getOutputType(); - } - - @Override - @NotNull - public PsiElement[] getInnerElements() { - return myInitialInfo.getInnerElements(); - } - - @Override - @NotNull - public GrStatement[] getStatements() { - return myInitialInfo.getStatements(); - } - public boolean isStatic() { return myIsStatic; } @@ -116,16 +60,6 @@ public class ExtractMethodInfoHelper implements ExtractInfoHelper { mySpecifyType = specifyType; } - @Override - @NotNull - public GrMemberOwner getOwner() { - return myInitialInfo.getOwner(); - } - - public boolean hasReturnValue() { - return myInitialInfo.hasReturnValue(); - } - public String getName() { return myName; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java index 1d4d07acc645..60343f373f22 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java @@ -16,7 +16,6 @@ package org.jetbrains.plugins.groovy.refactoring.extract.method; -import com.intellij.ide.highlighter.JavaFileType; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.help.HelpManager; @@ -36,6 +35,7 @@ import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil; import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil; import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo; import org.jetbrains.plugins.groovy.refactoring.extract.ParameterTablePanel; +import org.jetbrains.plugins.groovy.refactoring.ui.GrMethodSignatureComponent; import org.jetbrains.plugins.groovy.refactoring.ui.GroovyComboboxVisibilityPanel; import org.jetbrains.plugins.groovy.settings.GroovyApplicationSettings; @@ -73,7 +73,7 @@ public class GroovyExtractMethodDialog extends DialogWrapper { myHelper = new ExtractMethodInfoHelper(info, ""); setUpNameField(); - myParameterTablePanel.init(this, info); + myParameterTablePanel.init(myHelper); setModal(true); setTitle(GroovyExtractMethodHandler.REFACTORING_NAME); @@ -181,12 +181,7 @@ public class GroovyExtractMethodDialog extends DialogWrapper { } private void createUIComponents() { - mySignature = new MethodSignatureComponent("", myProject, JavaFileType.INSTANCE) { - @Override - protected String getFileName() { - return "dummy." + GroovyFileType.GROOVY_FILE_TYPE.getDefaultExtension(); - } - }; + mySignature = new GrMethodSignatureComponent("", myProject); mySignature.setPreferredSize(new Dimension(500, 100)); mySignature.setMinimumSize(new Dimension(500, 100)); @@ -206,7 +201,19 @@ public class GroovyExtractMethodDialog extends DialogWrapper { } }); - myParameterTablePanel = new ParameterTablePanel(); + myParameterTablePanel = new ParameterTablePanel() { + protected void updateSignature(){ + GroovyExtractMethodDialog.this.updateSignature(); + } + + protected void doEnterAction(){ + GroovyExtractMethodDialog.this.clickDefaultButton(); + } + + protected void doCancelAction(){ + GroovyExtractMethodDialog.this.doCancelAction(); + } + }; } class DataChangedListener implements EventListener { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrMethodSignatureComponent.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrMethodSignatureComponent.java new file mode 100644 index 000000000000..a196e063bec5 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrMethodSignatureComponent.java @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2012 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 org.jetbrains.plugins.groovy.refactoring.ui; + +import com.intellij.openapi.project.Project; +import com.intellij.refactoring.ui.MethodSignatureComponent; +import org.jetbrains.plugins.groovy.GroovyFileType; + +/** + * @author Max Medvedev + */ +public class GrMethodSignatureComponent extends MethodSignatureComponent { + private final String myFileName; + + public GrMethodSignatureComponent(String signature, Project project) { + super(signature, project, GroovyFileType.GROOVY_FILE_TYPE); + myFileName = "dummy." + GroovyFileType.GROOVY_FILE_TYPE.getDefaultExtension(); + } + + @Override + protected String getFileName() { + return myFileName; + } +} From 387377d8f802b34796ce006a00041a62fdfb1e92 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 18 Jan 2012 12:04:44 +0400 Subject: [PATCH 5/7] test fix --- .../MagicConstantInspection.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java index 844abfd2765b..9d4840cf53fd 100644 --- a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java @@ -163,16 +163,18 @@ public class MagicConstantInspection extends LocalInspectionTool { if (module == null) { return; } - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - attachJdkAnnotations(module); - } - }); - } - }, ModalityState.NON_MODAL, module.getDisposed()); + if (!ApplicationManager.getApplication().isUnitTestMode()) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + attachJdkAnnotations(module); + } + }); + } + }, ModalityState.NON_MODAL, module.getDisposed()); + } } private static void attachJdkAnnotations(Module module) { From 9e44a3d68c795cc4179f12a5595be3bde0594630 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Wed, 18 Jan 2012 12:17:39 +0400 Subject: [PATCH 6/7] add trove4j as in bat/sh to fix launching --- build/conf/mac/Contents/Info.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/conf/mac/Contents/Info.plist b/build/conf/mac/Contents/Info.plist index aae772e03237..242d418c7b4c 100644 --- a/build/conf/mac/Contents/Info.plist +++ b/build/conf/mac/Contents/Info.plist @@ -58,7 +58,7 @@ Java ClassPath - $APP_PACKAGE/lib/bootstrap.jar:$APP_PACKAGE/lib/extensions.jar:$APP_PACKAGE/lib/util.jar:$APP_PACKAGE/lib/jdom.jar:$APP_PACKAGE/lib/log4j.jar:$APP_PACKAGE/lib/jna.jar + $APP_PACKAGE/lib/bootstrap.jar:$APP_PACKAGE/lib/extensions.jar:$APP_PACKAGE/lib/util.jar:$APP_PACKAGE/lib/jdom.jar:$APP_PACKAGE/lib/log4j.jar:$APP_PACKAGE/lib/jna.jar:$APP_PACKAGE/lib/trove4j.jar JVMVersion 1.6* From 7558201d0d33ff0a4eacfbce5b153720a4c38441 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 18 Jan 2012 09:23:43 +0100 Subject: [PATCH 7/7] new pipette and synchronization fixes --- .../src/com/intellij/ui/ColorPicker.java | 128 +++++++++++++----- 1 file changed, 92 insertions(+), 36 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/ColorPicker.java b/platform/platform-api/src/com/intellij/ui/ColorPicker.java index e19923d2ec3a..3d712f3b3819 100644 --- a/platform/platform-api/src/com/intellij/ui/ColorPicker.java +++ b/platform/platform-api/src/com/intellij/ui/ColorPicker.java @@ -20,6 +20,7 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.WindowManager; import com.intellij.util.Alarm; @@ -62,6 +63,7 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen private final Alarm myUpdateQueue; private RecentColorsComponent myRecentColorsComponent; + private final ColorPipette myPicker; private ColorPicker(@NotNull Disposable parent, @Nullable Color color, boolean enableOpacity) { this(parent, color, true, enableOpacity); @@ -77,9 +79,15 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5)); myColorWheelPanel = new ColorWheelPanel(this, enableOpacity); - + myPicker = new ColorPipette(this, getColor()); + myPicker.setListener(new ColorListener() { + @Override + public void colorChanged(Color color, Object source) { + setColor(color, source); + } + }); try { - add(buildTopPanel(restoreColors), BorderLayout.NORTH); + add(buildTopPanel(true), BorderLayout.NORTH); add(myColorWheelPanel, BorderLayout.CENTER); myRecentColorsComponent = new RecentColorsComponent(new ColorListener() { @@ -166,7 +174,8 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen private void validateAndUpdatePreview(JTextField src) { final Color color; if (myHex.hasFocus()) { - color = ColorUtil.fromHex(myHex.getText(), null); + Color c = ColorUtil.fromHex(myHex.getText(), null); + color = c != null ? new Color(c.getRed(), c.getGreen(), c.getBlue(), (int)(255 * myColorWheelPanel.myColorWheel.myOpacity)) : null; } else { color = gatherRGB(); } @@ -245,12 +254,12 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen pipette.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - ColorPipette.pickColor(new ColorListener() { - @Override - public void colorChanged(Color color, Object source) { - setColor(color, source); - } - }, ColorPicker.this); + myPicker.myOldColor = getColor(); + myPicker.pick(); + //JBPopupFactory.getInstance().createBalloonBuilder(new JLabel("Press ESC button to close pipette")) + // .setAnimationCycle(2000) + // .setSmallVariant(true) + // .createBalloon().show(new RelativePoint(pipette, new Point(pipette.getWidth() / 2, 0)), Balloon.Position.above); } }); previewPanel.add(pipette, BorderLayout.WEST); @@ -939,6 +948,7 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen private final Color myPreselectedColor; private ColorPicker myColorPicker; private final boolean myEnableOpacity; + private ColorPipette myPicker; public ColorPickerDialog(Component parent, String caption, Color preselectedColor, boolean enableOpacity) { super(parent, true); @@ -948,6 +958,18 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen setResizable(false); setOKButtonText("Choose"); init(); + addMouseListener((MouseMotionListener)new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + myPicker.cancelPipette(); + } + + @Override + public void mouseExited(MouseEvent e) { + myPicker.pick(); + } + }); + } @Override @@ -1058,6 +1080,7 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen private static class ColorPipette implements ImageObserver { private Dialog myPickerFrame; private final JComponent myParent; + private Color myOldColor; private Timer myTimer; private Point myPoint = new Point(); @@ -1074,11 +1097,13 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen private Color myTransparentColor = new Color(0, true); private Rectangle myZoomRect; private Rectangle myGlassRect; - private ColorListener myDoWhenDone; + private ColorListener myColorListener; private BufferedImage myMaskImage; + private Alarm myColorListenersNotifier = new Alarm(Alarm.ThreadToUse.SWING_THREAD); - private ColorPipette(JComponent parent) { + private ColorPipette(JComponent parent, Color oldColor) { myParent = parent; + myOldColor = oldColor; try { myRobot = new Robot(); @@ -1088,14 +1113,16 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen } } - public void pick(ColorListener doWhenDone) { - myDoWhenDone = doWhenDone; - getPicker(); - myTimer.start(); + public void setListener(ColorListener colorListener) { + myColorListener = colorListener; + } + + public void pick() { Dialog picker = getPicker(); picker.setVisible(true); + myTimer.start(); // it seems like it's the lowest value for opacity for mouse events to be processed correctly - WindowManager.getInstance().setAlphaModeRatio(picker, 0.99f); + WindowManager.getInstance().setAlphaModeRatio(picker, SystemInfo.isMac ? 0.95f : 0.99f); } @Override @@ -1148,18 +1175,18 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen } }); - myPickerFrame.setSize(100, 100); + myPickerFrame.setSize(50, 50); myPickerFrame.setUndecorated(true); myPickerFrame.setAlwaysOnTop(true); JRootPane rootPane = ((JDialog)myPickerFrame).getRootPane(); rootPane.putClientProperty("Window.shadow", Boolean.FALSE); - myGlassRect = new Rectangle(2, 2, 28, 28); + myGlassRect = new Rectangle(0, 0, 32, 32); myPickOffset = new Point(0, 0); myCaptureRect = new Rectangle(-4, -4, 8, 8); myCaptureOffset = new Point(myCaptureRect.x, myCaptureRect.y); - myHotspot = new Point(16, 16); + myHotspot = new Point(14, 16); myZoomRect = new Rectangle(0, 0, 32, 32); @@ -1170,7 +1197,7 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen maskG.setColor(Color.RED); maskG.setComposite(AlphaComposite.SrcOut); - maskG.fillOval(myGlassRect.x, myGlassRect.y, myGlassRect.width, myGlassRect.height); + maskG.fillRect(0, 0, 32, 32); maskG.dispose(); myMagnifierImage = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB); @@ -1181,14 +1208,15 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); graphics.setColor(Color.BLACK); - graphics.drawOval(1, 1, 30, 30); - graphics.drawOval(2, 2, 28, 28); - - graphics.drawLine(2, 16, 12, 16); - graphics.drawLine(20, 16, 30, 16); - - graphics.drawLine(16, 2, 16, 12); - graphics.drawLine(16, 20, 16, 30); + //graphics.drawOval(1, 1, 30, 30); + //graphics.drawOval(2, 2, 28, 28); + // + //graphics.drawLine(2, 16, 12, 16); + //graphics.drawLine(20, 16, 30, 16); + // + //graphics.drawLine(16, 2, 16, 12); + //graphics.drawLine(16, 20, 16, 30); + PICK.paintIcon(null, graphics, 14, 0); graphics.dispose(); @@ -1225,15 +1253,19 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen private void cancelPipette() { myTimer.stop(); myPickerFrame.setVisible(false); + if (myColorListener != null && myOldColor != null) { + myColorListener.colorChanged(myOldColor, this); + } } - private void pickDone() { + public void pickDone() { cancelPipette(); PointerInfo pointerInfo = MouseInfo.getPointerInfo(); Point location = pointerInfo.getLocation(); Color pixelColor = myRobot.getPixelColor(location.x + myPickOffset.x, location.y + myPickOffset.y); - if (myDoWhenDone != null) { - myDoWhenDone.colorChanged(pixelColor, this); + if (myColorListener != null) { + myColorListener.colorChanged(pixelColor, this); + myOldColor = pixelColor; } } @@ -1246,11 +1278,12 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen myPoint.x = mouseLoc.x + myPickOffset.x; myPoint.y = mouseLoc.y + myPickOffset.y; - Color c = myRobot.getPixelColor(myPoint.x, myPoint.y); + final Color c = myRobot.getPixelColor(myPoint.x, myPoint.y); if (!c.equals(myPreviousColor) || !mouseLoc.equals(myPreviousLocation)) { myPreviousColor = c; myPreviousLocation = mouseLoc; - myCaptureRect.setLocation(mouseLoc.x + myCaptureOffset.x, mouseLoc.y + myCaptureOffset.y); + myCaptureRect.setLocation(mouseLoc.x - 2/*+ myCaptureOffset.x*/, mouseLoc.y - 2/*+ myCaptureOffset.y*/); + myCaptureRect.setBounds(mouseLoc.x -2, mouseLoc.y -2, 5, 5); BufferedImage capture = myRobot.createScreenCapture(myCaptureRect); @@ -1273,13 +1306,27 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen // the color picker uses the new imagery. //BufferedImage subImage = myImage.getSubimage(0, 0, myImage.getWidth(), myImage.getHeight()); myPickerFrame.setCursor(myParent.getToolkit().createCustomCursor(myImage, myHotspot, "ColorPicker")); + if (myColorListener != null) { + myColorListenersNotifier.cancelAllRequests(); + myColorListenersNotifier.addRequest(new Runnable() { + @Override + public void run() { + myColorListener.colorChanged(c, ColorPipette.this); + } + }, 300); + } } } } - public static void pickColor(ColorListener doWhenDone, JComponent c) { - new ColorPipette(c).pick(doWhenDone); - } + //public static void pickColor(ColorListener listener, JComponent c) { + // new ColorPipette(c, new ColorListener() { + // @Override + // public void colorChanged(Color color, Object source) { + // ColorPicker.this.setColor(color, my); + // } + // }).pick(listener); + //} public static boolean isAvailable() { try { @@ -1292,6 +1339,15 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen } } } + + public static void main(String[] args) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + ColorPicker.showDialog(null, "", null, true); + } + }); + } } interface ColorListener { void colorChanged(Color color, Object source);