@Override protected PsiClassType calcType() { final PsiElement classElement = myClass.getElement(); if (!(classElement instanceof PsiClass)) return null; Map<PsiTypeParameter, PsiType> resurrected = new HashMap<PsiTypeParameter, PsiType>(); final Set<Map.Entry<SmartPsiElementPointer, SmartTypePointer>> set = myMap.entrySet(); for (Map.Entry<SmartPsiElementPointer, SmartTypePointer> entry : set) { PsiElement element = entry.getKey().getElement(); if (element instanceof PsiTypeParameter) { SmartTypePointer typePointer = entry.getValue(); resurrected.put((PsiTypeParameter)element, typePointer == null ? null : typePointer.getType()); } } for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable((PsiClass)classElement)) { if (!resurrected.containsKey(typeParameter)) { resurrected.put(typeParameter, null); } } final PsiSubstitutor resurrectedSubstitutor = PsiSubstitutorImpl.createSubstitutor(resurrected); return new PsiImmediateClassType((PsiClass)classElement, resurrectedSubstitutor); }
@Override public PsiType getType() { PsiJavaCodeReferenceElement qualifier = getQualifier(); if (qualifier != null){ PsiElement qualifierResolve = qualifier.resolve(); if (qualifierResolve instanceof PsiClass) return new PsiImmediateClassType((PsiClass)qualifierResolve, PsiSubstitutor.EMPTY); return new PsiClassReferenceType(qualifier, null); } for(PsiElement scope = getContext(); scope != null; scope = scope.getContext()){ if (scope instanceof PsiClass){ PsiClass aClass = (PsiClass)scope; return new PsiImmediateClassType(aClass, PsiSubstitutor.EMPTY); } else if (scope instanceof PsiExpressionList && scope.getParent() instanceof PsiAnonymousClass){ scope = scope.getParent(); } else if (scope instanceof JavaCodeFragment){ PsiType fragmentThisType = ((JavaCodeFragment)scope).getThisType(); if (fragmentThisType != null) return fragmentThisType; } } return null; }
private static boolean canTypesBeEquivalent(PsiType type1, PsiType type2) { if (type1 == null || type2 == null) return false; if (!type2.isAssignableFrom(type1)) { if (type1 instanceof PsiImmediateClassType && type2 instanceof PsiImmediateClassType) { final PsiClass psiClass1 = ((PsiImmediateClassType)type1).resolve(); final PsiClass psiClass2 = ((PsiImmediateClassType)type2).resolve(); if (!(psiClass1 instanceof PsiAnonymousClass && psiClass2 instanceof PsiAnonymousClass && psiClass1.getManager().areElementsEquivalent(((PsiAnonymousClass)psiClass1).getBaseClassType().resolve(), ((PsiAnonymousClass)psiClass2).getBaseClassType().resolve()))) { return false; } } else { return false; } } return true; }
@NotNull @Override @SuppressWarnings("unchecked") public <Psi extends PsiElement> List<Psi> getAugments(@NotNull PsiElement element, @NotNull Class<Psi> type) { if(type == PsiMethod.class && element instanceof PsiClass && element.getUserData(FLAG) == Boolean.TRUE && ((PsiClass) element).isEnum()) { List<Psi> list = new ArrayList<Psi>(2); LightMethodBuilder valuesMethod = new LightMethodBuilder(element.getManager(), JavaLanguage.INSTANCE, VALUES_METHOD_NAME); valuesMethod.setContainingClass((PsiClass) element); valuesMethod.setMethodReturnType(new PsiArrayType(new PsiImmediateClassType((PsiClass)element, PsiSubstitutor.EMPTY))); valuesMethod.addModifiers(PsiModifier.PUBLIC, PsiModifier.STATIC); list.add((Psi) valuesMethod); LightMethodBuilder valueOfMethod = new LightMethodBuilder(element.getManager(), JavaLanguage.INSTANCE, VALUE_OF_METHOD_NAME); valueOfMethod.setContainingClass((PsiClass) element); valueOfMethod.setMethodReturnType(new PsiImmediateClassType((PsiClass) element, PsiSubstitutor.EMPTY)); valueOfMethod.addModifiers(PsiModifier.PUBLIC, PsiModifier.STATIC); valueOfMethod.addParameter("name", JavaClassNames.JAVA_LANG_STRING); valueOfMethod.addException(JavaClassNames.JAVA_LANG_ILLEGAL_ARGUMENT_EXCEPTION); list.add((Psi) valueOfMethod); return list; } return Collections.emptyList(); }
@Override public PsiType getType() { PsiJavaCodeReferenceElement qualifier = getQualifier(); if (qualifier != null){ PsiClass qualifierResolve = (PsiClass)qualifier.resolve(); if (qualifierResolve != null) return new PsiImmediateClassType(qualifierResolve, PsiSubstitutor.EMPTY); return new PsiClassReferenceType(qualifier, null); } for(PsiElement scope = getContext(); scope != null; scope = scope.getContext()){ if (scope instanceof PsiClass){ PsiClass aClass = (PsiClass)scope; return new PsiImmediateClassType(aClass, PsiSubstitutor.EMPTY); } else if (scope instanceof PsiExpressionList && scope.getParent() instanceof PsiAnonymousClass){ scope = scope.getParent(); } else if (scope instanceof JavaCodeFragment){ PsiType fragmentThisType = ((JavaCodeFragment)scope).getThisType(); if (fragmentThisType != null) return fragmentThisType; } } return null; }
private static boolean canTypesBeEquivalent(PsiType type1, PsiType type2) { if(type1 == null || type2 == null) { return false; } if(!type2.isAssignableFrom(type1)) { if(type1 instanceof PsiImmediateClassType && type2 instanceof PsiImmediateClassType) { final PsiClass psiClass1 = ((PsiImmediateClassType) type1).resolve(); final PsiClass psiClass2 = ((PsiImmediateClassType) type2).resolve(); if(!(psiClass1 instanceof PsiAnonymousClass && psiClass2 instanceof PsiAnonymousClass && psiClass1.getManager().areElementsEquivalent(((PsiAnonymousClass) psiClass1).getBaseClassType().resolve(), ((PsiAnonymousClass) psiClass2).getBaseClassType().resolve()))) { return false; } } else { return false; } } return true; }
@NotNull private static Query<PsiMember> createQuery(@NotNull PsiClass target, @NotNull PsiClass annClass) { PsiImmediateClassType type = new PsiImmediateClassType(target, PsiSubstitutor.EMPTY); return new FilteredQuery<>(AnnotatedMembersSearch.search(annClass), psiMember -> ReadAction.compute(() -> { if(psiMember instanceof PsiMethod && !psiMember.hasModifierProperty(PsiModifier.STATIC)) { PsiParameterList parameterList = ((PsiMethod) psiMember).getParameterList(); PsiParameter[] parameters = parameterList.getParameters(); if(parameters.length == 1 && parameters[0].getType().equals(type)) { return true; } } return false; })); }
@Nullable public <T extends PsiExpression> PsiType getType(@NotNull T expr, @NotNull Function<T, PsiType> f) { final boolean isOverloadCheck = MethodCandidateInfo.isOverloadCheck(); PsiType type = isOverloadCheck ? null : myCalculatedTypes.get(expr); if (type == null) { final RecursionGuard.StackStamp dStackStamp = PsiDiamondType.ourDiamondGuard.markStack(); type = f.fun(expr); if (!dStackStamp.mayCacheNow() || isOverloadCheck) { return type; } if (type == null) type = TypeConversionUtil.NULL_TYPE; myCalculatedTypes.put(expr, type); if (type instanceof PsiClassReferenceType) { // convert reference-based class type to the PsiImmediateClassType, since the reference may become invalid PsiClassType.ClassResolveResult result = ((PsiClassReferenceType)type).resolveGenerics(); PsiClass psiClass = result.getElement(); type = psiClass == null ? type // for type with unresolved reference, leave it in the cache // for clients still might be able to retrieve its getCanonicalText() from the reference text : new PsiImmediateClassType(psiClass, result.getSubstitutor(), ((PsiClassReferenceType)type).getLanguageLevel(), type.getAnnotations()); } } if (!type.isValid()) { if (expr.isValid()) { PsiJavaCodeReferenceElement refInside = type instanceof PsiClassReferenceType ? ((PsiClassReferenceType)type).getReference() : null; @NonNls String typeinfo = type + " (" + type.getClass() + ")" + (refInside == null ? "" : "; ref inside: "+refInside + " ("+refInside.getClass()+") valid:"+refInside.isValid()); LOG.error("Type is invalid: " + typeinfo + "; expr: '" + expr + "' (" + expr.getClass() + ") is valid"); } else { LOG.error("Expression: '"+expr+"' is invalid, must not be used for getType()"); } } return type == TypeConversionUtil.NULL_TYPE ? null : type; }
@NotNull public static PsiType getType(@NotNull PsiClassObjectAccessExpression classAccessExpression) { GlobalSearchScope resolveScope = classAccessExpression.getResolveScope(); PsiManager manager = classAccessExpression.getManager(); final PsiClass classClass = JavaPsiFacade.getInstance(manager.getProject()).findClass("java.lang.Class", resolveScope); if (classClass == null) { return new PsiClassReferenceType(new LightClassReference(manager, "Class", "java.lang.Class", resolveScope), null); } if (!PsiUtil.isLanguageLevel5OrHigher(classAccessExpression)) { //Raw java.lang.Class return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createType(classClass); } PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; PsiType operandType = classAccessExpression.getOperand().getType(); if (operandType instanceof PsiPrimitiveType && !PsiType.NULL.equals(operandType)) { if (PsiType.VOID.equals(operandType)) { operandType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory() .createTypeByFQClassName("java.lang.Void", classAccessExpression.getResolveScope()); } else { operandType = ((PsiPrimitiveType)operandType).getBoxedType(classAccessExpression); } } final PsiTypeParameter[] typeParameters = classClass.getTypeParameters(); if (typeParameters.length == 1) { substitutor = substitutor.put(typeParameters[0], operandType); } return new PsiImmediateClassType(classClass, substitutor); }
@Nullable private static String doCheckRepeatableAnnotation(@NotNull PsiAnnotation annotation) { PsiAnnotationOwner owner = annotation.getOwner(); if (!(owner instanceof PsiModifierList)) return null; PsiElement target = ((PsiModifierList)owner).getParent(); if (!(target instanceof PsiClass) || !((PsiClass)target).isAnnotationType()) return null; PsiClass container = getRepeatableContainer(annotation); if (container == null) return null; PsiMethod[] methods = container.findMethodsByName("value", false); if (methods.length == 0) { return JavaErrorMessages.message("annotation.container.no.value", container.getQualifiedName()); } if (methods.length == 1) { PsiType expected = new PsiImmediateClassType((PsiClass)target, PsiSubstitutor.EMPTY).createArrayType(); if (!expected.equals(methods[0].getReturnType())) { return JavaErrorMessages.message("annotation.container.bad.type", container.getQualifiedName(), JavaHighlightUtil.formatType(expected)); } } RetentionPolicy targetPolicy = getRetentionPolicy((PsiClass)target); if (targetPolicy != null) { RetentionPolicy containerPolicy = getRetentionPolicy(container); if (containerPolicy != null && targetPolicy.compareTo(containerPolicy) > 0) { return JavaErrorMessages.message("annotation.container.low.retention", container.getQualifiedName(), containerPolicy); } } Set<PsiAnnotation.TargetType> repeatableTargets = PsiImplUtil.getAnnotationTargets((PsiClass)target); if (repeatableTargets != null) { Set<PsiAnnotation.TargetType> containerTargets = PsiImplUtil.getAnnotationTargets(container); if (containerTargets != null && !repeatableTargets.containsAll(containerTargets)) { return JavaErrorMessages.message("annotation.container.wide.target", container.getQualifiedName()); } } return null; }
public void addVariable(String name, GrExpression expr) { PsiType type = expr.getType(); if (type instanceof GrClassReferenceType) { final PsiClassType.ClassResolveResult resolveResult = ((GrClassReferenceType)type).resolveGenerics(); final PsiClass psiClass = resolveResult.getElement(); type = psiClass == null ? null : new PsiImmediateClassType(psiClass, resolveResult.getSubstitutor()); } if (type != null) { myVariables.put(name, new GrLightVariable(getManager(), name, type, this)); } }
@Nullable public <T extends PsiExpression> PsiType getType(@NotNull T expr, @NotNull Function<T, PsiType> f) { PsiType type = getCachedType(expr); if (type == null) { final RecursionGuard.StackStamp dStackStamp = PsiDiamondType.ourDiamondGuard.markStack(); final RecursionGuard.StackStamp gStackStamp = PsiResolveHelper.ourGraphGuard.markStack(); type = f.fun(expr); if (!dStackStamp.mayCacheNow() || !gStackStamp.mayCacheNow()) { return type; } if (type == null) type = TypeConversionUtil.NULL_TYPE; Reference<PsiType> ref = new SoftReference<PsiType>(type); myCalculatedTypes.put(expr, ref); if (type instanceof PsiClassReferenceType) { // convert reference-based class type to the PsiImmediateClassType, since the reference may become invalid PsiClassType.ClassResolveResult result = ((PsiClassReferenceType)type).resolveGenerics(); PsiClass psiClass = result.getElement(); type = psiClass == null ? type // for type with unresolved reference, leave it in the cache // for clients still might be able to retrieve its getCanonicalText() from the reference text : new PsiImmediateClassType(psiClass, result.getSubstitutor(), ((PsiClassReferenceType)type).getLanguageLevel(), type.getAnnotations()); } } if (!type.isValid()) { if (expr.isValid()) { PsiJavaCodeReferenceElement refInside = type instanceof PsiClassReferenceType ? ((PsiClassReferenceType)type).getReference() : null; @NonNls String typeinfo = type + " (" + type.getClass() + ")" + (refInside == null ? "" : "; ref inside: "+refInside + " ("+refInside.getClass()+") valid:"+refInside.isValid()); LOG.error("Type is invalid: " + typeinfo + "; expr: '" + expr + "' (" + expr.getClass() + ") is valid"); } else { LOG.error("Expression: '"+expr+"' is invalid, must not be used for getType()"); } } return type == TypeConversionUtil.NULL_TYPE ? null : type; }
public static PsiType getType(@NotNull PsiClassObjectAccessExpression classAccessExpression) { GlobalSearchScope resolveScope = classAccessExpression.getResolveScope(); PsiManager manager = classAccessExpression.getManager(); final PsiClass classClass = JavaPsiFacade.getInstance(manager.getProject()).findClass("java.lang.Class", resolveScope); if (classClass == null) { return new PsiClassReferenceType(new LightClassReference(manager, "Class", "java.lang.Class", resolveScope), null); } if (!PsiUtil.isLanguageLevel5OrHigher(classAccessExpression)) { //Raw java.lang.Class return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createType(classClass); } PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; PsiType operandType = classAccessExpression.getOperand().getType(); if (operandType instanceof PsiPrimitiveType && !PsiType.NULL.equals(operandType)) { if (PsiType.VOID.equals(operandType)) { operandType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory() .createTypeByFQClassName("java.lang.Void", classAccessExpression.getResolveScope()); } else { operandType = ((PsiPrimitiveType)operandType).getBoxedType(classAccessExpression); } } final PsiTypeParameter[] typeParameters = classClass.getTypeParameters(); if (typeParameters.length == 1) { substitutor = substitutor.put(typeParameters[0], operandType); } return new PsiImmediateClassType(classClass, substitutor); }
@Nullable private static String doCheckRepeatableAnnotation(PsiAnnotation annotation) { PsiAnnotationOwner owner = annotation.getOwner(); if (!(owner instanceof PsiModifierList)) return null; PsiElement target = ((PsiModifierList)owner).getParent(); if (!(target instanceof PsiClass) || !((PsiClass)target).isAnnotationType()) return null; PsiClass container = getRepeatableContainer(annotation); if (container == null) return null; PsiMethod[] methods = container.findMethodsByName("value", false); if (methods.length == 0) { return JavaErrorMessages.message("annotation.container.no.value", container.getQualifiedName()); } if (methods.length == 1) { PsiType expected = new PsiImmediateClassType((PsiClass)target, PsiSubstitutor.EMPTY).createArrayType(); if (!expected.equals(methods[0].getReturnType())) { return JavaErrorMessages.message("annotation.container.bad.type", container.getQualifiedName(), JavaHighlightUtil .formatType(expected)); } } RetentionPolicy targetPolicy = getRetentionPolicy((PsiClass)target); if (targetPolicy != null) { RetentionPolicy containerPolicy = getRetentionPolicy(container); if (containerPolicy != null && targetPolicy.compareTo(containerPolicy) > 0) { return JavaErrorMessages.message("annotation.container.low.retention", container.getQualifiedName(), containerPolicy); } } Set<PsiAnnotation.TargetType> repeatableTargets = PsiImplUtil.getAnnotationTargets((PsiClass)target); if (repeatableTargets != null) { Set<PsiAnnotation.TargetType> containerTargets = PsiImplUtil.getAnnotationTargets(container); if (containerTargets != null && !repeatableTargets.containsAll(containerTargets)) { return JavaErrorMessages.message("annotation.container.wide.target", container.getQualifiedName()); } } return null; }
@NotNull private PsiType fromQName(String qName) { PsiClass aClass = JavaPsiFacade.getInstance(myNavTarget.getProject()).findClass(qName, myNavTarget.getResolveScope()); if(aClass == null) { return fromText(qName); } return new PsiImmediateClassType(aClass, PsiSubstitutor.EMPTY); }
@Override protected PsiClassType calcType() { final PsiElement classElement = myClass.getElement(); if(!(classElement instanceof PsiClass)) { return null; } Map<PsiTypeParameter, PsiType> resurrected = new HashMap<PsiTypeParameter, PsiType>(); final Set<Map.Entry<SmartPsiElementPointer, SmartTypePointer>> set = myMap.entrySet(); for(Map.Entry<SmartPsiElementPointer, SmartTypePointer> entry : set) { PsiElement element = entry.getKey().getElement(); if(element instanceof PsiTypeParameter) { SmartTypePointer typePointer = entry.getValue(); resurrected.put((PsiTypeParameter) element, typePointer == null ? null : typePointer.getType()); } } for(PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable((PsiClass) classElement)) { if(!resurrected.containsKey(typeParameter)) { resurrected.put(typeParameter, null); } } final PsiSubstitutor resurrectedSubstitutor = PsiSubstitutorImpl.createSubstitutor(resurrected); return new PsiImmediateClassType((PsiClass) classElement, resurrectedSubstitutor); }
@NotNull public static PsiType getType(@NotNull PsiClassObjectAccessExpression classAccessExpression) { GlobalSearchScope resolveScope = classAccessExpression.getResolveScope(); PsiManager manager = classAccessExpression.getManager(); final PsiClass classClass = JavaPsiFacade.getInstance(manager.getProject()).findClass("java.lang.Class", resolveScope); if(classClass == null) { return new PsiClassReferenceType(new LightClassReference(manager, "Class", "java.lang.Class", resolveScope), null); } if(!PsiUtil.isLanguageLevel5OrHigher(classAccessExpression)) { //Raw java.lang.Class return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createType(classClass); } PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; PsiType operandType = classAccessExpression.getOperand().getType(); if(operandType instanceof PsiPrimitiveType && !PsiType.NULL.equals(operandType)) { if(PsiType.VOID.equals(operandType)) { operandType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Void", classAccessExpression.getResolveScope()); } else { operandType = ((PsiPrimitiveType) operandType).getBoxedType(classAccessExpression); } } final PsiTypeParameter[] typeParameters = classClass.getTypeParameters(); if(typeParameters.length == 1) { substitutor = substitutor.put(typeParameters[0], operandType); } return new PsiImmediateClassType(classClass, substitutor); }
@Override public void fillRootObject(@NotNull PsiClass psiClass, @NotNull JsonObjectDescriptor jsonObjectDescriptor) { PropertyType type = toType(psiClass.getProject(), null, new PsiImmediateClassType(psiClass, PsiSubstitutor.EMPTY)); if(type != null && type.myValue instanceof JsonObjectDescriptor) { for(Map.Entry<String, JsonPropertyDescriptor> entry : ((JsonObjectDescriptor) type.myValue).getProperties().entrySet()) { jsonObjectDescriptor.getProperties().put(entry.getKey(), entry.getValue()); } } }
private static List<LookupElement> searchForLookups(final TargetType target, final Set<String> contextRelevantTypes, final ChainCompletionContext completionContext) { final Project project = completionContext.getProject(); final MethodsUsageIndexReader methodsUsageIndexReader = MethodsUsageIndexReader.getInstance(project); final List<MethodsChain> searchResult = searchChains(target, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE, completionContext, methodsUsageIndexReader); if (searchResult.size() < MAX_SEARCH_RESULT_SIZE) { if (!target.isArray()) { final List<MethodsChain> inheritorFilteredSearchResult = new SmartList<MethodsChain>(); final Processor<TargetType> consumer = new Processor<TargetType>() { @Override public boolean process(final TargetType targetType) { for (final MethodsChain chain : searchChains(targetType, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE, completionContext, methodsUsageIndexReader)) { boolean insert = true; for (final MethodsChain baseChain : searchResult) { final MethodsChain.CompareResult r = MethodsChain.compare(baseChain, chain, completionContext.getPsiManager()); if (r != MethodsChain.CompareResult.NOT_EQUAL) { insert = false; break; } } if (insert) { inheritorFilteredSearchResult.add(chain); } } searchResult.addAll(inheritorFilteredSearchResult); return searchResult.size() < MAX_SEARCH_RESULT_SIZE; } }; DirectClassInheritorsSearch.search(((PsiClassType)target.getPsiType()).resolve()).forEach(new Processor<PsiClass>() { @Override public boolean process(final PsiClass psiClass) { final String inheritorQName = psiClass.getQualifiedName(); if (inheritorQName == null) { return true; } return consumer.process(new TargetType(inheritorQName, false, new PsiImmediateClassType(psiClass, PsiSubstitutor.EMPTY))); } }); } } final List<MethodsChain> chains = searchResult.size() > MAX_CHAIN_SIZE ? chooseHead(searchResult) : searchResult; return MethodsChainLookupRangingHelper .chainsToWeightableLookupElements(filterTailAndGetSumLastMethodOccurrence(chains), completionContext); }
@NotNull @Override public PsiClassType createType(@NotNull PsiClass resolve, @NotNull PsiSubstitutor substitutor) { return new PsiImmediateClassType(resolve, substitutor); }
@NotNull @Override public PsiClassType createType(@NotNull PsiClass resolve, @NotNull PsiSubstitutor substitutor, @Nullable LanguageLevel languageLevel) { return new PsiImmediateClassType(resolve, substitutor, languageLevel); }
@NotNull @Override public PsiClassType createType(@NotNull PsiClass resolve, @NotNull PsiSubstitutor substitutor, @Nullable LanguageLevel languageLevel, @NotNull PsiAnnotation[] annotations) { return new PsiImmediateClassType(resolve, substitutor, languageLevel, annotations); }
@NotNull @Override public PsiClassType createType(@NotNull final PsiClass aClass) { return new PsiImmediateClassType(aClass, aClass instanceof PsiTypeParameter ? PsiSubstitutor.EMPTY : createRawSubstitutor(aClass)); }
@Nullable public <T extends PsiExpression> PsiType getType(@NotNull T expr, @NotNull Function<T, PsiType> f) { final boolean isOverloadCheck = MethodCandidateInfo.isOverloadCheck() || LambdaUtil.isLambdaParameterCheck(); final boolean polyExpression = PsiPolyExpressionUtil.isPolyExpression(expr); PsiType type = isOverloadCheck && polyExpression ? null : myCalculatedTypes.get(expr); if(type == null) { final RecursionGuard.StackStamp dStackStamp = PsiDiamondType.ourDiamondGuard.markStack(); type = f.fun(expr); if(!dStackStamp.mayCacheNow()) { return type; } //cache standalone expression types as they do not depend on the context if(isOverloadCheck && polyExpression) { return type; } if(type == null) { type = TypeConversionUtil.NULL_TYPE; } myCalculatedTypes.put(expr, type); if(type instanceof PsiClassReferenceType) { // convert reference-based class type to the PsiImmediateClassType, since the reference may become invalid PsiClassType.ClassResolveResult result = ((PsiClassReferenceType) type).resolveGenerics(); PsiClass psiClass = result.getElement(); type = psiClass == null ? type // for type with unresolved reference, leave it in the cache // for clients still might be able to retrieve its getCanonicalText() from the reference text : new PsiImmediateClassType(psiClass, result.getSubstitutor(), ((PsiClassReferenceType) type).getLanguageLevel(), type.getAnnotationProvider()); } } if(!type.isValid()) { if(expr.isValid()) { PsiJavaCodeReferenceElement refInside = type instanceof PsiClassReferenceType ? ((PsiClassReferenceType) type).getReference() : null; @NonNls String typeinfo = type + " (" + type.getClass() + ")" + (refInside == null ? "" : "; ref inside: " + refInside + " (" + refInside.getClass() + ") valid:" + refInside.isValid ()); LOG.error("Type is invalid: " + typeinfo + "; expr: '" + expr + "' (" + expr.getClass() + ") is valid"); } else { LOG.error("Expression: '" + expr + "' is invalid, must not be used for getType()"); } } return type == TypeConversionUtil.NULL_TYPE ? null : type; }
@Nullable private static String doCheckRepeatableAnnotation(@NotNull PsiAnnotation annotation) { PsiAnnotationOwner owner = annotation.getOwner(); if(!(owner instanceof PsiModifierList)) { return null; } PsiElement target = ((PsiModifierList) owner).getParent(); if(!(target instanceof PsiClass) || !((PsiClass) target).isAnnotationType()) { return null; } PsiClass container = getRepeatableContainer(annotation); if(container == null) { return null; } PsiMethod[] methods = container.findMethodsByName("value", false); if(methods.length == 0) { return JavaErrorMessages.message("annotation.container.no.value", container.getQualifiedName()); } if(methods.length == 1) { PsiType expected = new PsiImmediateClassType((PsiClass) target, PsiSubstitutor.EMPTY).createArrayType(); if(!expected.equals(methods[0].getReturnType())) { return JavaErrorMessages.message("annotation.container.bad.type", container.getQualifiedName(), JavaHighlightUtil.formatType(expected)); } } RetentionPolicy targetPolicy = getRetentionPolicy((PsiClass) target); if(targetPolicy != null) { RetentionPolicy containerPolicy = getRetentionPolicy(container); if(containerPolicy != null && targetPolicy.compareTo(containerPolicy) > 0) { return JavaErrorMessages.message("annotation.container.low.retention", container.getQualifiedName(), containerPolicy); } } Set<PsiAnnotation.TargetType> repeatableTargets = AnnotationTargetUtil.getAnnotationTargets((PsiClass) target); if(repeatableTargets != null) { Set<PsiAnnotation.TargetType> containerTargets = AnnotationTargetUtil.getAnnotationTargets(container); if(containerTargets != null && !repeatableTargets.containsAll(containerTargets)) { return JavaErrorMessages.message("annotation.container.wide.target", container.getQualifiedName()); } } return null; }