diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2013-04-01 14:41:51 -0700 |
---|---|---|
committer | Jean-Baptiste Queru <jbq@google.com> | 2013-04-01 14:41:51 -0700 |
commit | 2bd2b7c2623d4266384e890271869efc044aabff (patch) | |
tree | 0b31f50e55975b6354ed458314e17b4441bb4e17 /java/java-psi-api/src | |
parent | 1d526b16d476792ca7ce47616d55833115e8d6ab (diff) | |
download | idea-2bd2b7c2623d4266384e890271869efc044aabff.tar.gz |
Snapshot ee98b298267d0e09d2cd2f0731b6480a56dd48e7 from master branch of git://git.jetbrains.org/idea/community.git
Change-Id: I4515f72af131fdea9fc6905a4dc0fe9532409a81
Diffstat (limited to 'java/java-psi-api/src')
19 files changed, 240 insertions, 101 deletions
diff --git a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java index 1d6834be1dcb..1f91685ec32b 100644 --- a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.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. @@ -234,7 +234,8 @@ public class GenericsUtil { } @Nullable - public static PsiType getVariableTypeByExpressionType(final PsiType type) { + public static PsiType getVariableTypeByExpressionType(@Nullable final PsiType type) { + if (type == null) return null; PsiType transformed = type.accept(new PsiTypeVisitor<PsiType>() { @Override public PsiType visitArrayType(PsiArrayType arrayType) { diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java index 07cc842b7e05..fc1d2957c2da 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java @@ -28,9 +28,14 @@ import java.util.List; public class LambdaHighlightingUtil { @Nullable public static String checkInterfaceFunctional(@NotNull PsiClass psiClass) { + return checkInterfaceFunctional(psiClass, "Target type of a lambda conversion must be an interface"); + } + + @Nullable + public static String checkInterfaceFunctional(@NotNull PsiClass psiClass, String interfaceNonFunctionalMessage) { if (psiClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference final List<MethodSignature> signatures = LambdaUtil.findFunctionCandidates(psiClass); - if (signatures == null) return "Target type of a lambda conversion must be an interface"; + if (signatures == null) return interfaceNonFunctionalMessage; if (signatures.isEmpty()) return "No target method found"; if (signatures.size() == 1) { final MethodSignature functionalMethod = signatures.get(0); diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index 672f290abbdc..d66962410665 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -652,7 +652,7 @@ public class LambdaUtil { final PsiType interfaceReturnType1 = getReturnType(functionalInterfaceIdx, conflict); if (actualParameterTypes[functionalInterfaceIdx] instanceof PsiLambdaExpressionType || actualParameterTypes[functionalInterfaceIdx] instanceof PsiMethodReferenceType) { if (interfaceReturnType != null && interfaceReturnType1 != null && !Comparing.equal(interfaceReturnType, interfaceReturnType1)) { - int moreSpecific1 = isMoreSpecific(interfaceReturnType, interfaceReturnType1); + int moreSpecific1 = isMoreSpecific(interfaceReturnType, interfaceReturnType1, actualParameterTypes[functionalInterfaceIdx]); if (moreSpecific < 0 && moreSpecific1 > 0 || moreSpecific > 0 && moreSpecific1 < 0) { moreSpecific = 0; break; @@ -676,22 +676,38 @@ public class LambdaUtil { } } - private static int isMoreSpecific(PsiType returnType, PsiType returnType1) { + enum TypeKind { + PRIMITIVE, REFERENCE, NONE_DETERMINED + } + + private static int isMoreSpecific(PsiType returnType, PsiType returnType1, PsiType lambdaType) { if (returnType == PsiType.VOID || returnType1 == PsiType.VOID) return 0; - if (returnType instanceof PsiPrimitiveType) { - if (!(returnType1 instanceof PsiPrimitiveType)) { - return -1; - } else { - return TypeConversionUtil.isAssignable(returnType, returnType1) ? 1 : -1; + TypeKind typeKind = TypeKind.PRIMITIVE; + if (lambdaType instanceof PsiLambdaExpressionType) { + typeKind = areLambdaReturnExpressionsPrimitive((PsiLambdaExpressionType)lambdaType); + } else if (lambdaType instanceof PsiMethodReferenceType) { + final PsiElement referencedElement = ((PsiMethodReferenceType)lambdaType).getExpression().resolve(); + if (referencedElement instanceof PsiMethod && !(((PsiMethod)referencedElement).getReturnType() instanceof PsiPrimitiveType)) { + typeKind = TypeKind.REFERENCE; + } + } + if (typeKind != TypeKind.NONE_DETERMINED) { + if (returnType instanceof PsiPrimitiveType) { + final int moreSpecific = typeKind == TypeKind.PRIMITIVE ? 1 : -1; + if (!(returnType1 instanceof PsiPrimitiveType)) { + return -moreSpecific; + } else { + return TypeConversionUtil.isAssignable(returnType, returnType1) ? moreSpecific : -moreSpecific; + } + } + if (returnType1 instanceof PsiPrimitiveType) { + return typeKind == TypeKind.PRIMITIVE ? 1 : -1; } - } - if (returnType1 instanceof PsiPrimitiveType) { - return 1; } - final PsiClassType.ClassResolveResult r = PsiUtil.resolveGenericsClassInType(returnType); + final PsiClassType.ClassResolveResult r = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(returnType)); final PsiClass rClass = r.getElement(); - final PsiClassType.ClassResolveResult r1 = PsiUtil.resolveGenericsClassInType(returnType1); + final PsiClassType.ClassResolveResult r1 = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(returnType1)); final PsiClass rClass1 = r1.getElement(); if (rClass != null && rClass1 != null) { if (rClass == rClass1) { @@ -728,6 +744,28 @@ public class LambdaUtil { return 0; } + private static TypeKind areLambdaReturnExpressionsPrimitive(PsiLambdaExpressionType lambdaType) { + final List<PsiExpression> returnExpressions = getReturnExpressions(lambdaType.getExpression()); + TypeKind typeKind = TypeKind.NONE_DETERMINED; + for (PsiExpression expression : returnExpressions) { + final PsiType returnExprType = expression.getType(); + if (returnExprType instanceof PsiPrimitiveType) { + if (typeKind == TypeKind.REFERENCE) { + typeKind = TypeKind.NONE_DETERMINED; + break; + } + typeKind = TypeKind.PRIMITIVE; + } else { + if (typeKind == TypeKind.PRIMITIVE) { + typeKind = TypeKind.NONE_DETERMINED; + break; + } + typeKind = TypeKind.REFERENCE; + } + } + return typeKind; + } + @Nullable private static PsiType getReturnType(int functionalTypeIdx, CandidateInfo method) { final PsiParameter[] methodParameters = ((PsiMethod)method.getElement()).getParameterList().getParameters(); @@ -744,7 +782,7 @@ public class LambdaUtil { if (owner instanceof PsiModifierList) { final PsiElement parent = ((PsiModifierList)owner).getParent(); if (parent instanceof PsiClass) { - return LambdaHighlightingUtil.checkInterfaceFunctional((PsiClass)parent); + return LambdaHighlightingUtil.checkInterfaceFunctional((PsiClass)parent, ((PsiClass)parent).getName() + " is not a functional interface"); } } } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiAnnotation.java b/java/java-psi-api/src/com/intellij/psi/PsiAnnotation.java index dd80c5a0bb12..d2c9c77f6d2e 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiAnnotation.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiAnnotation.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. @@ -42,6 +42,18 @@ public interface PsiAnnotation extends PsiAnnotationMemberValue, PsiMetaOwner { @NonNls String DEFAULT_REFERENCED_METHOD_NAME = "value"; /** + * Kinds of element to which an annotation type is applicable (see {@link java.lang.annotation.ElementType}). + */ + enum TargetType { + // see java.lang.annotation.ElementType + TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_USE, TYPE_PARAMETER, + // auxiliary value, used when it's impossible to determine annotation's targets + UNKNOWN; + + public static final TargetType[] EMPTY_ARRAY = {}; + } + + /** * Returns the list of parameters for the annotation. * * @return the parameter list instance. @@ -69,8 +81,8 @@ public interface PsiAnnotation extends PsiAnnotationMemberValue, PsiMetaOwner { /** * Returns the value of the annotation element with the specified name. * - * @param attributeName name of the annotation element for which the value is requested. If it isn't defined in annotation, the default - * value is returned. + * @param attributeName name of the annotation element for which the value is requested. If it isn't defined in annotation, + * the default value is returned. * @return the element value, or null if the annotation does not contain a value for * the element and the element has no default value. */ diff --git a/java/java-psi-api/src/com/intellij/psi/PsiAnnotationOwner.java b/java/java-psi-api/src/com/intellij/psi/PsiAnnotationOwner.java index 086b28c5b959..fc66868cac80 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiAnnotationOwner.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiAnnotationOwner.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. @@ -31,16 +31,15 @@ public interface PsiAnnotationOwner { @NotNull PsiAnnotation[] getAnnotations(); - /** - * @return the list of annotations which are applicable to this owner. - * E.g. Type annotations on method belong to its type element, not the method. + * @return the list of annotations which are applicable to this owner + * (e.g. type annotations on method belong to its type element, not the method). */ @NotNull PsiAnnotation[] getApplicableAnnotations(); /** - * Searches the modifier list for an annotation with the specified fully qualified name + * Searches the owner for an annotation with the specified fully qualified name * and returns one if it is found. * * @param qualifiedName the fully qualified name of the annotation to find. @@ -50,7 +49,7 @@ public interface PsiAnnotationOwner { PsiAnnotation findAnnotation(@NotNull @NonNls String qualifiedName); /** - * Add a new annotation to this modifier list. The annotation class name will be shortened. No attributes will be defined. + * Adds a new annotation to this owner. The annotation class name will be shortened. No attributes will be defined. * * @param qualifiedName qualifiedName * @return newly added annotation diff --git a/java/java-psi-api/src/com/intellij/psi/PsiArrayType.java b/java/java-psi-api/src/com/intellij/psi/PsiArrayType.java index 1c6ed36d97bd..39d4dac9494a 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiArrayType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiArrayType.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. @@ -36,14 +36,14 @@ public class PsiArrayType extends PsiType { this(componentType, PsiAnnotation.EMPTY_ARRAY); } - public PsiArrayType(@NotNull PsiType componentType, PsiAnnotation[] annotations) { + public PsiArrayType(@NotNull PsiType componentType, @NotNull PsiAnnotation[] annotations) { super(annotations); myComponentType = componentType; } @Override public String getPresentableText() { - return StringUtil.joinOrNull(myComponentType.getPresentableText(), "[]"); + return StringUtil.joinOrNull(myComponentType.getPresentableText(), getAnnotationsTextPrefix(false, true, true), "[]"); } @Override @@ -53,7 +53,7 @@ public class PsiArrayType extends PsiType { @Override public String getInternalCanonicalText() { - return StringUtil.joinOrNull(myComponentType.getInternalCanonicalText(), "[]"); + return StringUtil.joinOrNull(myComponentType.getInternalCanonicalText(), getAnnotationsTextPrefix(true, true, true), "[]"); } @Override diff --git a/java/java-psi-api/src/com/intellij/psi/PsiClassType.java b/java/java-psi-api/src/com/intellij/psi/PsiClassType.java index 649f355502ca..5a85ba65fdff 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiClassType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiClassType.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. @@ -39,11 +39,13 @@ public abstract class PsiClassType extends PsiType { return new PsiClassType[count]; } }; + protected final LanguageLevel myLanguageLevel; protected PsiClassType(LanguageLevel languageLevel) { this(languageLevel, PsiAnnotation.EMPTY_ARRAY); } + protected PsiClassType(LanguageLevel languageLevel, @NotNull PsiAnnotation[] annotations) { super(annotations); myLanguageLevel = languageLevel; @@ -69,7 +71,8 @@ public abstract class PsiClassType extends PsiType { * * @return the array of type arguments, or an empty array if the type does not point to a generic class or interface. */ - @NotNull public abstract PsiType[] getParameters(); + @NotNull + public abstract PsiType[] getParameters(); public int getParameterCount() { return getParameters().length; @@ -78,8 +81,7 @@ public abstract class PsiClassType extends PsiType { public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof PsiClassType)) return false; - PsiClassType otherClassType = (PsiClassType) obj; - //if (!isValid() || !otherClassType.isValid()) return false; + PsiClassType otherClassType = (PsiClassType)obj; String className = getClassName(); String otherClassName = otherClassType.getClassName(); @@ -158,20 +160,20 @@ public abstract class PsiClassType extends PsiType { @Override @NotNull public PsiType[] getSuperTypes() { - final ClassResolveResult resolveResult = resolveGenerics(); - final PsiClass aClass = resolveResult.getElement(); + ClassResolveResult resolveResult = resolveGenerics(); + PsiClass aClass = resolveResult.getElement(); if (aClass == null) return EMPTY_ARRAY; - final PsiClassType[] superTypes = aClass.getSuperTypes(); - final PsiType[] subtitutionResults = new PsiType[superTypes.length]; + PsiClassType[] superTypes = aClass.getSuperTypes(); + PsiType[] substitutionResults = new PsiType[superTypes.length]; for (int i = 0; i < superTypes.length; i++) { - subtitutionResults[i] = resolveResult.getSubstitutor().substitute(superTypes[i]); + substitutionResults[i] = resolveResult.getSubstitutor().substitute(superTypes[i]); } - return subtitutionResults; + return substitutionResults; } /** - * Checks whether the specified resolve result representss a raw type. <br> + * Checks whether the specified resolve result represents a raw type. <br> * Raw type is a class type for a class <i>with type parameters</i> which does not assign * any value to them. If a class does not have any type parameters, it cannot generate any raw type. */ @@ -196,14 +198,16 @@ public abstract class PsiClassType extends PsiType { * * @return the resolve result instance. */ - @NotNull public abstract ClassResolveResult resolveGenerics(); + @NotNull + public abstract ClassResolveResult resolveGenerics(); /** * Returns the raw type (with no values assigned to type parameters) corresponding to this type. * * @return the raw type instance. */ - @NotNull public abstract PsiClassType rawType(); + @NotNull + public abstract PsiClassType rawType(); /** * Overrides {@link com.intellij.psi.PsiType#getResolveScope()} to narrow specify @NotNull. @@ -223,6 +227,7 @@ public abstract class PsiClassType extends PsiType { /** * Functional style setter preserving original type's language level + * * @param languageLevel level to obtain class type with * @return type with requested language level */ @@ -248,17 +253,17 @@ public abstract class PsiClassType extends PsiType { } @Override - public boolean isValidResult(){ + public boolean isValidResult() { return false; } @Override - public boolean isAccessible(){ + public boolean isAccessible() { return false; } @Override - public boolean isStaticsScopeCorrect(){ + public boolean isStaticsScopeCorrect() { return false; } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiElementFactory.java b/java/java-psi-api/src/com/intellij/psi/PsiElementFactory.java index 27eeb0a2663f..3838dc1ef1ff 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiElementFactory.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiElementFactory.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. @@ -43,7 +43,7 @@ public interface PsiElementFactory extends PsiJavaParserFacade, JVMElementFactor return ServiceManager.getService(project, PsiElementFactory.class); } } - + /** * Creates an empty class with the specified name. * @@ -164,12 +164,21 @@ public interface PsiElementFactory extends PsiJavaParserFacade, JVMElementFactor */ @NotNull PsiClassType createType(@NotNull PsiClass resolve, @NotNull PsiSubstitutor substitutor); - /* - additional languageLevel parameter to memorize language level for allowing/prohibiting boxing/unboxing + /** + * Creates a class type for the specified class, using the specified substitutor + * to replace generic type parameters on the class. + * + * @param resolve the class for which the class type is created. + * @param substitutor the substitutor to use. + * @param languageLevel to memorize language level for allowing/prohibiting boxing/unboxing. + * @return the class type instance. */ - @NotNull PsiClassType createType(@NotNull PsiClass resolve, @NotNull PsiSubstitutor substitutor, @NotNull LanguageLevel languageLevel); + @NotNull PsiClassType createType(@NotNull PsiClass resolve, @NotNull PsiSubstitutor substitutor, @Nullable LanguageLevel languageLevel); - @NotNull PsiClassType createType(@NotNull PsiClass resolve, @NotNull PsiSubstitutor substitutor, @NotNull LanguageLevel languageLevel, @NotNull PsiAnnotation[] annotations); + @NotNull PsiClassType createType(@NotNull PsiClass resolve, + @NotNull PsiSubstitutor substitutor, + @Nullable LanguageLevel languageLevel, + @NotNull PsiAnnotation[] annotations); /** * Creates a class type for the specified reference pointing to a class. diff --git a/java/java-psi-api/src/com/intellij/psi/PsiEllipsisType.java b/java/java-psi-api/src/com/intellij/psi/PsiEllipsisType.java index f295375f9403..498137e87709 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiEllipsisType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiEllipsisType.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. @@ -18,7 +18,6 @@ package com.intellij.psi; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; - /** * Represents the type of a variable arguments array passed as a method parameter. * @@ -36,7 +35,7 @@ public class PsiEllipsisType extends PsiArrayType { @Override public String getPresentableText() { - return StringUtil.joinOrNull(getComponentType().getPresentableText(), "..."); + return StringUtil.joinOrNull(getComponentType().getPresentableText(), getAnnotationsTextPrefix(false, true, true), "..."); } @Override @@ -46,13 +45,13 @@ public class PsiEllipsisType extends PsiArrayType { @Override public String getInternalCanonicalText() { - return StringUtil.joinOrNull(getComponentType().getInternalCanonicalText(), "..."); + return StringUtil.joinOrNull(getComponentType().getInternalCanonicalText(), getAnnotationsTextPrefix(true, true, true), "..."); } @Override public boolean equalsToText(String text) { - return text.endsWith("...") && getComponentType().equalsToText(text.substring(0, text.length() - 3)) - || super.equalsToText(text); + return text.endsWith("...") && getComponentType().equalsToText(text.substring(0, text.length() - 3)) || + super.equalsToText(text); } /** diff --git a/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java b/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java index 8c13cd7582c6..8bc973444dfd 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.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. @@ -169,10 +169,11 @@ public class PsiIntersectionType extends PsiType { @Override public String toString() { - String s = "PsiIntersectionType: "; - for (PsiType conjunct : myConjuncts) { - s += conjunct.getPresentableText() +", "; + StringBuilder sb = new StringBuilder("PsiIntersectionType: "); + for (int i = 0; i < myConjuncts.length; i++) { + if (i > 0) sb.append(", "); + sb.append(myConjuncts[i].getPresentableText()); } - return s; + return sb.toString(); } } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiJavaCodeReferenceElement.java b/java/java-psi-api/src/com/intellij/psi/PsiJavaCodeReferenceElement.java index b30a7cc7a09f..b2f80104449c 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiJavaCodeReferenceElement.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiJavaCodeReferenceElement.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. @@ -40,7 +40,7 @@ public interface PsiJavaCodeReferenceElement extends PsiJavaReference, PsiQualif * Returns the element representing the name of the referenced element. * * @return the element, or null if the reference element is not physical (for example, - * exists in compiled code). + * exists in compiled code). */ @Nullable PsiElement getReferenceNameElement(); @@ -74,5 +74,4 @@ public interface PsiJavaCodeReferenceElement extends PsiJavaReference, PsiQualif * @return the qualified text of the reference. */ String getQualifiedName(); - } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java index 1d0b2d750304..b051604ff656 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java @@ -191,6 +191,7 @@ public class PsiMethodReferenceUtil { } public static boolean isReceiverType(PsiType receiverType, @Nullable PsiClass containingClass, PsiSubstitutor psiSubstitutor) { + boolean arrayType = receiverType instanceof PsiArrayType; if (containingClass != null) { receiverType = getExpandedType(receiverType, containingClass); } @@ -198,7 +199,8 @@ public class PsiMethodReferenceUtil { final PsiClass receiverClass = resolveResult.getElement(); if (receiverClass != null && isReceiverType(receiverClass, containingClass)) { LOG.assertTrue(containingClass != null); - return resolveResult.getSubstitutor().equals(psiSubstitutor) || + return arrayType || + resolveResult.getSubstitutor().equals(psiSubstitutor) || emptyOrRaw(containingClass, psiSubstitutor) || emptyOrRaw(receiverClass, resolveResult.getSubstitutor()); } @@ -260,6 +262,9 @@ public class PsiMethodReferenceUtil { for (int i = 0; i < min; i++) { final PsiType type1 = GenericsUtil.eliminateWildcards(psiSubstitutor.substitute(signatureParameterTypes1[offset + i])); if (isVarargs && i == min - 1) { + if (!(signatureParameterTypes2[i] instanceof PsiArrayType)) { + return false; + } if (!TypeConversionUtil.isAssignable(((PsiArrayType)signatureParameterTypes2[i]).getComponentType(), type1) && !TypeConversionUtil.isAssignable(signatureParameterTypes2[i], type1)) { return false; diff --git a/java/java-psi-api/src/com/intellij/psi/PsiNewExpression.java b/java/java-psi-api/src/com/intellij/psi/PsiNewExpression.java index bebd2703a054..d8fa9a116251 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiNewExpression.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiNewExpression.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. @@ -37,7 +37,7 @@ public interface PsiNewExpression extends PsiCallExpression, PsiConstructorCall * an array creation expression. * * @return the array of expressions for the dimensions, or an empty array if the - * <code>new</code> expression is not an array creation expression. + * <code>new</code> expression is not an array creation expression. */ @NotNull PsiExpression[] getArrayDimensions(); @@ -47,7 +47,7 @@ public interface PsiNewExpression extends PsiCallExpression, PsiConstructorCall * an array creation expression. * * @return the array initializer expression, or null if the <code>new</code> - * expression is not an array creation expression or has no initializer. + * expression is not an array creation expression or has no initializer. */ @Nullable PsiArrayInitializerExpression getArrayInitializer(); @@ -63,8 +63,7 @@ public interface PsiNewExpression extends PsiCallExpression, PsiConstructorCall /** * Returns the anonymous class created by the <code>new</code> expression. * - * @return the anonymous class, or null if the expression does not create an - * anonymous class. + * @return the anonymous class, or null if the expression does not create an anonymous class. */ @Nullable PsiAnonymousClass getAnonymousClass(); @@ -75,5 +74,16 @@ public interface PsiNewExpression extends PsiCallExpression, PsiConstructorCall * * @return class reference, or null if the expression is incomplete. */ - @Nullable PsiJavaCodeReferenceElement getClassOrAnonymousClassReference(); + @Nullable + PsiJavaCodeReferenceElement getClassOrAnonymousClassReference(); + + /** + * For type-annotated array creation expressions returns subtype of getType(), + * to which an annotation belongs. + * + * @param annotation annotation to find the type for. + * @return annotated subtype or null, if annotation is incorrectly placed. + */ + @Nullable + PsiType getOwner(@NotNull PsiAnnotation annotation); } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiPrimitiveType.java b/java/java-psi-api/src/com/intellij/psi/PsiPrimitiveType.java index acbbfdfdb014..0a38c643799c 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiPrimitiveType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiPrimitiveType.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. @@ -53,7 +53,7 @@ public class PsiPrimitiveType extends PsiType { @Override public String getPresentableText() { - return myName; + return getAnnotationsTextPrefix(false, false, true) + myName; } @Override @@ -63,7 +63,7 @@ public class PsiPrimitiveType extends PsiType { @Override public String getInternalCanonicalText() { - return getAnnotationsTextPrefix() + getCanonicalText(); + return getAnnotationsTextPrefix(true, false, true) + myName; } /** diff --git a/java/java-psi-api/src/com/intellij/psi/PsiType.java b/java/java-psi-api/src/com/intellij/psi/PsiType.java index 5ed21bd5fdd0..cc78466a7e4a 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiType.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. @@ -17,8 +17,6 @@ package com.intellij.psi; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.TypeConversionUtil; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.Function; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,6 +39,7 @@ public abstract class PsiType implements PsiAnnotationOwner { public static final PsiType[] EMPTY_ARRAY = new PsiType[0]; private final PsiAnnotation[] myAnnotations; + protected PsiType(@NotNull PsiAnnotation[] annotations) { myAnnotations = annotations; } @@ -52,22 +51,31 @@ public abstract class PsiType implements PsiAnnotationOwner { public PsiArrayType createArrayType() { return new PsiArrayType(this); } + /** * Creates array type with this type as a component. */ @NotNull public PsiArrayType createArrayType(PsiAnnotation... annotations) { - return new PsiArrayType(this,annotations); + return new PsiArrayType(this, annotations); } /** - * @return text of this type that can be presented to user. + * @return text of the type that can be presented to a user (non-qualified references, with annotations). */ + @NonNls public abstract String getPresentableText(); + /** + * @return text of the type (fully-qualified references, no annotations). + */ @NonNls public abstract String getCanonicalText(); + /** + * @return text of the type (fully-qualified references, with annotations). + */ + @NonNls public abstract String getInternalCanonicalText(); /** @@ -109,7 +117,8 @@ public abstract class PsiType implements PsiAnnotationOwner { */ @NotNull public static PsiClassType getJavaLangObject(@NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) { - return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, resolveScope); + PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); + return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, resolveScope); } /** @@ -120,7 +129,8 @@ public abstract class PsiType implements PsiAnnotationOwner { * @return the class instance. */ public static PsiClassType getJavaLangClass(PsiManager manager, GlobalSearchScope resolveScope) { - return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeByFQClassName(CommonClassNames.JAVA_LANG_CLASS, resolveScope); + PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); + return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_CLASS, resolveScope); } /** @@ -131,7 +141,8 @@ public abstract class PsiType implements PsiAnnotationOwner { * @return the class instance. */ public static PsiClassType getJavaLangThrowable(PsiManager manager, GlobalSearchScope resolveScope) { - return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeByFQClassName(CommonClassNames.JAVA_LANG_THROWABLE, resolveScope); + PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); + return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_THROWABLE, resolveScope); } /** @@ -143,7 +154,8 @@ public abstract class PsiType implements PsiAnnotationOwner { */ @NotNull public static PsiClassType getJavaLangString(PsiManager manager, GlobalSearchScope resolveScope) { - return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeByFQClassName(CommonClassNames.JAVA_LANG_STRING, resolveScope); + PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); + return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_STRING, resolveScope); } /** @@ -154,7 +166,8 @@ public abstract class PsiType implements PsiAnnotationOwner { * @return the class instance. */ public static PsiClassType getJavaLangError(PsiManager manager, GlobalSearchScope resolveScope) { - return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeByFQClassName(CommonClassNames.JAVA_LANG_ERROR, resolveScope); + PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); + return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_ERROR, resolveScope); } /** @@ -165,7 +178,8 @@ public abstract class PsiType implements PsiAnnotationOwner { * @return the class instance. */ public static PsiClassType getJavaLangRuntimeException(PsiManager manager, GlobalSearchScope resolveScope) { - return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeByFQClassName(CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION, resolveScope); + PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); + return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION, resolveScope); } /** @@ -195,7 +209,7 @@ public abstract class PsiType implements PsiAnnotationOwner { * Returns the innermost component type for an array type. * * @return the innermost (non-array) component of the type, or <code>this</code> if the type is not - * an array type. + * an array type. */ @NotNull public final PsiType getDeepComponentType() { @@ -214,11 +228,6 @@ public abstract class PsiType implements PsiAnnotationOwner { @Nullable public abstract GlobalSearchScope getResolveScope(); - public String toString() { - //noinspection HardCodedStringLiteral - return "PsiType:" + getPresentableText(); - } - /** * Returns the list of superclass types for a class type. * @@ -250,14 +259,36 @@ public abstract class PsiType implements PsiAnnotationOwner { return getAnnotations(); } + /** @deprecated use {@link #getAnnotationsTextPrefix(boolean, boolean, boolean)} (to remove in IDEA 13) */ + @SuppressWarnings("UnusedDeclaration") protected String getAnnotationsTextPrefix() { + return getAnnotationsTextPrefix(false, false, true); + } + + @NotNull + protected String getAnnotationsTextPrefix(boolean qualified, boolean leadingSpace, boolean trailingSpace) { PsiAnnotation[] annotations = getAnnotations(); - return StringUtil.join(annotations, new Function<PsiAnnotation, String>() { - @Override - public String fun(PsiAnnotation annotation) { - return "@"+annotation.getQualifiedName(); + if (annotations.length == 0) return ""; + + StringBuilder sb = new StringBuilder(); + if (leadingSpace) sb.append(' '); + for (int i = 0; i < annotations.length; i++) { + if (i > 0) sb.append(' '); + PsiAnnotation annotation = annotations[i]; + if (qualified) { + sb.append('@').append(annotation.getQualifiedName()).append(annotation.getParameterList().getText()); + } + else { + sb.append(annotation.getText()); } - }, " ") + (annotations.length == 0 ? "" : " "); + } + if (trailingSpace) sb.append(' '); + return sb.toString(); } + @Override + public String toString() { + //noinspection HardCodedStringLiteral + return "PsiType:" + getPresentableText(); + } } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiTypeElement.java b/java/java-psi-api/src/com/intellij/psi/PsiTypeElement.java index 57e5381f6550..64a7b8066820 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiTypeElement.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiTypeElement.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. @@ -53,6 +53,7 @@ public interface PsiTypeElement extends PsiElement,PsiAnnotationOwner { @Nullable PsiJavaCodeReferenceElement getInnermostComponentReferenceElement(); + /** @deprecated equals to getType() (to remove in IDEA 13) */ PsiAnnotationOwner getOwner(PsiAnnotation annotation); PsiType getTypeNoResolve(@NotNull PsiElement context); diff --git a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java index cac0f3bc2c89..01726de99d24 100644 --- a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java +++ b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java @@ -151,6 +151,23 @@ public class MethodCandidateInfo extends CandidateInfo{ : PsiExpression.EMPTY_ARRAY); } + public PsiSubstitutor inferSubstitutorFromArgs(final ParameterTypeInferencePolicy policy, final PsiExpression[] arguments) { + if (myTypeArguments == null) { + return inferTypeArguments(policy, arguments); + } + else { + PsiSubstitutor incompleteSubstitutor = super.getSubstitutor(); + PsiMethod method = getElement(); + if (method != null) { + PsiTypeParameter[] typeParams = method.getTypeParameters(); + for (int i = 0; i < myTypeArguments.length && i < typeParams.length; i++) { + incompleteSubstitutor = incompleteSubstitutor.put(typeParams[i], myTypeArguments[i]); + } + } + return incompleteSubstitutor; + } + } + public PsiSubstitutor inferTypeArguments(final ParameterTypeInferencePolicy policy, final PsiExpression[] arguments) { Map<PsiElement, Pair<PsiMethod, PsiSubstitutor>> map = CURRENT_CANDIDATE.get(); if (map == null) { diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java index bba6f97400b8..49fbfec70d4c 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java @@ -722,9 +722,14 @@ public final class PsiUtil extends PsiUtilCore { @PsiModifier.ModifierConstant public static String getMaximumModifierForMember(final PsiClass aClass) { + return getMaximumModifierForMember(aClass, true); + } + + @PsiModifier.ModifierConstant + public static String getMaximumModifierForMember(final PsiClass aClass, boolean allowPublicAbstract) { String modifier = PsiModifier.PUBLIC; - if (aClass.hasModifierProperty(PsiModifier.ABSTRACT) && !aClass.isEnum()) { + if (!allowPublicAbstract && aClass.hasModifierProperty(PsiModifier.ABSTRACT) && !aClass.isEnum()) { modifier = PsiModifier.PROTECTED; } else if (aClass.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) { diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java index 09ef657b4c4a..672a01334f47 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java @@ -708,7 +708,7 @@ public class TypeConversionUtil { } if (left instanceof PsiCapturedWildcardType) { - return left.equals(right) || isAssignable(((PsiCapturedWildcardType)left).getLowerBound(), right, false); + return left.equals(right) || isAssignable(((PsiCapturedWildcardType)left).getLowerBound(), right, allowUncheckedConversion); } if (right instanceof PsiCapturedWildcardType) { return isAssignable(left, ((PsiCapturedWildcardType)right).getUpperBound(), allowUncheckedConversion); @@ -896,7 +896,9 @@ public class TypeConversionUtil { PsiSubstitutor leftSubstitutor = leftResult.getSubstitutor(); if (!leftClass.getManager().areElementsEquivalent(leftClass, rightClass)) { - if (!allowUncheckedConversion && PsiUtil.isRawSubstitutor(leftClass, leftSubstitutor) && !rightClass.hasTypeParameters() && !(rightClass instanceof PsiTypeParameter)) return false; + if (!allowUncheckedConversion && PsiUtil.isRawSubstitutor(leftClass, leftSubstitutor) && !rightClass.hasTypeParameters() && !(rightClass instanceof PsiTypeParameter)) { + return false; + } rightSubstitutor = getSuperClassSubstitutor(leftClass, rightClass, rightSubstitutor); rightClass = leftClass; } |