@Nullable private static PsiType getLeastUpperBoundForNumericType( @NotNull PsiType lType, @NotNull PsiType rType) { String lCanonical = lType.getCanonicalText(); String rCanonical = rType.getCanonicalText(); if (JAVA_LANG_FLOAT.equals(lCanonical)) lCanonical = JAVA_LANG_DOUBLE; if (JAVA_LANG_FLOAT.equals(rCanonical)) rCanonical = JAVA_LANG_DOUBLE; if (TYPE_TO_RANK.containsKey(lCanonical) && TYPE_TO_RANK.containsKey(rCanonical)) { return TYPE_TO_RANK.get(lCanonical) > TYPE_TO_RANK.get(rCanonical) ? lType : rType; } return null; }
@Nullable public static PsiType rawSecondGeneric(PsiType type, Project project) { if (!(type instanceof PsiClassType)) return null; final PsiClassType.ClassResolveResult result = ((PsiClassType) type).resolveGenerics(); final PsiClass element = result.getElement(); if (element == null) return null; final PsiType[] parameters = ((PsiClassType) type).getParameters(); boolean changed = false; for (int i = 0; i < parameters.length; i++) { PsiType parameter = parameters[i]; if (parameter == null) continue; final Ref<PsiType> newParam = new Ref<PsiType>(); parameter.accept( new PsiTypeVisitorEx<Object>() { @Nullable @Override public Object visitClassType(PsiClassType classType) { if (classType.getParameterCount() > 0) { newParam.set(classType.rawType()); } return null; } @Nullable @Override public Object visitCapturedWildcardType(PsiCapturedWildcardType capturedWildcardType) { newParam.set(capturedWildcardType.getWildcard().getBound()); return null; } @Nullable @Override public Object visitWildcardType(PsiWildcardType wildcardType) { newParam.set(wildcardType.getBound()); return null; } }); if (!newParam.isNull()) { changed = true; parameters[i] = newParam.get(); } } if (!changed) return null; return JavaPsiFacade.getElementFactory(project).createType(element, parameters); }
public static boolean isNumericType(@Nullable PsiType type) { if (type instanceof PsiClassType) { return TYPE_TO_RANK.contains(type.getCanonicalText()); } return type instanceof PsiPrimitiveType && TypeConversionUtil.isNumericType(type); }
private static PsiType genNewListBy(PsiType genericOwner, PsiManager manager) { PsiClass list = JavaPsiFacade.getInstance(manager.getProject()) .findClass(JAVA_UTIL_LIST, genericOwner.getResolveScope()); PsiElementFactory factory = JavaPsiFacade.getElementFactory(manager.getProject()); if (list == null) return factory.createTypeFromText(JAVA_UTIL_LIST, null); return factory.createType(list, PsiUtil.extractIterableTypeParameter(genericOwner, false)); }
private static PsiType genNewMapBy(PsiType genericOwner, PsiManager manager) { PsiClass map = JavaPsiFacade.getInstance(manager.getProject()) .findClass(JAVA_UTIL_MAP, genericOwner.getResolveScope()); PsiElementFactory factory = JavaPsiFacade.getElementFactory(manager.getProject()); if (map == null) return factory.createTypeFromText(JAVA_UTIL_MAP, null); final PsiType key = PsiUtil.substituteTypeParameter(genericOwner, JAVA_UTIL_MAP, 0, false); final PsiType value = PsiUtil.substituteTypeParameter(genericOwner, JAVA_UTIL_MAP, 1, false); return factory.createType(map, key, value); }
public static boolean isAssignableWithoutConversions( @Nullable PsiType lType, @Nullable PsiType rType, @NotNull PsiElement context) { if (lType == null || rType == null) return false; if (rType == PsiType.NULL) { return !(lType instanceof PsiPrimitiveType); } PsiManager manager = context.getManager(); GlobalSearchScope scope = context.getResolveScope(); if (rType instanceof GrTupleType && ((GrTupleType) rType).getComponentTypes().length == 0) { if (lType instanceof PsiArrayType || InheritanceUtil.isInheritor(lType, JAVA_UTIL_LIST) || InheritanceUtil.isInheritor(lType, JAVA_UTIL_SET)) { return true; } } if (isClassType(rType, GROOVY_LANG_GSTRING) && lType.equalsToText(JAVA_LANG_STRING)) { return true; } if (isNumericType(lType) && isNumericType(rType)) { lType = unboxPrimitiveTypeWrapper(lType); if (isClassType(lType, JAVA_MATH_BIG_DECIMAL)) lType = PsiType.DOUBLE; rType = unboxPrimitiveTypeWrapper(rType); if (isClassType(rType, JAVA_MATH_BIG_DECIMAL)) rType = PsiType.DOUBLE; } else { rType = boxPrimitiveType(rType, manager, scope); lType = boxPrimitiveType(lType, manager, scope); } if (rType instanceof GrMapType || rType instanceof GrTupleType) { Boolean result = isAssignableForNativeTypes(lType, (PsiClassType) rType, context); if (result != null && result.booleanValue()) return true; } if (TypeConversionUtil.isAssignable(lType, rType)) { return true; } return false; }
@Nullable public static PsiType getLeastUpperBound( @NotNull PsiType type1, @NotNull PsiType type2, PsiManager manager) { if (type1 instanceof GrTupleType && type2 instanceof GrTupleType) { GrTupleType tuple1 = (GrTupleType) type1; GrTupleType tuple2 = (GrTupleType) type2; PsiType[] components1 = tuple1.getComponentTypes(); PsiType[] components2 = tuple2.getComponentTypes(); if (components1.length == 0) return genNewListBy(type2, manager); if (components2.length == 0) return genNewListBy(type1, manager); PsiType[] components3 = new PsiType[Math.min(components1.length, components2.length)]; for (int i = 0; i < components3.length; i++) { PsiType c1 = components1[i]; PsiType c2 = components2[i]; if (c1 == null || c2 == null) { components3[i] = null; } else { components3[i] = getLeastUpperBound(c1, c2, manager); } } return new GrTupleType( components3, JavaPsiFacade.getInstance(manager.getProject()), tuple1.getScope().intersectWith(tuple2.getResolveScope())); } else if (checkEmptyListAndList(type1, type2)) { return genNewListBy(type2, manager); } else if (checkEmptyListAndList(type2, type1)) { return genNewListBy(type1, manager); } else if (type1 instanceof GrMapType && type2 instanceof GrMapType) { return GrMapType.merge(((GrMapType) type1), ((GrMapType) type2)); } else if (checkEmptyMapAndMap(type1, type2)) { return genNewMapBy(type2, manager); } else if (checkEmptyMapAndMap(type2, type1)) { return genNewMapBy(type1, manager); } else if (type1 instanceof GrClosureType && type2 instanceof GrClosureType) { GrClosureType clType1 = (GrClosureType) type1; GrClosureType clType2 = (GrClosureType) type2; GrSignature signature1 = clType1.getSignature(); GrSignature signature2 = clType2.getSignature(); if (signature1 instanceof GrClosureSignature && signature2 instanceof GrClosureSignature) { if (((GrClosureSignature) signature1).getParameterCount() == ((GrClosureSignature) signature2).getParameterCount()) { final GrClosureSignature signature = GrClosureSignatureImpl.getLeastUpperBound( ((GrClosureSignature) signature1), ((GrClosureSignature) signature2), manager); if (signature != null) { GlobalSearchScope scope = clType1.getResolveScope().intersectWith(clType2.getResolveScope()); final LanguageLevel languageLevel = ComparatorUtil.max(clType1.getLanguageLevel(), clType2.getLanguageLevel()); return GrClosureType.create( signature, scope, JavaPsiFacade.getInstance(manager.getProject()), languageLevel, true); } } } } else if (GroovyCommonClassNames.GROOVY_LANG_GSTRING.equals(type1.getCanonicalText()) && CommonClassNames.JAVA_LANG_STRING.equals(type2.getInternalCanonicalText())) { return type2; } else if (GroovyCommonClassNames.GROOVY_LANG_GSTRING.equals(type2.getCanonicalText()) && CommonClassNames.JAVA_LANG_STRING.equals(type1.getInternalCanonicalText())) { return type1; } final PsiType result = getLeastUpperBoundForNumericType(type1, type2); if (result != null) return result; return GenericsUtil.getLeastUpperBound(type1, type2, manager); }
@NotNull public static PsiClassType getJavaLangObject(@NotNull PsiElement context) { return PsiType.getJavaLangObject(context.getManager(), context.getResolveScope()); }
public static boolean isAssignable( @Nullable PsiType lType, @Nullable PsiType rType, @NotNull PsiElement context) { if (lType == null || rType == null) { return false; } if (rType instanceof PsiIntersectionType) { for (PsiType child : ((PsiIntersectionType) rType).getConjuncts()) { if (isAssignable(lType, child, context)) { return true; } } return false; } if (lType instanceof PsiIntersectionType) { for (PsiType child : ((PsiIntersectionType) lType).getConjuncts()) { if (!isAssignable(child, rType, context)) { return false; } } return true; } if (rType == PsiType.NULL) { return !(lType instanceof PsiPrimitiveType); } if (isNumericType(lType) && isNumericType(rType)) { return true; } if (isClassType(lType, JAVA_LANG_STRING)) { return true; } final PsiManager manager = context.getManager(); final GlobalSearchScope scope = context.getResolveScope(); if (lType instanceof PsiArrayType) { PsiType lComponentType = ((PsiArrayType) lType).getComponentType(); PsiType rComponentType = ClosureParameterEnhancer.findTypeForIteration(rType, context); if (rComponentType != null && isAssignable(lComponentType, rComponentType, context)) { return true; } } if (unboxPrimitiveTypeWrapper(lType) == PsiType.CHAR && (isClassType(rType, JAVA_LANG_STRING) || isClassType(rType, GROOVY_LANG_GSTRING))) { return true; } if (isAssignableByMethodCallConversion(lType, rType, context)) return true; lType = boxPrimitiveType(lType, manager, scope); rType = boxPrimitiveType(rType, manager, scope); if (lType.isAssignableFrom(rType)) { return true; } if (context instanceof GroovyPsiElement) { for (GrTypeConverter converter : GrTypeConverter.EP_NAME.getExtensions()) { if (!converter.isAllowedInMethodCall()) { Boolean result = converter.isConvertible(lType, rType, (GroovyPsiElement) context); if (result != null) { return result; } } } } return false; }