From b79013283088edc6f103e57e02029d6d6a659ec4 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Mon, 10 Sep 2012 08:57:10 +0400 Subject: [PATCH] IDEA-91164 Should have an Intention to strongly type groovy variable --- .../after.groovy.template | 1 + .../before.groovy.template | 1 + .../GrSetStrongTypeIntention/description.html | 5 + plugins/groovy/src/META-INF/plugin.xml | 5 + .../GroovyIntentionsBundle.properties | 2 + .../declaration/GrSetStrongTypeIntention.java | 114 ++++++++++++++++++ .../convertToJava/ExpressionGenerator.java | 12 +- .../expressions/ChooseTypeExpression.java | 7 +- 8 files changed, 136 insertions(+), 11 deletions(-) create mode 100644 plugins/groovy/resources/intentionDescriptions/GrSetStrongTypeIntention/after.groovy.template create mode 100644 plugins/groovy/resources/intentionDescriptions/GrSetStrongTypeIntention/before.groovy.template create mode 100644 plugins/groovy/resources/intentionDescriptions/GrSetStrongTypeIntention/description.html create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrSetStrongTypeIntention.java diff --git a/plugins/groovy/resources/intentionDescriptions/GrSetStrongTypeIntention/after.groovy.template b/plugins/groovy/resources/intentionDescriptions/GrSetStrongTypeIntention/after.groovy.template new file mode 100644 index 000000000000..e04a2d7f7f71 --- /dev/null +++ b/plugins/groovy/resources/intentionDescriptions/GrSetStrongTypeIntention/after.groovy.template @@ -0,0 +1 @@ +int abc = 5 \ No newline at end of file diff --git a/plugins/groovy/resources/intentionDescriptions/GrSetStrongTypeIntention/before.groovy.template b/plugins/groovy/resources/intentionDescriptions/GrSetStrongTypeIntention/before.groovy.template new file mode 100644 index 000000000000..69c4e1f1029f --- /dev/null +++ b/plugins/groovy/resources/intentionDescriptions/GrSetStrongTypeIntention/before.groovy.template @@ -0,0 +1 @@ +def abc = 5 \ No newline at end of file diff --git a/plugins/groovy/resources/intentionDescriptions/GrSetStrongTypeIntention/description.html b/plugins/groovy/resources/intentionDescriptions/GrSetStrongTypeIntention/description.html new file mode 100644 index 000000000000..9cef258aee57 --- /dev/null +++ b/plugins/groovy/resources/intentionDescriptions/GrSetStrongTypeIntention/description.html @@ -0,0 +1,5 @@ + + +This intention inserts type declaration to the selected variable. + + \ No newline at end of file diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 190922a76023..c47140ec7ac0 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -1215,6 +1215,11 @@ intention.category.groovy/intention.category.groovy.declaration org.jetbrains.plugins.groovy.intentions.declaration.GrCreateFieldForParameterIntention + + org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle + intention.category.groovy/intention.category.groovy.declaration + org.jetbrains.plugins.groovy.intentions.declaration.GrSetStrongTypeIntention + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties index 4c81f7c81e33..3f7457df039e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties @@ -166,6 +166,8 @@ gr.convert.string.to.char.intention.name=Cast to char gr.convert.string.to.char.intention.family.name=Cast to char create.field.for.parameter.0 = Create Field for Parameter {0} create.field.for.parameter=Create Field for Parameter +gr.set.strong.type.intention.name=Declare explicit type +gr.set.strong.type.intention.family.name=Declare explicit type remove.unnecessary.escape.characters.intention.name=Remove unnecessary escape characters remove.unnecessary.escape.characters.intention.family.name=Remove unnecessary escape characters gr.break.string.on.line.breaks.intention.name=Break string on '\\n' diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrSetStrongTypeIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrSetStrongTypeIntention.java new file mode 100644 index 000000000000..1244719260cc --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrSetStrongTypeIntention.java @@ -0,0 +1,114 @@ +/* + * 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.intentions.declaration; + +import com.intellij.codeInsight.CodeInsightUtilBase; +import com.intellij.codeInsight.template.Template; +import com.intellij.codeInsight.template.TemplateBuilderImpl; +import com.intellij.codeInsight.template.TemplateManager; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiManager; +import com.intellij.psi.PsiType; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.intentions.base.Intention; +import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; +import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SupertypeConstraint; +import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; +import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; +import org.jetbrains.plugins.groovy.template.expressions.ChooseTypeExpression; + +import java.util.ArrayList; + +/** + * Created with IntelliJ IDEA. + * User: maxmedvedev + * Date: 9/8/12 + * Time: 9:55 + * To change this template use File | Settings | File Templates. + */ +public class GrSetStrongTypeIntention extends Intention { + + + @Override + protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException { + if (element instanceof GrVariableDeclaration) { + GrVariable[] variables = ((GrVariableDeclaration)element).getVariables(); + ArrayList types = new ArrayList(); + for (GrVariable variable : variables) { + if (variable.getInitializerGroovy() != null) { + PsiType type = variable.getInitializerGroovy().getType(); + types.add(SupertypeConstraint.create(type)); + } + } + + TemplateBuilderImpl builder = new TemplateBuilderImpl(element); + + + PsiManager manager = element.getManager(); + + GrModifierList modifierList = ((GrVariableDeclaration)element).getModifierList(); + if (modifierList.hasModifierProperty(GrModifier.DEF) && modifierList.getModifiers().length == 1) { + PsiElement def = PsiUtil.findModifierInList(modifierList, GrModifier.DEF); + builder.replaceElement(def, new ChooseTypeExpression(types.toArray(new TypeConstraint[types.size()]), manager)); + } + else { + ((GrVariableDeclaration)element).setType(TypesUtil.createType("Abc", element)); + GrTypeElement typeElement = ((GrVariableDeclaration)element).getTypeElementGroovy(); + builder.replaceElement(typeElement, new ChooseTypeExpression(types.toArray(new TypeConstraint[types.size()]), manager)); + } + + + final PsiElement afterPostprocess = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(element); + final Template template = builder.buildTemplate(); + TextRange range = afterPostprocess.getTextRange(); + Document document = editor.getDocument(); + document.deleteString(range.getStartOffset(), range.getEndOffset()); + + TemplateManager templateManager = TemplateManager.getInstance(project); + templateManager.startTemplate(editor, template); + } + } + + @NotNull + @Override + protected PsiElementPredicate getElementPredicate() { + return new PsiElementPredicate() { + @Override + public boolean satisfiedBy(PsiElement element) { + if (element instanceof GrVariableDeclaration && ((GrVariableDeclaration)element).getTypeElementGroovy() == null) { + GrVariable[] variables = ((GrVariableDeclaration)element).getVariables(); + for (GrVariable variable : variables) { + if (variable.getInitializerGroovy() != null) return true; + } + } + + return false; + } + }; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java index aa275520e18f..bf202bdfd560 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java @@ -1008,15 +1008,9 @@ public class ExpressionGenerator extends Generator { @Override public void visitThisSuperReferenceExpression(GrThisSuperReferenceExpression expr) { - if (context.isInAnonymousContext() && expr.getQualifier() == null) { - builder.append(expr.getReferenceName()); - return; - } - final PsiElement resolved = expr.resolve(); - LOG.assertTrue(resolved instanceof PsiClass); - - if (!(resolved instanceof PsiAnonymousClass)) { - builder.append(((PsiClass)resolved).getQualifiedName()).append('.'); + GrReferenceExpression qualifier = expr.getQualifier(); + if (!context.isInAnonymousContext() && qualifier != null) { + qualifier.accept(this); } builder.append(expr.getReferenceName()); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/template/expressions/ChooseTypeExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/template/expressions/ChooseTypeExpression.java index 92d87712bccb..98568427ec21 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/template/expressions/ChooseTypeExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/template/expressions/ChooseTypeExpression.java @@ -27,6 +27,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SubtypeConstraint; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SupertypeConstraint; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import java.util.LinkedHashSet; import java.util.Set; @@ -88,8 +89,7 @@ public class ChooseTypeExpression extends Expression { private PsiType chooseType(TypeConstraint[] constraints) { if (constraints.length > 0) return constraints[0].getDefaultType(); - return JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory() - .createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, GlobalSearchScope.allScope(myManager.getProject())); + return PsiType.getJavaLangObject(myManager, GlobalSearchScope.allScope(myManager.getProject())); } public Result calculateResult(ExpressionContext context) { @@ -100,6 +100,9 @@ public class ChooseTypeExpression extends Expression { return new TextResult(GrModifier.DEF); } + type = TypesUtil.unboxPrimitiveTypeWrapper(type); + if (type == null) return null; + return new PsiTypeResult(type, context.getProject()) { @Override public void handleRecalc(PsiFile psiFile, Document document, int segmentStart, int segmentEnd) {