From c8e11c61eb7b0fc4fe4d40119c2afcc19dabe6b1 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Fri, 29 Mar 2013 17:07:19 +0400 Subject: [PATCH] IDEA-99867 Groovy Static type checking: parameters of closures should have explict types. Intention to insert type --- .../declaration/GrSetStrongTypeIntention.java | 38 ++++++++++++++++--- .../ClosureParameterEnhancer.java | 19 +++++----- 2 files changed, 43 insertions(+), 14 deletions(-) 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 index eb2350b0568b..c7c9afaada9e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrSetStrongTypeIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrSetStrongTypeIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -23,10 +23,7 @@ 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.PsiClassType; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiManager; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,12 +33,16 @@ 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.statements.clauses.GrForInClause; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; 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.typeEnhancers.ClosureParameterEnhancer; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.template.expressions.ChooseTypeExpression; @@ -70,6 +71,10 @@ public class GrSetStrongTypeIntention extends Intention { variables = ((GrVariableDeclaration)parent).getVariables(); elementToBuildTemplate = parent; } + else if (parent instanceof GrParameter && parent.getParent() instanceof GrParameterList) { + variables = new GrVariable[]{(GrVariable)parent}; + elementToBuildTemplate = parent.getParent().getParent(); + } else if (parent instanceof GrVariable) { variables = new GrVariable[]{((GrVariable)parent)}; elementToBuildTemplate = parent; @@ -92,6 +97,13 @@ public class GrSetStrongTypeIntention extends Intention { types.add(SupertypeConstraint.create(type)); } } + if (variable instanceof GrParameter) { + final PsiParameter parameter = (PsiParameter)variable; + final PsiType type = getClosureParameterType(parameter); + if (type != null) { + types.add(SupertypeConstraint.create(type)); + } + } } } @@ -116,6 +128,19 @@ public class GrSetStrongTypeIntention extends Intention { templateManager.startTemplate(editor, template); } + @Nullable + private static PsiType getClosureParameterType(@NotNull PsiParameter parameter) { + final PsiElement scope = parameter.getDeclarationScope(); + final PsiType type; + if (scope instanceof GrClosableBlock) { + type = ClosureParameterEnhancer.inferType((GrClosableBlock)scope, ((GrParameterList)parameter.getParent()).getParameterIndex(parameter)); + } + else { + type = null; + } + return type; + } + @Nullable private static PsiElement setType(PsiElement element, PsiElement parent, PsiElement elementToBuildTemplate) { GrModifierList modifierList = getModifierList(parent); @@ -187,6 +212,9 @@ public class GrSetStrongTypeIntention extends Intention { else if (pparent instanceof GrForInClause) { return PsiUtil.extractIteratedType((GrForInClause)pparent) != null; } + else if (parent instanceof GrParameter && pparent instanceof GrParameterList) { + return getClosureParameterType((PsiParameter)parent) != null; + } else { return isVarDeclaredWithInitializer((GrVariable)parent); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java index 99d90ee389f1..d6854fdea9c8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java @@ -19,7 +19,6 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.containers.hash.HashMap; import com.intellij.util.containers.hash.HashSet; @@ -34,7 +33,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrRefere import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrStringInjection; import org.jetbrains.plugins.groovy.lang.psi.impl.GrRangeType; import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GdkMethodUtil; @@ -49,10 +47,10 @@ import static com.intellij.psi.CommonClassNames.JAVA_IO_FILE; * @author peter */ public class ClosureParameterEnhancer extends AbstractClosureParameterEnhancer { - private final Map simpleTypes = new HashMap(); - private final Set iterations = new HashSet(); + private static final Map simpleTypes = new HashMap(); + private static final Set iterations = new HashSet(); - public ClosureParameterEnhancer() { + static { simpleTypes.put("times", "java.lang.Integer"); simpleTypes.put("upto", "java.lang.Integer"); simpleTypes.put("downto", "java.lang.Integer"); @@ -105,22 +103,25 @@ public class ClosureParameterEnhancer extends AbstractClosureParameterEnhancer { iterations.add("findIndexValues"); iterations.add("findIndexOf"); iterations.add("count"); - } @Override @Nullable protected PsiType getClosureParameterType(GrClosableBlock closure, int index) { - final PsiMember containingMember = PsiTreeUtil.getParentOfType(closure, PsiMember.class); - if (containingMember != null && GroovyPsiManager.getInstance(closure.getProject()).isCompileStatic(containingMember)) { + if (org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.isCompileStatic(closure)) { return null; } + return inferType(closure, index); + } + + @Nullable + public static PsiType inferType(@NotNull GrClosableBlock closure, int index) { PsiElement parent = closure.getParent(); if (parent instanceof GrStringInjection && index == 0) { return TypesUtil.createTypeByFQClassName("java.io.StringWriter", closure); } - + if (parent instanceof GrArgumentList) parent = parent.getParent(); if (!(parent instanceof GrMethodCall)) { return null;