Merge remote branch 'origin/master'

This commit is contained in:
irengrig
2012-01-18 13:03:29 +04:00
27 changed files with 1261 additions and 1031 deletions
+1 -1
View File
@@ -58,7 +58,7 @@
<key>Java</key>
<dict>
<key>ClassPath</key>
<string>$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</string>
<string>$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</string>
<key>JVMVersion</key>
<string>1.6*</string>
@@ -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) {
@@ -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);
@@ -165,3 +165,4 @@ change.usages.of.var=Change usages of variable ''{0}''?
reference.to.accessor.0.is.used=Reference to accessor <bold>{0}<bold> 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
@@ -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;
@@ -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";
}
@@ -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);
}
}
@@ -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<InfoHelper extends ExtractInfoHelper> 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<GrStatement> allReturnStatements = new HashSet<GrStatement>();
GrControlFlowOwner controlFlowOwner = ControlFlowUtils.findControlFlowOwner(statement0);
assert controlFlowOwner != null;
allReturnStatements.addAll(ControlFlowUtils.collectReturns(controlFlowOwner, true));
ArrayList<GrStatement> returnStatements = new ArrayList<GrStatement>();
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<GrStatement> returnStatementsCopy = new ArrayList<GrStatement>(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);
}
InitialInfo info = new InitialInfo(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 InitialInfo initialInfo);
public abstract void performRefactoring(@NotNull final InfoHelper helper,
@NotNull final GrMemberOwner owner,
final GrStatementOwner declarationOwner,
final Editor editor,
final PsiElement startElement);
}
@@ -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();
}
@@ -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<String, ParameterInfo> myInputNamesMap;
public ExtractInfoHelperBase(
InitialInfo initialInfo) {
myInitialInfo = initialInfo;
final ParameterInfo[] infos = initialInfo.getParameterInfos();
myInputNamesMap = new HashMap<String, ParameterInfo>(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<ParameterInfo> 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<ParameterInfo> 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();
}
}
@@ -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,16 +95,16 @@ 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();
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())};
}
@@ -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<GrStatement> 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<String> conflicts = new ArrayList<String>();
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
@@ -302,7 +302,7 @@ public class ExtractMethodUtil {
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 ExtractMethodUtil {
return method;
}
static String[] getParameterString(ExtractMethodInfoHelper helper) {
public static String[] getParameterString(ExtractInfoHelper helper, boolean useCanonicalText) {
int i = 0;
ParameterInfo[] infos = helper.getParameterInfos();
int number = 0;
@@ -377,7 +377,14 @@ public class ExtractMethodUtil {
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++;
}
@@ -385,12 +392,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 +412,7 @@ public class ExtractMethodUtil {
return typeText;
}
static GrStatement[] getStatementsByElements(PsiElement[] elements) {
public static GrStatement[] getStatementsByElements(PsiElement[] elements) {
ArrayList<GrStatement> statementList = new ArrayList<GrStatement>();
for (PsiElement element : elements) {
if (element instanceof GrStatement) {
@@ -415,7 +422,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 +439,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 +449,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 +486,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 +505,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 +516,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<GrStatement> returnStatements) {
public static boolean isReturnStatement(GrStatement statement, Collection<GrStatement> returnStatements) {
if (statement instanceof GrReturnStatement) return true;
if (statement instanceof GrIfStatement) {
boolean checked = GroovyInlineMethodUtil.checkTailIfStatement(((GrIfStatement) statement), returnStatements);
@@ -0,0 +1,182 @@
/*
* 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.ArrayList;
import java.util.List;
/**
* @author Max Medvedev
*/
public class InitialInfo implements ExtractInfoHelper {
private final ParameterInfo[] myParameterInfos;
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;
private String[] myArgumentNames;
public InitialInfo(VariableInfo[] inputInfos,
VariableInfo[] outputInfos,
PsiElement[] innerElements,
GrStatement[] statements,
GrMemberOwner targetClass,
ArrayList<GrStatement> returnStatements) {
myInnerElements = innerElements;
myStatements = statements;
myTargetClass = targetClass;
myOutputNames = outputInfos;
myHasReturnValue = ContainerUtil.find(returnStatements, new Condition<GrStatement>() {
@Override
public boolean value(GrStatement statement) {
return statement instanceof GrReturnStatement && ((GrReturnStatement)statement).getReturnValue() != null;
}
}) != null;
assert myStatements.length > 0;
myProject = myStatements[0].getProject();
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();
myParameterInfos[i] = new ParameterInfo(info.getName(), i, type);
myArgumentNames[i] = info.getName();
}
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<GrStatement> 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<PsiType> types = new ArrayList<PsiType>(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() {
return myParameterInfos;
}
@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() {
return myArgumentNames;
}
@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;
}
}
@@ -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;
@@ -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;
@@ -24,56 +25,48 @@ 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.Table;
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 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;
/**
* @author ilyas
*/
public class ParameterTablePanel extends JPanel {
public abstract 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;
private JComboBox myTypeRendererCombo;
public ParameterTablePanel() {
super(new BorderLayout());
}
void init(GroovyExtractMethodDialog dialog, ExtractMethodInfoHelper helper) {
public void init(ExtractInfoHelper 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);
DefaultCellEditor defaultEditor = (DefaultCellEditor) myTable.getDefaultEditor(Object.class);
myTable = new JBTable(myTableModel);
DefaultCellEditor defaultEditor = (DefaultCellEditor)myTable.getDefaultEditor(Object.class);
defaultEditor.setClickCountToStart(1);
myTable.setTableHeader(null);
@@ -89,14 +82,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,21 +98,19 @@ 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<ParameterInfo>(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;
}
});
myTable.getColumnModel().getColumn(MyTableModel.PARAMETER_TYPE_COLUMN).setCellEditor(new AbstractTableCellEditor() {
TypeSelector myCurrentSelector;
public Object getCellEditorValue() {
return myCurrentSelector.getSelectedType();
}
@@ -216,143 +208,47 @@ 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);
}
}
protected abstract void updateSignature();
public void setEnabled(boolean enabled) {
myTable.setEnabled(enabled);
if (!enabled) {
myUpButton.setEnabled(false);
myDownButton.setEnabled(false);
}
else {
updateMoveButtons();
}
super.setEnabled(enabled);
}
protected abstract void doEnterAction();
protected abstract void doCancelAction();
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(){
myDialog.updateSignature();
}
protected void doEnterAction(){
myDialog.clickDefaultButton();
}
protected void doCancelAction(){
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;
myParameterInfos[oldIndex].setPosition(oldIndex);
myParameterInfos[newIndex].setPosition(newIndex);
fireTableRowsUpdated(Math.min(oldIndex, newIndex), Math.max(oldIndex, newIndex));
updateSignature();
}
public int getRowCount() {
return myParameterInfos.length;
}
@@ -381,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();
@@ -389,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);
}
@@ -398,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;
}
@@ -412,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;
}
@@ -433,6 +331,4 @@ public class ParameterTablePanel extends JPanel {
return rendererComponent;
}
}
}
@@ -0,0 +1,70 @@
/*
* 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.method;
import com.intellij.psi.PsiModifier;
import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInfoHelperBase;
import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil;
import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo;
/**
* @author ilyas
*/
public class ExtractMethodInfoHelper extends ExtractInfoHelperBase {
private final boolean myIsStatic;
private boolean mySpecifyType = true;
private String myVisibility;
private String myName;
public ExtractMethodInfoHelper(InitialInfo initialInfo, String name) {
super(initialInfo);
myVisibility = PsiModifier.PRIVATE;
myName = name;
myIsStatic = ExtractUtil.canBeStatic(initialInfo.getStatements()[0]);
}
public boolean isStatic() {
return myIsStatic;
}
public String getVisibility() {
return myVisibility;
}
public void setVisibility(String visibility) {
myVisibility = visibility;
}
public boolean specifyType() {
return mySpecifyType;
}
public void setSpecifyType(boolean specifyType) {
mySpecifyType = specifyType;
}
public String getName() {
return myName;
}
public void setName(String name) {
myName = name;
}
}
@@ -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;
@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.refactoring.extract.method.GroovyExtractMethodDialog">
<grid id="cbd77" binding="contentPane" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="48" y="54" width="555" height="380"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="181d3" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<clientProperties>
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithoutIndent"/>
</clientProperties>
<border type="etched" title-resource-bundle="org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle" title-key="signature.preview.border.title"/>
<children>
<component id="703ba" class="com.intellij.refactoring.ui.MethodSignatureComponent" binding="mySignature" custom-create="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
<preferred-size width="150" height="50"/>
</grid>
</constraints>
<properties/>
</component>
</children>
</grid>
<grid id="de338" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="17c7e" class="org.jetbrains.plugins.groovy.refactoring.extract.ParameterTablePanel" binding="myParameterTablePanel" custom-create="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
</children>
</grid>
<component id="26cfa" class="javax.swing.JCheckBox" binding="myCbSpecifyType">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle" key="specify.type.label"/>
</properties>
</component>
<grid id="520a9" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="7fe31" class="com.intellij.refactoring.ui.ComboBoxVisibilityPanel" binding="myVisibilityPanel" custom-create="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<grid id="17284" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="375ee" class="javax.swing.JLabel" binding="myNameLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle" key="name.label"/>
</properties>
</component>
<hspacer id="22e2d">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
<component id="588be" class="com.intellij.ui.EditorTextField" binding="myNameField" custom-create="true">
<constraints>
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
</children>
</grid>
</children>
</grid>
</children>
</grid>
</form>
@@ -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;
@@ -23,6 +23,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,12 +32,18 @@ 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.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;
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;
@@ -46,29 +54,28 @@ import java.util.EventListener;
* @author ilyas
*/
public class GroovyExtractMethodDialog extends DialogWrapper {
private final ExtractMethodInfoHelper myHelper;
private final Project myProject;
private final EventListenerList myListenerList = new EventListenerList();
private JPanel contentPane;
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 JButton buttonOK;
private final Project myProject;
public GroovyExtractMethodDialog(InitialInfo info) {
super(info.getProject(), true);
myProject = info.getProject();
myHelper = new ExtractMethodInfoHelper(info, "");
public GroovyExtractMethodDialog(ExtractMethodInfoHelper helper, Project project) {
super(project, true);
myProject = project;
myHelper = helper;
setUpNameField();
myParameterTablePanel.init(this, myHelper);
myParameterTablePanel.init(myHelper);
setModal(true);
// getRootPane().setDefaultButton(buttonOK);
setTitle(GroovyExtractMethodHandler.REFACTORING_NAME);
init();
setUpDialog();
@@ -78,8 +85,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()) {
@@ -92,9 +99,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);
}
@@ -146,6 +152,7 @@ public class GroovyExtractMethodDialog extends DialogWrapper {
private void update() {
String text = getEnteredName();
myHelper.setName(text);
updateSignature();
setOKActionEnabled(GroovyNamesUtil.isIdentifier(text));
}
@@ -155,7 +162,8 @@ public class GroovyExtractMethodDialog extends DialogWrapper {
String text = myNameField.getText();
if (text != null && text.trim().length() > 0) {
return text.trim();
} else {
}
else {
return null;
}
}
@@ -173,22 +181,39 @@ public class GroovyExtractMethodDialog extends DialogWrapper {
}
private void createUIComponents() {
mySignature = new GrMethodSignatureComponent("", myProject);
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();
}
});
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 {
@@ -201,7 +226,7 @@ public class GroovyExtractMethodDialog extends DialogWrapper {
Object[] list = myListenerList.getListenerList();
for (Object aList : list) {
if (aList instanceof DataChangedListener) {
((DataChangedListener) aList).dataChanged();
((DataChangedListener)aList).dataChanged();
}
}
}
@@ -209,16 +234,16 @@ public class GroovyExtractMethodDialog extends DialogWrapper {
/*
Update signature text area
*/
void updateSignature() {
if (mySignatureArea == null) return;
public void updateSignature() {
if (mySignature == 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, false);
if (params.length > 0) {
String INDENT = " ";
buffer.append("\n");
@@ -227,10 +252,10 @@ public class GroovyExtractMethodDialog extends DialogWrapper {
}
}
buffer.append(")");
mySignatureArea.setText(buffer.toString());
mySignature.setSignature(buffer.toString());
}
ExtractMethodSettings getSettings() {
public ExtractMethodSettings getSettings() {
return new MyExtractMethodSettings(this);
}
@@ -244,12 +269,12 @@ public class GroovyExtractMethodDialog extends DialogWrapper {
}
@NotNull
public ExtractMethodInfoHelper getHelper() {
return myHelper;
}
public ExtractMethodInfoHelper getHelper() {
return myHelper;
}
public String getEnteredName() {
return myEnteredName;
}
return myEnteredName;
}
}
}
@@ -0,0 +1,169 @@
/*
* 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.method;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
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.api.statements.GrStatement;
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.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.ExtractUtil;
import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo;
/**
* @author ilyas
*/
public class GroovyExtractMethodHandler extends ExtractHandlerBase<ExtractMethodInfoHelper> 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";
public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) {
invoke(project, editor, file);
}
void invoke(Project project, Editor editor, PsiFile file) {
editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
// select editor text fragment
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();
}
}
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() {
try {
PsiElement anchor = ExtractUtil.calculateAnchorToInsertBefore(owner, startElement);
GrMethod newMethod = owner.addMemberDeclaration(method, anchor);
ExtractUtil.renameParameterOccurrences(newMethod, helper);
GrReferenceAdjuster.shortenReferences(newMethod);
GrStatement realStatement;
if (declarationOwner != null && !ExtractUtil.isSingleExpression(helper.getStatements())) {
// Replace set of statements
final GrStatement[] newStatement = ExtractUtil.createResultStatement(helper, methodName);
// add call statement
final GrStatement[] statements = helper.getStatements();
assert statements.length > 0;
realStatement = null;
for (GrStatement statement : newStatement) {
realStatement = declarationOwner.addStatementBefore(statement, statements[0]);
}
assert realStatement != null;
// remove old statements
ExtractUtil.removeOldStatements(declarationOwner, helper);
PsiImplUtil.removeNewLineAfter(realStatement);
}
else {
// Expression call replace
GrExpression methodCall = ExtractUtil.createMethodCallByHelper(methodName, helper);
GrExpression oldExpr = (GrExpression)helper.getStatements()[0];
realStatement = oldExpr.replaceWithExpression(methodCall, true);
}
GrReferenceAdjuster.shortenReferences(realStatement);
PsiElement prev = newMethod.getPrevSibling();
IElementType elementType = prev.getNode().getElementType();
if (!TokenSets.WHITE_SPACES_SET.contains(elementType) || !prev.getText().contains("\n")) {
newMethod.getParent().getNode().addLeaf(GroovyTokenTypes.mNLS, "\n", newMethod.getNode());
}
// move to offset
if (editor != null) {
PsiDocumentManager.getInstance(helper.getProject()).commitDocument(editor.getDocument());
editor.getCaretModel().moveToOffset(ExtractUtil.getCaretOffset(realStatement));
}
}
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);
}
@Override
public ExtractMethodInfoHelper getSettings(@NotNull InitialInfo 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();
if (!dialog.isOK()) return null;
return dialog.getHelper();
}
public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
// does nothing
}
public String getInvokeResult() {
return myInvokeResult;
}
}
@@ -1,197 +0,0 @@
/*
* Copyright 2000-2009 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.extractMethod;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.*;
import com.intellij.util.containers.ContainerUtil;
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 java.util.*;
/**
* @author ilyas
*/
public class ExtractMethodInfoHelper {
private final Map<String, ParameterInfo> myInputNamesMap = new HashMap<String, ParameterInfo>();
private final VariableInfo[] myOutputNames;
private final PsiType myOutputType;
private final GrMemberOwner myTargetClass;
private final boolean myIsStatic;
private final boolean myIsReturnStatement;
private boolean mySpecifyType;
private final PsiElement[] myInnerElements;
private String myVisibility;
private final Project myProject;
private final GrStatement[] myStatements;
public ExtractMethodInfoHelper(VariableInfo[] inputInfos,
VariableInfo[] outputInfos,
PsiElement[] innerElements,
GrStatement[] statements,
GrMemberOwner targetClass,
boolean isStatic,
ArrayList<GrStatement> returnStatements) {
myInnerElements = innerElements;
myStatements = statements;
myTargetClass = targetClass;
myIsStatic = isStatic;
myIsReturnStatement = ContainerUtil.find(returnStatements, new Condition<GrStatement>() {
@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++;
}
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 (ExtractMethodUtil.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<PsiType> types = new ArrayList<PsiType>(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;
mySpecifyType = !(PsiType.VOID.equals(outputType) || myOutputType.equalsToText("java.lang.Object"));
}
@NotNull
public Project getProject() {
return myProject;
}
public ParameterInfo[] getParameterInfos() {
Collection<ParameterInfo> 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;
}
@NotNull
public VariableInfo[] getOutputNames() {
return myOutputNames;
}
/**
* Get old names of parameters to be pasted as method call arguments
*
* @return array of argument names
*/
public String[] getArgumentNames() {
Collection<ParameterInfo> 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;
}
@NotNull
public PsiType getOutputType() {
return myOutputType;
}
@NotNull
public PsiElement[] getInnerElements() {
return myInnerElements;
}
@NotNull
public GrStatement[] getStatements() {
return myStatements;
}
public boolean isStatic() {
return myIsStatic;
}
public String getVisibility() {
return myVisibility;
}
public void setVisibility(String visibility) {
myVisibility = visibility;
}
public boolean specifyType() {
return mySpecifyType;
}
public void setSpecifyType(boolean specifyType) {
mySpecifyType = specifyType;
}
@NotNull
public GrMemberOwner getOwner() {
return myTargetClass;
}
public boolean isReturnStatement() {
return myIsReturnStatement;
}
}
@@ -1,99 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.refactoring.extractMethod.GroovyExtractMethodDialog">
<grid id="cbd77" binding="contentPane" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="48" y="54" width="555" height="380"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="5afec" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<clientProperties>
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithoutIndent"/>
</clientProperties>
<border type="etched" title-resource-bundle="org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle" title-key="method.border.title">
<color color="-16777216"/>
</border>
<children>
<component id="76fe4" class="com.intellij.ui.EditorTextField" binding="myNameField" custom-create="true">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="94f13" class="javax.swing.JLabel" binding="myNameLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle" key="name.label"/>
</properties>
</component>
<component id="cd87f" class="javax.swing.JCheckBox" binding="myCbSpecifyType">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle" key="specify.type.label"/>
</properties>
</component>
</children>
</grid>
<grid id="181d3" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<clientProperties>
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithoutIndent"/>
</clientProperties>
<border type="etched" title-resource-bundle="org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle" title-key="signature.preview.border.title"/>
<children>
<component id="703ba" class="javax.swing.JTextArea" binding="mySignatureArea">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
<preferred-size width="150" height="50"/>
</grid>
</constraints>
<properties>
<background color="-1119000"/>
<editable value="false"/>
<text value=""/>
</properties>
</component>
</children>
</grid>
<grid id="de338" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="3b207" class="org.jetbrains.plugins.groovy.refactoring.extractMethod.VisibilityPanel" binding="myVisibilityPanel" custom-create="true">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="17c7e" class="org.jetbrains.plugins.groovy.refactoring.extractMethod.ParameterTablePanel" binding="myParameterTablePanel" custom-create="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
</children>
</grid>
</children>
</grid>
</form>
@@ -1,319 +0,0 @@
/*
* Copyright 2000-2011 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.extractMethod;
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;
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.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 java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* @author ilyas
*/
public class GroovyExtractMethodHandler implements RefactoringActionHandler {
private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.refactoring.extractMethod.GroovyExtractMethodHandler");
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) {
editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
// select editor text fragment
if (!editor.getSelectionModel().hasSelection()) {
editor.getSelectionModel().selectLineAtCaret();
}
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 = ExtractMethodUtil.getElementsInOffset(file, startOffset, endOffset);
if (elements.length == 1 && elements[0] instanceof GrExpression) {
selectionModel.setSelection(startOffset, elements[0].getTextRange().getEndOffset());
}
GrStatement[] statements = ExtractMethodUtil.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 = ExtractMethodUtil.getMemberOwner(statement0);
GrStatementOwner declarationOwner = ExtractMethodUtil.getDeclarationOwner(statement0);
if (owner == null ||
(declarationOwner == null && !ExtractMethodUtil.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())) {
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<GrStatement> allReturnStatements = new HashSet<GrStatement>();
GrControlFlowOwner controlFlowOwner = ControlFlowUtils.findControlFlowOwner(statement0);
assert controlFlowOwner != null;
allReturnStatements.addAll(ControlFlowUtils.collectReturns(controlFlowOwner, true));
ArrayList<GrStatement> returnStatements = new ArrayList<GrStatement>();
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 ||*/
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) {
if (hasInterruptingStatements =
GroovyRefactoringUtil.hasWrongBreakStatements(statement) ||
GroovyRefactoringUtil.haswrongContinueStatements(statement)) {
break;
}
}
// must be replaced by return statement
boolean hasReturns = returnStatements.size() > 0;
List<GrStatement> returnStatementsCopy = new ArrayList<GrStatement>(returnStatements.size());
returnStatementsCopy.addAll(returnStatements);
boolean isReturnStatement = ExtractMethodUtil.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 = ExtractMethodUtil.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) {
final GrMethod method = ExtractMethodUtil.createMethodByHelper(methodName, helper);
final Runnable runnable = new Runnable() {
public void run() {
try {
PsiElement anchor = ExtractMethodUtil.calculateAnchorToInsertBefore(owner, startElement);
GrMethod newMethod = owner.addMemberDeclaration(method, anchor);
ExtractMethodUtil.renameParameterOccurrences(newMethod, helper);
GrReferenceAdjuster.shortenReferences(newMethod);
GrStatement realStatement;
if (declarationOwner != null && !ExtractMethodUtil.isSingleExpression(helper.getStatements())) {
// Replace set of statements
final GrStatement[] newStatement = ExtractMethodUtil.createResultStatement(helper, methodName);
// add call statement
final GrStatement[] statements = helper.getStatements();
assert statements.length > 0;
realStatement = null;
for (GrStatement statement : newStatement) {
realStatement = declarationOwner.addStatementBefore(statement, statements[0]);
}
assert realStatement != null;
// remove old statements
ExtractMethodUtil.removeOldStatements(declarationOwner, helper);
PsiImplUtil.removeNewLineAfter(realStatement);
} else {
// Expression call replace
GrExpression methodCall = ExtractMethodUtil.createMethodCallByHelper(methodName, helper);
GrExpression oldExpr = (GrExpression) helper.getStatements()[0];
realStatement = oldExpr.replaceWithExpression(methodCall, true);
}
GrReferenceAdjuster.shortenReferences(realStatement);
PsiElement prev = newMethod.getPrevSibling();
IElementType elementType = prev.getNode().getElementType();
if (!TokenSets.WHITE_SPACES_SET.contains(elementType) || !prev.getText().contains("\n")) {
newMethod.getParent().getNode().addLeaf(GroovyTokenTypes.mNLS, "\n", newMethod.getNode());
}
// move to offset
if (editor != null) {
PsiDocumentManager.getInstance(helper.getProject()).commitDocument(editor.getDocument());
editor.getCaretModel().moveToOffset(ExtractMethodUtil.getCaretOffset(realStatement));
}
} 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);
}
private static GroovyExtractMethodDialog getDialog(@NotNull final ExtractMethodInfoHelper helper) {
GroovyExtractMethodDialog dialog = new GroovyExtractMethodDialog(helper, helper.getProject());
dialog.show();
return dialog;
}
public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
// does nothing
}
public String getInvokeResult() {
return myInvokeResult;
}
}
@@ -1,128 +0,0 @@
/*
* Copyright 2000-2009 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.extractMethod;
import com.intellij.psi.PsiModifier;
import com.intellij.ui.IdeBorderFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
import javax.swing.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.util.EventListener;
/**
* @author ilyas
*/
public class VisibilityPanel extends JPanel {
private final JRadioButton myRbPrivate;
private final JRadioButton myRbProtected;
private final JRadioButton myRbPublic;
public VisibilityPanel() {
setBorder(IdeBorderFactory.createTitledBorder(GroovyRefactoringBundle.message("visibility.border.title"), false, true, true));
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
ButtonGroup bg = new ButtonGroup();
ItemListener listener = new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if(e.getStateChange() == ItemEvent.SELECTED) {
fireStateChanged();
}
}
};
myRbPrivate = new JRadioButton();
myRbPrivate.setText(GroovyRefactoringBundle.message("visibility.private"));
myRbPrivate.addItemListener(listener);
myRbPrivate.setFocusable(false);
myRbPrivate.setMnemonic(KeyEvent.VK_V);
add(myRbPrivate);
bg.add(myRbPrivate);
myRbProtected = new JRadioButton();
myRbProtected.setText(GroovyRefactoringBundle.message("visibility.protected"));
myRbProtected.addItemListener(listener);
myRbProtected.setFocusable(false);
myRbProtected.setMnemonic(KeyEvent.VK_O);
add(myRbProtected);
bg.add(myRbProtected);
myRbPublic = new JRadioButton();
myRbPublic.setText(GroovyRefactoringBundle.message("visibility.public"));
myRbPublic.addItemListener(listener);
myRbPublic.setFocusable(false);
myRbPublic.setMnemonic(KeyEvent.VK_B);
add(myRbPublic);
bg.add(myRbPublic);
}
@NotNull
public String getVisibility() {
if (myRbPublic.isSelected()) {
return PsiModifier.PUBLIC;
}
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);
}
else if (PsiModifier.PROTECTED.equals(visibility)) {
myRbProtected.setSelected(true);
}
else if (PsiModifier.PRIVATE.equals(visibility)) {
myRbPrivate.setSelected(true);
}
}
public static interface VisibilityStateChanged extends EventListener {
void visibilityChanged(String newVisibility);
}
public void addStateChangedListener(VisibilityStateChanged l) {
listenerList.add(VisibilityStateChanged.class, l);
}
public void fireStateChanged() {
Object[] list = listenerList.getListenerList();
String visibility = getVisibility();
for (Object obj : list) {
if (obj instanceof VisibilityStateChanged) {
((VisibilityStateChanged)obj).visibilityChanged(visibility);
}
}
}
}
@@ -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;
}
}
@@ -0,0 +1,38 @@
/*
* 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.refactoring.ui.ComboBoxVisibilityPanel;
import static com.intellij.psi.PsiModifier.*;
import static com.intellij.util.VisibilityUtil.toPresentableText;
/**
* @author Max Medvedev
*/
public class GroovyComboboxVisibilityPanel extends ComboBoxVisibilityPanel {
private static final String[] MODIFIERS = {PRIVATE, PROTECTED, PUBLIC};
private static final String[] PRESENTABLE_NAMES = {
toPresentableText(PRIVATE),
toPresentableText(PROTECTED),
toPresentableText(PUBLIC)
};
public GroovyComboboxVisibilityPanel() {
super(MODIFIERS, PRESENTABLE_NAMES);
}
}
@@ -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;
@@ -34,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());
}
@@ -45,7 +46,7 @@ public class ExtractMethodTest extends LightGroovyTestCase {
private void doTest() {
final List<String> 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"));
}
@@ -7,11 +7,11 @@ void aaa(Map map) {
-----
void aaa(Map map) {
for (Map.Entry<String, String> versionEntry in map.entrySet()) {
testMethod(versionEntry);
testMethod(versionEntry)
}
}
private testMethod(Map.Entry<String, String> versionEntry) {
String name = versionEntry.getKey();
System.out.println(name)
System.out.println(name);
}