public static boolean haveConstructorsGenericsParameters(@NotNull final PsiClass psiClass) { for (PsiMethod method : psiClass.getConstructors()) { for (PsiParameter parameter : method.getParameterList().getParameters()) { final PsiType type = parameter.getType(); final Boolean accept = type.accept( new PsiTypeVisitor<Boolean>() { @Override public Boolean visitArrayType(PsiArrayType arrayType) { return arrayType.getComponentType().accept(this); } @Override public Boolean visitClassType(PsiClassType classType) { for (PsiType psiType : classType.getParameters()) { if (psiType != null) { final Boolean typaParamFound = psiType.accept(this); if (typaParamFound != null && typaParamFound) return true; } } return PsiUtil.resolveClassInType(classType) instanceof PsiTypeParameter; } @Override public Boolean visitWildcardType(PsiWildcardType wildcardType) { final PsiType bound = wildcardType.getBound(); if (bound == null) return false; return bound.accept(this); } }); if (accept != null && accept.booleanValue()) return true; } } return false; }
@NotNull public Type typeToType(@Nullable PsiType type) { if (type == null) return Type.EMPTY_TYPE; TypeVisitor typeVisitor = new TypeVisitor(this); type.accept(typeVisitor); return typeVisitor.getResult(); }
@Nullable @Override public Boolean visitWildcardType(PsiWildcardType wildcardType) { final PsiType bound = wildcardType.getBound(); if (bound != null) return bound.accept(this); return false; }
@Override public PsiType visitArrayType(PsiArrayType arrayType) { final PsiType componentType = arrayType.getComponentType(); final PsiType substitutedComponentType = componentType.accept(this); if (substitutedComponentType == null) return null; if (substitutedComponentType == componentType) return arrayType; // optimization return new PsiArrayType(substitutedComponentType); }
@Override public PsiType visitEllipsisType(PsiEllipsisType ellipsisType) { final PsiType componentType = ellipsisType.getComponentType(); final PsiType substitutedComponentType = componentType.accept(this); if (substitutedComponentType == null) return null; if (substitutedComponentType == componentType) return ellipsisType; // optimization return new PsiEllipsisType(substitutedComponentType); }
static boolean depends(PsiType type, TypeParamsChecker visitor, PsiTypeParameter... param2Check) { if (!visitor.startedInference()) return false; final Boolean accept = type.accept(visitor); if (param2Check.length > 0) { return visitor.used(param2Check); } return accept != null && accept.booleanValue(); }
@Override public PsiType substitute(PsiType type) { if (type == null) { //noinspection ConstantConditions return null; } PsiUtil.ensureValidType(type); PsiType substituted = type.accept(mySimpleSubstitutionVisitor); return correctExternalSubstitution(substituted, type); }
public Boolean visitClassType(final PsiClassType classType) { final PsiClass aClass = classType.resolve(); if (aClass instanceof PsiTypeParameter && myTypeParams.contains((PsiTypeParameter) aClass)) return true; final PsiType[] types = classType.getParameters(); for (final PsiType psiType : types) { if (psiType.accept(this).booleanValue()) return true; } return false; }
@Nullable public static HighlightInfo checkValidAnnotationType(final PsiTypeElement typeElement) { PsiType type = typeElement.getType(); if (type.accept(AnnotationReturnTypeVisitor.INSTANCE).booleanValue()) { return null; } String description = JavaErrorMessages.message("annotation.invalid.annotation.member.type"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(typeElement) .descriptionAndTooltip(description) .create(); }
@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 Binding reduceRecursive() { final BindingImpl binding = (BindingImpl) create(); for (final PsiTypeVariable var : myBoundVariables) { final int index = var.getIndex(); final PsiType type = myBindings.get(index); if (type != null) { class Verifier extends PsiExtendedTypeVisitor<Void> { boolean myFlag = false; @Override public Void visitTypeVariable(final PsiTypeVariable var) { if (var.getIndex() == index) { myFlag = true; } return null; } } final Verifier verifier = new Verifier(); type.accept(verifier); if (verifier.myFlag) { myBindings.put(index, Bottom.BOTTOM); binding.myBindings.put(index, Bottom.BOTTOM); } else { binding.myBindings.put(index, type); } } else { binding.myBindings.put(index, type); } } for (final PsiTypeVariable var : myBoundVariables) { final int index = var.getIndex(); final PsiType type = myBindings.get(index); if (type != null) { myBindings.put(index, binding.apply(type)); } } return this; }
@Override public Boolean visitClassType(PsiClassType classType) { boolean used = false; for (PsiType paramType : classType.getParameters()) { final Boolean paramAccepted = paramType.accept(this); used |= paramAccepted != null && paramAccepted.booleanValue(); } final PsiClass resolve = classType.resolve(); if (resolve instanceof PsiTypeParameter) { final PsiTypeParameter typeParameter = (PsiTypeParameter) resolve; if (check(typeParameter)) { myUsedTypeParams.add(typeParameter); return true; } } return used; }
private PsiType addBounds(PsiType substituted, final PsiTypeParameter typeParameter) { PsiElement captureContext = null; if (substituted instanceof PsiCapturedWildcardType) { final PsiCapturedWildcardType captured = (PsiCapturedWildcardType) substituted; substituted = captured.getWildcard(); captureContext = captured.getContext(); } if (substituted instanceof PsiWildcardType && !((PsiWildcardType) substituted).isSuper()) { PsiType originalBound = ((PsiWildcardType) substituted).getBound(); PsiManager manager = typeParameter.getManager(); final PsiType[] boundTypes = typeParameter.getExtendsListTypes(); for (PsiType boundType : boundTypes) { PsiType substitutedBoundType = boundType.accept(mySimpleSubstitutionVisitor); PsiWildcardType wildcardType = (PsiWildcardType) substituted; if (substitutedBoundType != null && !(substitutedBoundType instanceof PsiWildcardType) && !substitutedBoundType.equalsToText("java.lang.Object")) { if (originalBound == null || (!TypeConversionUtil.erasure(substitutedBoundType) .isAssignableFrom(TypeConversionUtil.erasure(originalBound)) && !TypeConversionUtil.erasure(substitutedBoundType) .isAssignableFrom( originalBound))) { // erasure is essential to avoid infinite recursion if (wildcardType.isExtends()) { final PsiType glb = GenericsUtil.getGreatestLowerBound(wildcardType.getBound(), substitutedBoundType); if (glb != null) { substituted = PsiWildcardType.createExtends(manager, glb); } } else { // unbounded substituted = PsiWildcardType.createExtends(manager, substitutedBoundType); } } } } } if (captureContext != null) { LOG.assertTrue(substituted instanceof PsiWildcardType); substituted = PsiCapturedWildcardType.create((PsiWildcardType) substituted, captureContext); } return substituted; }
private PsiType correctExternalSubstitution(PsiType substituted, final PsiType original) { if (original == null) return null; if (substituted == null) { return original.accept( new PsiTypeVisitor<PsiType>() { @Override public PsiType visitArrayType(PsiArrayType arrayType) { return new PsiArrayType(arrayType.getComponentType().accept(this)); } @Override public PsiType visitEllipsisType(PsiEllipsisType ellipsisType) { return new PsiEllipsisType(ellipsisType.getComponentType().accept(this)); } @Override public PsiType visitClassType(PsiClassType classType) { PsiClass aClass = classType.resolve(); if (aClass != null) { if (aClass instanceof PsiTypeParameter) { return rawTypeForTypeParameter((PsiTypeParameter) aClass); } else { return JavaPsiFacade.getInstance(aClass.getProject()) .getElementFactory() .createType(aClass); } } else { return classType; } } @Override public PsiType visitType(PsiType type) { LOG.error(type.getInternalCanonicalText()); return null; } }); } return substituted; }
@Override public PsiType visitWildcardType(PsiWildcardType wildcardType) { final PsiType bound = wildcardType.getBound(); if (bound == null) { return wildcardType; } else { final PsiType newBound = bound.accept(this); if (newBound == null) { return null; } assert newBound.isValid() : newBound.getClass() + "; " + bound.isValid(); if (newBound instanceof PsiWildcardType) { final PsiType newBoundBound = ((PsiWildcardType) newBound).getBound(); return !((PsiWildcardType) newBound).isBounded() ? PsiWildcardType.createUnbounded(wildcardType.getManager()) : rebound(wildcardType, newBoundBound); } return newBound == PsiType.NULL ? newBound : rebound(wildcardType, newBound); } }
@NotNull public TypeProjection transformToTypeProjection( @NotNull final PsiType javaType, @NotNull final TypeParameterDescriptor typeParameterDescriptor, @NotNull final TypeVariableResolver typeVariableByPsiResolver) { TypeProjection result = javaType.accept( new PsiTypeVisitor<TypeProjection>() { @Override public TypeProjection visitCapturedWildcardType( PsiCapturedWildcardType capturedWildcardType) { throw new UnsupportedOperationException(); // TODO } @Override public TypeProjection visitWildcardType(PsiWildcardType wildcardType) { if (!wildcardType.isBounded()) { return TypeUtils.makeStarProjection(typeParameterDescriptor); } Variance variance = wildcardType.isExtends() ? Variance.OUT_VARIANCE : Variance.IN_VARIANCE; PsiType bound = wildcardType.getBound(); assert bound != null; return new TypeProjection( variance, transformToType(bound, TypeUsage.UPPER_BOUND, typeVariableByPsiResolver)); } @Override public TypeProjection visitType(PsiType type) { return new TypeProjection( transformToType(type, TypeUsage.TYPE_ARGUMENT, typeVariableByPsiResolver)); } }); return result; }
@Override public PsiType visitWildcardType(PsiWildcardType wildcardType) { final PsiType bound = wildcardType.getBound(); if (bound == null) { return wildcardType; } else { final PsiType newBound = bound.accept(this); if (newBound == null) { return null; } if (newBound instanceof PsiWildcardType) { return handleBoundComposition(wildcardType, (PsiWildcardType) newBound); } if (newBound instanceof PsiCapturedWildcardType && wildcardType.isExtends() != ((PsiCapturedWildcardType) newBound).getWildcard().isExtends()) { return handleBoundComposition( wildcardType, ((PsiCapturedWildcardType) newBound).getWildcard()); } return PsiWildcardType.changeBound(wildcardType, newBound); } }
private void processMemberType( final PsiElement element, final TypeParameterSearcher parameterSearcher, final PsiClass psiClass, final PsiSubstitutor substitutor, final Map<PsiElement, Pair<PsiReference[], PsiType>> roots) { final PsiType elementType = TypeMigrationLabeler.getElementType(element); if (elementType != null && elementType.accept(parameterSearcher).booleanValue()) { final PsiType memberType = substitutor.substitute(elementType); prepareMethodsChangeSignature(psiClass, element, memberType); final List<PsiReference> refs = TypeMigrationLabeler.filterReferences( psiClass, ReferencesSearch.search(element, psiClass.getUseScope())); roots.put( element, Pair.create( myLabeler.markRootUsages( element, memberType, refs.toArray(new PsiReference[refs.size()])), memberType)); } }
@Nullable public static PsiType getVariableTypeByExpressionType( @Nullable PsiType type, final boolean openCaptured) { if (type == null) return null; if (type instanceof PsiCapturedWildcardType) { type = ((PsiCapturedWildcardType) type).getWildcard(); } PsiType transformed = type.accept( new PsiTypeVisitor<PsiType>() { @Override public PsiType visitArrayType(PsiArrayType arrayType) { PsiType componentType = arrayType.getComponentType(); PsiType type = componentType.accept(this); if (type == componentType) return arrayType; return type.createArrayType(); } @Override public PsiType visitType(PsiType type) { return type; } @Override public PsiType visitWildcardType(final PsiWildcardType wildcardType) { final PsiType bound = wildcardType.getBound(); PsiManager manager = wildcardType.getManager(); if (bound != null) { final PsiType acceptedBound = bound.accept(this); if (acceptedBound instanceof PsiWildcardType) { if (((PsiWildcardType) acceptedBound).isExtends() != wildcardType.isExtends()) return PsiWildcardType.createUnbounded(manager); return acceptedBound; } if (wildcardType.isExtends() && acceptedBound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return PsiWildcardType.createUnbounded(manager); if (acceptedBound.equals(bound)) return wildcardType; return wildcardType.isExtends() ? PsiWildcardType.createExtends(manager, acceptedBound) : PsiWildcardType.createSuper(manager, acceptedBound); } return wildcardType; } @Override public PsiType visitCapturedWildcardType( PsiCapturedWildcardType capturedWildcardType) { return openCaptured ? capturedWildcardType.getWildcard().accept(this) : capturedWildcardType; } @Override public PsiType visitClassType(PsiClassType classType) { PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics(); PsiClass aClass = resolveResult.getElement(); if (aClass == null) return classType; boolean toExtend = false; PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(aClass)) { PsiType typeArgument = resolveResult.getSubstitutor().substitute(typeParameter); if (typeArgument instanceof PsiCapturedWildcardType) toExtend = true; if (typeArgument instanceof PsiWildcardType && ((PsiWildcardType) typeArgument).getBound() instanceof PsiIntersectionType) { toExtend = true; } PsiType toPut; if (typeArgument == null) { toPut = null; } else { final PsiType accepted = typeArgument.accept(this); if (typeArgument instanceof PsiIntersectionType) { toPut = PsiWildcardType.createExtends(typeParameter.getManager(), accepted); } else { toPut = accepted; } } LOG.assertTrue(toPut == null || toPut.isValid(), toPut); substitutor = substitutor.put(typeParameter, toPut); } final PsiAnnotation[] applicableAnnotations = classType.getApplicableAnnotations(); if (substitutor == PsiSubstitutor.EMPTY && !toExtend && applicableAnnotations.length == 0 && !(aClass instanceof PsiTypeParameter)) return classType; PsiManager manager = aClass.getManager(); PsiType result = JavaPsiFacade.getInstance(manager.getProject()) .getElementFactory() .createType( aClass, substitutor, PsiUtil.getLanguageLevel(aClass), applicableAnnotations); if (toExtend) result = PsiWildcardType.createExtends(manager, result); return result; } }); PsiType componentType = transformed != null ? transformed.getDeepComponentType() : null; if (componentType instanceof PsiWildcardType) { componentType = ((PsiWildcardType) componentType).getExtendsBound(); int dims = transformed.getArrayDimensions(); for (int i = 0; i < dims; i++) componentType = componentType.createArrayType(); return componentType; } return transformed; }
public Boolean visitWildcardType(final PsiWildcardType wildcardType) { final PsiType bound = wildcardType.getBound(); return bound != null && bound.accept(this).booleanValue(); }
@Override public Boolean visitArrayType(PsiArrayType arrayType) { if (arrayType.getArrayDimensions() != 1) return Boolean.FALSE; PsiType componentType = arrayType.getComponentType(); return componentType.accept(this); }
private PsiType substituteInternal(PsiType type) { return type.accept(this); }
@NotNull public JetType transformToType( @NotNull PsiType javaType, @NotNull final TypeVariableResolver typeVariableResolver) { return javaType.accept( new PsiTypeVisitor<JetType>() { @Override public JetType visitClassType(PsiClassType classType) { PsiClassType.ClassResolveResult classResolveResult = classType.resolveGenerics(); PsiClass psiClass = classResolveResult.getElement(); if (psiClass == null) { return ErrorUtils.createErrorType( "Unresolved java class: " + classType.getPresentableText()); } if (psiClass instanceof PsiTypeParameter) { PsiTypeParameter typeParameter = (PsiTypeParameter) psiClass; TypeParameterDescriptor typeParameterDescriptor = typeVariableResolver.getTypeVariable(typeParameter.getName()); // return // TypeUtils.makeNullable(typeParameterDescriptor.getDefaultType()); return typeParameterDescriptor.getDefaultType(); } else { JetType jetAnalog = getClassTypesMap().get(psiClass.getQualifiedName()); if (jetAnalog != null) { return jetAnalog; } final JavaDescriptorResolver.ResolverClassData classData = resolver.resolveClassData(psiClass); if (classData == null) { return ErrorUtils.createErrorType( "Unresolve java class: " + classType.getPresentableText()); } List<TypeProjection> arguments = Lists.newArrayList(); if (classType.isRaw()) { List<TypeParameterDescriptor> parameters = classData.getClassDescriptor().getTypeConstructor().getParameters(); for (TypeParameterDescriptor parameter : parameters) { arguments.add(TypeUtils.makeStarProjection(parameter)); } } else { List<TypeParameterDescriptor> parameters = classData.getClassDescriptor().getTypeConstructor().getParameters(); PsiType[] psiArguments = classType.getParameters(); if (parameters.size() != psiArguments.length) { throw new IllegalStateException(); } for (int i = 0; i < parameters.size(); i++) { PsiType psiArgument = psiArguments[i]; TypeParameterDescriptor typeParameterDescriptor = parameters.get(i); arguments.add( transformToTypeProjection( psiArgument, typeParameterDescriptor, typeVariableResolver)); } } return new JetTypeImpl( Collections.<AnnotationDescriptor>emptyList(), classData.getClassDescriptor().getTypeConstructor(), true, arguments, classData.getClassDescriptor().getMemberScope(arguments)); } } @Override public JetType visitPrimitiveType(PsiPrimitiveType primitiveType) { String canonicalText = primitiveType.getCanonicalText(); JetType type = getPrimitiveTypesMap().get(canonicalText); assert type != null : canonicalText; return type; } @Override public JetType visitArrayType(PsiArrayType arrayType) { PsiType componentType = arrayType.getComponentType(); if (componentType instanceof PsiPrimitiveType) { JetType jetType = getPrimitiveTypesMap().get("[" + componentType.getCanonicalText()); if (jetType != null) return TypeUtils.makeNullable(jetType); } JetType type = transformToType(componentType, typeVariableResolver); return TypeUtils.makeNullable(standardLibrary.getArrayType(type)); } @Override public JetType visitType(PsiType type) { throw new UnsupportedOperationException( "Unsupported type: " + type.getPresentableText()); // TODO } }); }
@Override public PsiType substitute(PsiType type) { if (type == null) return null; PsiType substituted = type.accept(myAddingBoundsSubstitutionVisitor); return correctExternalSubstitution(substituted, type); }