Declare Variable, Add type annotation action for Introduce Variable feature.

This commit is contained in:
Alefas
2012-02-14 21:31:27 +04:00
parent a03922d467
commit 39d442b04f
6 changed files with 168 additions and 11 deletions
@@ -137,4 +137,9 @@ public class JetProperty extends JetTypeParameterListOwner implements JetModifie
public ASTNode getValOrVarNode() {
return getNode().findChildByType(TokenSet.create(VAL_KEYWORD, VAR_KEYWORD));
}
@Nullable
public ASTNode getEqualsSign() {
return getNode().findChildByType(TokenSet.create(EQ));
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
@@ -24,6 +25,7 @@ import com.intellij.util.LocalTimeCounter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lexer.JetKeywordToken;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.JetFileType;
import java.util.List;
@@ -32,6 +34,16 @@ import java.util.List;
* @author max
*/
public class JetPsiFactory {
public static ASTNode createValNode(Project project) {
JetProperty property = createProperty(project, "val x = 1");
return property.getValOrVarNode();
}
public static ASTNode createVarNode(Project project) {
JetProperty property = createProperty(project, "var x = 1");
return property.getValOrVarNode();
}
public static JetExpression createExpression(Project project, String text) {
JetProperty property = createProperty(project, "val x = " + text);
return property.getInitializer();
@@ -48,6 +60,11 @@ public class JetPsiFactory {
return Pair.create(property.findElementAt(5), property.findElementAt(7));
}
public static ASTNode createColonNode(Project project) {
JetProperty property = createProperty(project, "val x: Int");
return property.getNode().findChildByType(JetTokens.COLON);
}
public static PsiElement createWhiteSpace(Project project) {
return createWhiteSpace(project, " ");
}
-8
View File
@@ -1,8 +0,0 @@
fun a(op: (Int) -> Int) {}
fun b() {
a {it}
a {
it
}
2 + 2
}
@@ -0,0 +1,58 @@
package org.jetbrains.jet.plugin.refactoring.introduceVariable;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetProperty;
import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.psi.JetTypeReference;
import org.jetbrains.jet.lang.types.JetType;
/**
* User: Alefas
* Date: 14.02.12
*/
public class JetChangePropertyActions {
private JetChangePropertyActions() {
}
public static void declareValueOrVariable(Project project, boolean isVariable, JetProperty property) {
ASTNode node;
if (isVariable) {
node = JetPsiFactory.createVarNode(project);
} else {
node = JetPsiFactory.createValNode(project);
}
property.getValOrVarNode().getPsi().replace(node.getPsi());
}
public static void addTypeAnnotation(Project project, JetProperty property, @NotNull JetType exprType) {
if (property.getPropertyTypeRef() != null) return;
PsiElement anchor = property.getNameIdentifier();
if (anchor == null) return;
anchor = anchor.getNextSibling();
if (anchor == null || !(anchor instanceof PsiWhiteSpace)) return;
JetTypeReference typeReference = JetPsiFactory.createType(project, exprType.toString());
ASTNode colon = JetPsiFactory.createColonNode(project);
ASTNode anchorNode = anchor.getNode().getTreeNext();
property.getNode().addChild(colon, anchorNode);
property.getNode().addChild(JetPsiFactory.createWhiteSpace(project).getNode(), anchorNode);
property.getNode().addChild(typeReference.getNode(), anchorNode);
property.getNode().addChild(JetPsiFactory.createWhiteSpace(project).getNode(), anchorNode);
anchor.delete();
}
public static void removeTypeAnnotation(Project project, JetProperty property) {
JetTypeReference propertyTypeRef = property.getPropertyTypeRef();
if (propertyTypeRef == null) return;
PsiElement identifier = property.getNameIdentifier();
if (identifier == null) return;
PsiElement sibling = identifier.getNextSibling();
if (sibling == null) return;
PsiElement nextSibling = propertyTypeRef.getNextSibling();
if (nextSibling == null) return;
sibling.getParent().getNode().removeRange(sibling.getNode(), nextSibling.getNode());
}
}
@@ -16,15 +16,25 @@
package org.jetbrains.jet.plugin.refactoring.introduceVariable;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
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.PsiNamedElement;
import com.intellij.refactoring.introduce.inplace.InplaceVariableIntroducer;
import com.intellij.ui.NonFocusableCheckBox;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetProperty;
import org.jetbrains.jet.lang.types.JetType;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* User: Alefas
@@ -34,14 +44,88 @@ public class JetInplaceVariableIntroducer extends InplaceVariableIntroducer<JetE
private boolean myReplaceOccurrence;
private JetProperty myProperty;
private boolean isVar;
private boolean myDoNotChangeVar;
private @Nullable JetType myExprType;
private JCheckBox myVarCheckbox;
private JCheckBox myExprTypeCheckbox;
public JetInplaceVariableIntroducer(PsiNamedElement elementToRename, Editor editor, Project project,
String title, JetExpression[] occurrences,
@Nullable JetExpression expr, boolean replaceOccurrence,
JetProperty property) {
JetProperty property, boolean isVar, boolean doNotChangeVar,
@Nullable JetType exprType) {
super(elementToRename, editor, project, title, occurrences, expr);
this.myReplaceOccurrence = replaceOccurrence;
myProperty = property;
this.isVar = isVar;
myDoNotChangeVar = doNotChangeVar;
myExprType = exprType;
}
@Nullable
protected JComponent getComponent() {
if (!myDoNotChangeVar) {
myVarCheckbox = new NonFocusableCheckBox("Declare variable");
myVarCheckbox.setSelected(isVar);
myVarCheckbox.setMnemonic('v');
myVarCheckbox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new WriteCommandAction(myProject, getCommandName(), getCommandName()) {
@Override
protected void run(Result result) throws Throwable {
PsiDocumentManager.getInstance(myProject).commitDocument(myEditor.getDocument());
JetChangePropertyActions.declareValueOrVariable(myProject, myVarCheckbox.isSelected(),
myProperty);
}
}.execute();
}
});
}
if (myExpr != null) {
myExprTypeCheckbox = new NonFocusableCheckBox("Add type annotation");
myExprTypeCheckbox.setSelected(false);
myExprTypeCheckbox.setMnemonic('t');
myExprTypeCheckbox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new WriteCommandAction(myProject, getCommandName(), getCommandName()) {
@Override
protected void run(Result result) throws Throwable {
PsiDocumentManager.getInstance(myProject).commitDocument(myEditor.getDocument());
if (myExprTypeCheckbox.isSelected()) {
JetChangePropertyActions.addTypeAnnotation(myProject, myProperty, myExprType);
} else {
JetChangePropertyActions.removeTypeAnnotation(myProject, myProperty);
}
}
}.execute();
}
});
}
final JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(null);
int count = 1;
if (myVarCheckbox != null) {
panel.add(myVarCheckbox, new GridBagConstraints(0, count, 1, 1, 1, 0, GridBagConstraints.NORTHWEST,
GridBagConstraints.HORIZONTAL,
new Insets(5, 5, 5, 5), 0, 0));
++count;
}
if (myExprTypeCheckbox != null) {
panel.add(myExprTypeCheckbox, new GridBagConstraints(0, count, 1, 1, 1, 0, GridBagConstraints.NORTHWEST,
GridBagConstraints.HORIZONTAL,
new Insets(5, 5, 5, 5), 0, 0));
++count;
}
panel.add(Box.createVerticalBox(), new GridBagConstraints(0, count, 1, 1, 1, 1, GridBagConstraints.NORTHWEST,
GridBagConstraints.BOTH,
new Insets(0, 0, 0, 0), 0, 0));
return panel;
}
@Override
@@ -97,7 +97,7 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
}
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache((JetFile) expression.getContainingFile(),
AnalyzerFacade.SINGLE_DECLARATION_PROVIDER);
JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression); //can be null or error type
final JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression); //can be null or error type
if (expressionType instanceof NamespaceType) {
showErrorHint(project, editor, JetRefactoringBundle.message("cannot.refactor.namespace.expression"));
return;
@@ -156,7 +156,8 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
new JetInplaceVariableIntroducer(property, editor, project, INTRODUCE_VARIABLE,
references.toArray(new JetExpression[references.size()]),
reference.get(), finalReplaceOccurrence,
property);
property, /*todo*/false, /*todo*/false,
expressionType);
variableIntroducer.performInplaceRefactoring(suggestedNamesSet);
}
}