From 51f20ecbab08ea532a5280a5903fa45b671f1d29 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Sat, 23 Nov 2013 15:33:44 +0400 Subject: [PATCH] IDEA-116628 No nulls in type parameters --- .../MissingReturnInspection.java | 62 +++++++++++- .../plugins/groovy/gpp/GppTypeConverter.java | 17 ++-- .../GroovyExpectedTypesProvider.java | 28 +----- .../groovy/lang/psi/impl/GrClosureType.java | 33 +++---- .../lang/psi/impl/GrLiteralClassType.java | 34 ++++--- .../groovy/lang/psi/impl/GrMapType.java | 10 +- .../groovy/lang/psi/impl/GrRangeType.java | 18 +++- .../groovy/lang/psi/impl/GrSpreadType.java | 78 --------------- .../groovy/lang/psi/impl/GrTupleType.java | 20 ++-- .../statements/expressions/TypesUtil.java | 9 ++ .../DefaultCallExpressionTypeCalculator.java | 13 +-- .../groovy/lang/GppFunctionalTest.groovy | 35 ------- .../lang/LiteralConstructorUsagesTest.groovy | 94 +------------------ .../codeBlock/emptyList.java | 2 +- .../codeBlock/emptyMap.java | 2 +- .../file/dynamicMethodsAccess.java | 2 +- .../file/reflectedMethodWithEllipsis.java | 2 +- 17 files changed, 149 insertions(+), 310 deletions(-) delete mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrSpreadType.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java index fc23c014df46..31a97407fd13 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java @@ -16,6 +16,7 @@ package org.jetbrains.plugins.groovy.codeInspection.noReturnMethod; import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; @@ -29,16 +30,26 @@ import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementVisitor; +import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; 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.expressions.GrMethodCall; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.MaybeReturnInstruction; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ThrowingInstruction; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider; +import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * @author ven @@ -67,7 +78,7 @@ public class MissingReturnInspection extends GroovySuppressableInspectionTool { public static ReturnStatus getReturnStatus(PsiElement subject) { if (subject instanceof GrClosableBlock) { - final PsiType inferredReturnType = GroovyExpectedTypesProvider.getExpectedClosureReturnType((GrClosableBlock)subject); + final PsiType inferredReturnType = getExpectedClosureReturnType((GrClosableBlock)subject); if (inferredReturnType instanceof PsiClassType) { PsiClass resolved = ((PsiClassType)inferredReturnType).resolve(); if (resolved != null && !(resolved instanceof PsiTypeParameter)) return mustReturnValue; @@ -83,6 +94,55 @@ public class MissingReturnInspection extends GroovySuppressableInspectionTool { } } + @Nullable + public static PsiType getExpectedClosureReturnType(GrClosableBlock closure) { + List expectedReturnTypes = new ArrayList(); + + PsiElement parent = closure.getParent(); + if (parent instanceof GrArgumentList && parent.getParent() instanceof GrMethodCall || parent instanceof GrMethodCall) { + GrMethodCall call = (GrMethodCall)(parent instanceof GrArgumentList ? parent.getParent() : parent); + + GroovyResolveResult[] variants = call.getCallVariants(null); + + for (GroovyResolveResult variant : variants) { + Map> map = + GrClosureSignatureUtil.mapArgumentsToParameters(variant, closure, true, true, call.getNamedArguments(), call.getExpressionArguments(), call.getClosureArguments()); + + if (map != null) { + Pair pair = map.get(closure); + if (pair == null) continue; + + PsiParameter parameter = pair.getFirst(); + + PsiType type = parameter.getType(); + if (TypesUtil.isPsiClassTypeToClosure(type)) { + PsiType[] parameters = ((PsiClassType)type).getParameters(); + if (parameters.length == 1) { + expectedReturnTypes.add(parameters[0]); + } + } + } + } + } + else { + final Set expectedTypes = GroovyExpectedTypesProvider.getDefaultExpectedTypes(closure); + + for (PsiType expectedType : expectedTypes) { + if (TypesUtil.isPsiClassTypeToClosure(expectedType)) { + PsiType[] parameters = ((PsiClassType)expectedType).getParameters(); + if (parameters.length == 1) { + expectedReturnTypes.add(parameters[0]); + } + } + } + } + + for (PsiType type : expectedReturnTypes) { + if (PsiType.VOID.equals(type)) return PsiType.VOID; + } + return TypesUtil.getLeastUpperBoundNullable(expectedReturnTypes, closure.getManager()); + } + @NotNull public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder problemsHolder, boolean onTheFly) { return new GroovyPsiElementVisitor(new GroovyElementVisitor() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java index 7c8714897b5b..0b4e639a0035 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java @@ -73,10 +73,13 @@ public class GppTypeConverter extends GrTypeConverter { final PsiType expectedComponent = PsiUtil.extractIterableTypeParameter(lType, false); if (expectedComponent != null && isMethodCallConversion(context)) { - PsiType tupleComponent = tupleType.getParameters()[0]; - if (tupleComponent != null && - TypesUtil.isAssignable(expectedComponent, tupleComponent, context) && hasDefaultConstructor(lType)) { - return true; + PsiType[] parameters = tupleType.getParameters(); + if (parameters.length == 1) { + PsiType tupleComponent = parameters[0]; + if (tupleComponent != null && + TypesUtil.isAssignable(expectedComponent, tupleComponent, context) && hasDefaultConstructor(lType)) { + return true; + } } } @@ -88,10 +91,10 @@ public class GppTypeConverter extends GrTypeConverter { final PsiType lKeyType = PsiUtil.substituteTypeParameter(lType, CommonClassNames.JAVA_UTIL_MAP, 0, false); final PsiType lValueType = PsiUtil.substituteTypeParameter(lType, CommonClassNames.JAVA_UTIL_MAP, 1, false); final PsiType[] parameters = ((GrMapType)rType).getParameters(); - if (lKeyType != null && lValueType != null && + if (parameters.length == 2 && lKeyType != null && lValueType != null && parameters[0] != null && parameters[1] != null && - (!TypesUtil.isAssignable(lKeyType, parameters[0], context) || !TypesUtil - .isAssignable(lValueType, parameters[1], context))) { + (!TypesUtil.isAssignable(lKeyType, parameters[0], context) || + !TypesUtil.isAssignable(lValueType, parameters[1], context))) { return null; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesProvider.java index d03a7101861e..f3779a15910a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesProvider.java @@ -105,32 +105,6 @@ public class GroovyExpectedTypesProvider { return result; } - @Nullable - public static PsiType getExpectedClosureReturnType(GrClosableBlock closure) { - final Set expectedTypes = getDefaultExpectedTypes(closure); - - List expectedReturnTypes = new ArrayList(); - for (PsiType expectedType : expectedTypes) { - if (!(expectedType instanceof PsiClassType)) return null; - - final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)expectedType).resolveGenerics(); - final PsiClass resolved = resolveResult.getElement(); - if (resolved == null || !(GroovyCommonClassNames.GROOVY_LANG_CLOSURE.equals(resolved.getQualifiedName()))) return null; - - final PsiTypeParameter[] typeParameters = resolved.getTypeParameters(); - if (typeParameters.length != 1) return null; - - final PsiTypeParameter expected = typeParameters[0]; - final PsiType expectedReturnType = resolveResult.getSubstitutor().substitute(expected); - if (expectedReturnType == PsiType.VOID || expectedReturnType == null) return null; - - expectedReturnTypes.add(expectedReturnType); - } - - return TypesUtil.getLeastUpperBoundNullable(expectedReturnTypes, closure.getManager()); -} - - private static class MyCalculator extends GroovyElementVisitor { private TypeConstraint[] myResult; private final GrExpression myExpression; @@ -214,7 +188,7 @@ public class GroovyExpectedTypesProvider { final GrExpression[] expressionArgs = argumentList == null ? GrExpression.EMPTY_ARRAY : argumentList.getExpressionArguments(); try { final Map> map = - GrClosureSignatureUtil.mapArgumentsToParameters(variant, methodCall, true, true, namedArgs, expressionArgs, closureArgs); + GrClosureSignatureUtil.mapArgumentsToParameters(variant, methodCall, true, false, namedArgs, expressionArgs, closureArgs); addConstraintsFromMap(constraints, map); } catch (RuntimeException e) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureType.java index 04db42793f7f..6d59dd8adc28 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureType.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureType.java @@ -39,7 +39,7 @@ import java.util.List; * @author ven */ public class GrClosureType extends GrLiteralClassType { - private final @NotNull GrSignature mySignature; + private final GrSignature mySignature; private PsiType[] myTypeArgs = null; private GrClosureType(@NotNull LanguageLevel languageLevel, @@ -52,21 +52,22 @@ public class GrClosureType extends GrLiteralClassType { if (!shouldInferTypeParameters) myTypeArgs = PsiType.EMPTY_ARRAY; } + private GrClosureType(@NotNull LanguageLevel level, + @NotNull GlobalSearchScope scope, + @NotNull JavaPsiFacade facade, + @NotNull GrSignature signature, + @NotNull PsiType[] typeArgs) { + super(level, scope, facade); + + mySignature = signature; + myTypeArgs = typeArgs; + } + @NotNull public String getClassName() { return "Closure"; } - @Override - public int getParameterCount() { - if (myTypeArgs != null) { - return myTypeArgs.length; - } - - final PsiClass psiClass = resolve(); - return psiClass != null && psiClass.getTypeParameters().length == 1 ? 1 : 0; - } - @NotNull public PsiType[] getParameters() { if (myTypeArgs == null) { @@ -79,7 +80,7 @@ public class GrClosureType extends GrLiteralClassType { final PsiClass psiClass = resolve(); if (psiClass != null && psiClass.getTypeParameters().length == 1) { final PsiType type = GrClosureSignatureUtil.getReturnType(mySignature); - if (type == PsiType.NULL) { + if (type == PsiType.NULL || type == null) { return new PsiType[]{null}; } else { @@ -129,9 +130,7 @@ public class GrClosureType extends GrLiteralClassType { @NotNull public PsiClassType setLanguageLevel(@NotNull final LanguageLevel languageLevel) { - final GrClosureType result = create(mySignature, myScope, myFacade, languageLevel, true); - result.myTypeArgs = this.myTypeArgs; - return result; + return new GrClosureType(languageLevel, myScope, myFacade, mySignature, myTypeArgs); } public static GrClosureType create(GroovyResolveResult[] results, GroovyPsiElement context) { @@ -187,9 +186,7 @@ public class GrClosureType extends GrLiteralClassType { public PsiType curry(@NotNull PsiType[] args, int position, @NotNull GroovyPsiElement context) { final GrSignature newSignature = mySignature.curry(args, position, context); if (newSignature == null) return null; - final GrClosureType result = create(newSignature, myScope, myFacade, myLanguageLevel, true); - result.myTypeArgs = this.myTypeArgs; - return result; + return new GrClosureType(myLanguageLevel, myScope, myFacade, newSignature, myTypeArgs); } @NotNull diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLiteralClassType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLiteralClassType.java index 55c8d34e9594..3595f8d70dc5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLiteralClassType.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLiteralClassType.java @@ -46,20 +46,7 @@ public abstract class GrLiteralClassType extends PsiClassType { @NotNull public ClassResolveResult resolveGenerics() { final PsiClass myBaseClass = resolve(); - final PsiSubstitutor substitutor; - if (myBaseClass != null) { - final PsiType[] typeArgs = getParameters(); - final PsiTypeParameter[] typeParams = myBaseClass.getTypeParameters(); - if (typeParams.length == typeArgs.length) { - substitutor = PsiSubstitutor.EMPTY.putAll(myBaseClass, typeArgs); - } - else { - substitutor = PsiSubstitutor.EMPTY; - } - } - else { - substitutor = PsiSubstitutor.EMPTY; - } + final PsiSubstitutor substitutor = inferSubstitutor(myBaseClass); return new ClassResolveResult() { @@ -94,6 +81,23 @@ public abstract class GrLiteralClassType extends PsiClassType { }; } + @NotNull + private PsiSubstitutor inferSubstitutor(@Nullable PsiClass myBaseClass) { + if (myBaseClass != null) { + final PsiType[] typeArgs = getParameters(); + final PsiTypeParameter[] typeParams = myBaseClass.getTypeParameters(); + if (typeParams.length == typeArgs.length) { + return PsiSubstitutor.EMPTY.putAll(myBaseClass, typeArgs); + } + else { + return PsiSubstitutor.EMPTY.putAll(myBaseClass, new PsiType[typeParams.length]); + } + } + else { + return PsiSubstitutor.EMPTY; + } + } + @Override @NotNull public abstract String getClassName() ; @@ -161,7 +165,7 @@ public abstract class GrLiteralClassType extends PsiClassType { } @NotNull - protected PsiType getLeastUpperBound(PsiType[] psiTypes) { + protected PsiType getLeastUpperBound(PsiType... psiTypes) { PsiType result = null; final PsiManager manager = getPsiManager(); for (final PsiType other : psiTypes) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java index 69f11760cb8d..3387f988057e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java @@ -37,8 +37,6 @@ import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames. * @author peter */ public class GrMapType extends GrLiteralClassType { - private static final PsiType[] RAW_PARAMETERS = new PsiType[]{null, null}; - private final Map myStringEntries; private final List> myOtherEntries; private final String myJavaClassName; @@ -83,12 +81,6 @@ public class GrMapType extends GrLiteralClassType { } } - @NotNull - @Override - public PsiClassType rawType() { - return new GrMapType(myFacade, getResolveScope(), Collections.emptyMap(), Collections.>emptyList(), getLanguageLevel()); - } - @NotNull @Override protected String getJavaClassName() { @@ -136,7 +128,7 @@ public class GrMapType extends GrLiteralClassType { final PsiType[] keyTypes = getAllKeyTypes(); final PsiType[] valueTypes = getAllValueTypes(); if (keyTypes.length == 0 && valueTypes.length == 0) { - return RAW_PARAMETERS; + return EMPTY_ARRAY; } return new PsiType[]{getLeastUpperBound(keyTypes), getLeastUpperBound(valueTypes)}; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrRangeType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrRangeType.java index bdd93682e691..ed887fff4c8c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrRangeType.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrRangeType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 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. @@ -18,6 +18,7 @@ package org.jetbrains.plugins.groovy.lang.psi.impl; import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiType; import com.intellij.psi.search.GlobalSearchScope; @@ -38,6 +39,8 @@ public class GrRangeType extends GrLiteralClassType { private final PsiType myIterationType; private final String myQualifiedName; + private final PsiType[] myParameters; + public GrRangeType(LanguageLevel languageLevel, GlobalSearchScope scope, JavaPsiFacade facade, @@ -53,6 +56,8 @@ public class GrRangeType extends GrLiteralClassType { else { myQualifiedName = GroovyCommonClassNames.GROOVY_LANG_OBJECT_RANGE; } + + myParameters = inferParameters(); } public GrRangeType(GlobalSearchScope scope, JavaPsiFacade facade, @Nullable PsiType left, @Nullable PsiType right) { @@ -74,7 +79,16 @@ public class GrRangeType extends GrLiteralClassType { @NotNull @Override public PsiType[] getParameters() { - return PsiType.EMPTY_ARRAY; + return myParameters; + } + + private PsiType[] inferParameters() { + if (myIterationType == null) return EMPTY_ARRAY; + + PsiClass resolved = resolve(); + if (resolved == null || resolved.getTypeParameters().length == 0) return EMPTY_ARRAY; + + return new PsiType[]{myIterationType}; } @NotNull diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrSpreadType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrSpreadType.java deleted file mode 100644 index 99b1556901de..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrSpreadType.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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.lang.psi.impl; - -import com.intellij.openapi.project.Project; -import com.intellij.pom.java.LanguageLevel; -import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.PsiClassType; -import com.intellij.psi.PsiType; -import com.intellij.psi.search.GlobalSearchScope; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; - -/** - * @author Max Medvedev - */ -public class GrSpreadType extends GrLiteralClassType { - - private PsiType myType; - - public GrSpreadType(PsiType original, PsiType containerType, GlobalSearchScope scope) { - this(original, containerType, LanguageLevel.JDK_1_5, scope, JavaPsiFacade.getInstance(scope.getProject())); - } - - public GrSpreadType(PsiType original, PsiType containerType, LanguageLevel languageLevel, GlobalSearchScope scope, JavaPsiFacade facade) { - super(languageLevel, scope, facade); - - final Project project = facade.getProject(); - myType = TypesUtil.createSimilarCollection(containerType, project, original); - } - - @NotNull - @Override - protected String getJavaClassName() { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - @NotNull - @Override - public String getClassName() { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - @NotNull - @Override - public PsiType[] getParameters() { - return new PsiType[0]; //To change body of implemented methods use File | Settings | File Templates. - } - - @NotNull - @Override - public PsiClassType setLanguageLevel(@NotNull LanguageLevel languageLevel) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public String getInternalCanonicalText() { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public boolean isValid() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } -} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrTupleType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrTupleType.java index 0be4a6698d82..9d1b305d0a8b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrTupleType.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrTupleType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -31,8 +31,8 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUt * @author ven */ public class GrTupleType extends GrLiteralClassType { - private static final PsiType[] RAW_PARAMETERS = new PsiType[]{null}; private final PsiType[] myComponentTypes; + private final PsiType[] myParameters; public GrTupleType(PsiType[] componentTypes, JavaPsiFacade facade, GlobalSearchScope scope) { this(componentTypes, facade, scope,LanguageLevel.JDK_1_5); @@ -40,6 +40,8 @@ public class GrTupleType extends GrLiteralClassType { public GrTupleType(PsiType[] componentTypes, JavaPsiFacade facade, GlobalSearchScope scope,LanguageLevel languageLevel) { super(languageLevel, scope, facade); myComponentTypes = componentTypes; + + myParameters = inferParameters(); } @NotNull @@ -48,12 +50,6 @@ public class GrTupleType extends GrLiteralClassType { return CommonClassNames.JAVA_UTIL_ARRAY_LIST; } - @NotNull - @Override - public PsiClassType rawType() { - return new GrTupleType(RAW_PARAMETERS, myFacade, getResolveScope(), getLanguageLevel()); - } - @NotNull public String getClassName() { return StringUtil.getShortName(getJavaClassName()); @@ -61,9 +57,13 @@ public class GrTupleType extends GrLiteralClassType { @NotNull public PsiType[] getParameters() { - if (myComponentTypes.length == 0) return RAW_PARAMETERS; + return myParameters; + } + + private PsiType[] inferParameters() { + if (myComponentTypes.length == 0) return PsiType.EMPTY_ARRAY; final PsiType leastUpperBound = getLeastUpperBound(myComponentTypes); - if (leastUpperBound == PsiType.NULL) return RAW_PARAMETERS; + if (leastUpperBound == PsiType.NULL) return EMPTY_ARRAY; return new PsiType[]{leastUpperBound}; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java index b3955eece999..ad3219cf8810 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java @@ -913,4 +913,13 @@ public class TypesUtil { if (!changed) return null; return JavaPsiFacade.getElementFactory(project).createType(element, parameters); } + + public static boolean isPsiClassTypeToClosure(PsiType type) { + if (!(type instanceof PsiClassType)) return false; + + final PsiClass psiClass = ((PsiClassType)type).resolve(); + if (psiClass == null) return false; + + return GROOVY_LANG_CLOSURE.equals(psiClass.getQualifiedName()); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/DefaultCallExpressionTypeCalculator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/DefaultCallExpressionTypeCalculator.java index 7c6c7b97b250..b8d1dedd7c79 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/DefaultCallExpressionTypeCalculator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/DefaultCallExpressionTypeCalculator.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. @@ -109,7 +109,7 @@ public class DefaultCallExpressionTypeCalculator extends GrCallExpressionTypeCal if (type instanceof GrClosureType) { returnType = GrClosureSignatureUtil.getReturnType(((GrClosureType)type).getSignature(), callExpression); } - else if (isPsiClassTypeToClosure(type)) { + else if (TypesUtil.isPsiClassTypeToClosure(type)) { assert type instanceof PsiClassType; final PsiType[] parameters = ((PsiClassType)type).getParameters(); if (parameters.length == 1) { @@ -131,15 +131,6 @@ public class DefaultCallExpressionTypeCalculator extends GrCallExpressionTypeCal } - private static boolean isPsiClassTypeToClosure(PsiType type) { - if (!(type instanceof PsiClassType)) return false; - - final PsiClass psiClass = ((PsiClassType)type).resolve(); - if (psiClass == null) return false; - - return GroovyCommonClassNames.GROOVY_LANG_CLOSURE.equals(psiClass.getQualifiedName()); - } - private static final Set CLOSURE_METHODS = new HashSet(); static { CLOSURE_METHODS.add("call"); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy index 3287b7613d56..39e4703016ca 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy @@ -405,41 +405,6 @@ class Point { assertEquals 1, multiResolveReference().size() } - public void testGotoSuperConstructorFromLiteralOnsets() throws Exception { - PsiClass point = myFixture.addClass(""" -class Point { - Point() {} - Point(int y) {} -}""") - - configureGppScript "Point p = [super: 2]" - assertEquals point.constructors[1], resolveReference() - - configureGppScript "Point p = [2]" - assertEquals point.constructors[1], resolveReference() - - configureGppScript "Point p = []" - assertEquals point.constructors[0], resolveReference() - - configureGppScript "Point p = [:]" - assertEquals point.constructors[0], resolveReference() - - configureGppScript "Point p = [239, 42]" - assertEquals 2, multiResolveReference().size() - - configureGppScript """ -def foo(Point p) {} -foo([2, 3]) -""" - assertEquals 2, multiResolveReference().size() - - configureGppScript """ -def foo(Point... p) {} -foo(['super':[2, 3]]) -""" - assertEquals 2, multiResolveReference().size() - } - public void testGotoClassFromLiteralOnsetsWhenNoConstructorsPresent() throws Exception { PsiClass point = myFixture.addClass(""" class Point { }""") configureGppScript "Point p = [super: 2]" diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/LiteralConstructorUsagesTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/LiteralConstructorUsagesTest.groovy index d24fa7de36b5..f56c2cb87bd4 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/LiteralConstructorUsagesTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/LiteralConstructorUsagesTest.groovy @@ -42,7 +42,7 @@ class LiteralConstructorUsagesTest extends LightGroovyTestCase { myFixture.addFileToProject "a.gpp", "Foo x = []" assertOneElement(ReferencesSearch.search(foo.constructors[0]).findAll()) } - + public void testList_ReturnValue() throws Exception { def foo = myFixture.addClass("""class Foo { Foo() {} @@ -97,98 +97,6 @@ Foo untyped() { [] } assertEquals(2, ReferencesSearch.search(foo.constructors[0]).findAll().size()) } - public void testList_GppMethodCall() throws Exception { - //------------------------declarations - def foo = myFixture.addClass(""" - package z; - class Foo { - public Foo() {} - } - """) - - myFixture.addClass(""" - package z; - public class Bar { - public static void giveMeFoo(int a, Foo f) {} - } -""") - myFixture.addFileToProject("Decl.groovy", "static def giveMeFooAsWell(z.Foo f) {}") - - //----------------------usages - myFixture.addFileToProject "a.gpp", "z.Bar.giveMeFoo(2, []) //usage" - myFixture.addFileToProject "b.groovy", """ - @Typed package aa; - z.Bar.giveMeFoo(3, []) //usage - """ - myFixture.addFileToProject "c.groovy", """ - @Typed def someMethod() { - z.Bar.giveMeFoo 4, [] //usage - Decl.giveMeFooAsWell([]) //usage - } - z.Bar.giveMeFoo 5, [] //non-typed context - Decl.giveMeFooAsWell([]) - """ - myFixture.addFileToProject "invalid.gpp", "z.Bar.giveMeFoo 42, 239, []" - myFixture.addFileToProject "nonGpp.groovy", "z.Bar.giveMeFoo(6, [])" - assertEquals(4, ReferencesSearch.search(foo.constructors[0]).findAll().size()) - } - - public void testList_GppConstructorCallWithSeveralParameters() throws Exception { - def foo = myFixture.addClass(""" - class Foo { - Foo() {} - } - """) - - myFixture.addClass(""" - class Bar { - Bar(Foo f1, Foo f2, Foo f3) {} - } - """) - myFixture.addFileToProject "a.gpp", "new Bar([],[],[])" - assertEquals(3, ReferencesSearch.search(foo.constructors[0]).findAll().size()) - } - - public void testMap_GppOverloads() throws Exception { - def foo = myFixture.addClass(""" - class Foo { - Foo() {} - Foo(int a) {} - } - """) - - myFixture.addClass(""" - class Bar { - static void foo(Foo f1, Foo f2) {} - } - """) - myFixture.addFileToProject "a.gpp", "Bar.foo([:], [super:2])" - assertEquals(1, ReferencesSearch.search(foo.constructors[0]).findAll().size()) - assertEquals(1, ReferencesSearch.search(foo.constructors[1]).findAll().size()) - } - - public void testGppCallVarargs() throws Exception { - def foo = myFixture.addClass(""" - class Foo { - Foo() {} - Foo(int a) {} - } - """) - - myFixture.addClass(""" - class Bar { - static void foo(Foo f1, Foo f2) {} - static void doo(int a, Foo f1, Foo f2) {} - } - """) - myFixture.addFileToProject "a.gpp", """ - Bar.foo([:], [super:2]) - Bar.doo 3, [:], [super:2] - """ - assertEquals(2, ReferencesSearch.search(foo.constructors[0]).findAll().size()) - assertEquals(2, ReferencesSearch.search(foo.constructors[1]).findAll().size()) - } - public void testOverloadedConstructorUsages() throws Exception { def foo = myFixture.addClass(""" class Foo { diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyList.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyList.java index f1283b852258..8f64cd13364f 100644 --- a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyList.java +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyList.java @@ -1,3 +1,3 @@ -java.util.ArrayList list = new java.util.ArrayList(); +java.util.ArrayList list = new java.util.ArrayList(); java.lang.Integer[] arr = new java.lang.Integer[0]; java.util.List strings = new java.util.ArrayList(); diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyMap.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyMap.java index ea2a48f2aa2e..75eabcd8e91c 100644 --- a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyMap.java +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyMap.java @@ -1,2 +1,2 @@ -java.util.Map map = new java.util.Map(); +java.util.Map map = new java.util.Map(); print(map.get(1)); diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/dynamicMethodsAccess.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/dynamicMethodsAccess.java index 61cfcc94699b..6a5310f384ae 100644 --- a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/dynamicMethodsAccess.java +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/dynamicMethodsAccess.java @@ -8,7 +8,7 @@ java.lang.String s = "a"; org.codehaus.groovy.runtime.DefaultGroovyMethods.invokeMethod(s, "bar", new java.lang.Object[]{4}); org.codehaus.groovy.runtime.DefaultGroovyMethods.print(this, org.codehaus.groovy.runtime.DefaultGroovyMethods.invokeMethod(s, "bar", new java.lang.Object[]{5})); -return org.codehaus.groovy.runtime.DefaultGroovyMethods.invokeMethod(s, "anme", new java.util.ArrayList()); +return org.codehaus.groovy.runtime.DefaultGroovyMethods.invokeMethod(s, "anme", new java.util.ArrayList()); } } diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/reflectedMethodWithEllipsis.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/reflectedMethodWithEllipsis.java index 3abffed415d8..6ae1849b2f89 100644 --- a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/reflectedMethodWithEllipsis.java +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/reflectedMethodWithEllipsis.java @@ -2,7 +2,7 @@ public class MyClass { public void foo(java.util.Map args, java.lang.String a, java.lang.String... b) {} public void foo(java.lang.String a, java.lang.String... b) { -foo(new java.util.LinkedHashMap(), a, b); +foo(new java.util.LinkedHashMap(), a, b); } }