private static PsiType createType(PsiClass cls, PsiSubstitutor currentSubstitutor, int arrayDim) { final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(cls.getProject()).getElementFactory(); PsiType newType = elementFactory.createType(cls, currentSubstitutor); for (int i = 0; i < arrayDim; i++) { newType = newType.createArrayType(); } return newType; }
private void makeArray(PsiVariable variable) throws IncorrectOperationException { PsiType type = variable.getType(); PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory(); PsiType newType = type.createArrayType(); PsiDeclarationStatement variableDeclarationStatement; PsiExpression initializer = variable.getInitializer(); if (initializer == null) { String expression = "[1]"; while (type instanceof PsiArrayType) { expression += "[1]"; type = ((PsiArrayType) type).getComponentType(); } PsiExpression init = factory.createExpressionFromText("new " + type.getCanonicalText() + expression, variable); variableDeclarationStatement = factory.createVariableDeclarationStatement(variable.getName(), newType, init); } else { PsiExpression init = factory.createExpressionFromText("{ " + initializer.getText() + " }", variable); variableDeclarationStatement = factory.createVariableDeclarationStatement(variable.getName(), newType, init); } PsiVariable newVariable = (PsiVariable) variableDeclarationStatement.getDeclaredElements()[0]; PsiUtil.setModifierProperty(newVariable, PsiModifier.FINAL, true); PsiElement newExpression = factory.createExpressionFromText(variable.getName() + "[0]", variable); PsiElement outerCodeBlock = PsiUtil.getVariableCodeBlock(variable, null); if (outerCodeBlock == null) return; List<PsiReferenceExpression> outerReferences = new ArrayList<PsiReferenceExpression>(); collectReferences(outerCodeBlock, variable, outerReferences); replaceReferences(outerReferences, newExpression); variable.replace(newVariable); }
@NotNull private static PsiType getLeastUpperBound( PsiType type1, PsiType type2, Set<Pair<PsiType, PsiType>> compared, PsiManager manager) { if (type1 instanceof PsiCapturedWildcardType) { return getLeastUpperBound( ((PsiCapturedWildcardType) type1).getUpperBound(), type2, compared, manager); } if (type2 instanceof PsiCapturedWildcardType) { return getLeastUpperBound( type1, ((PsiCapturedWildcardType) type2).getUpperBound(), compared, manager); } if (type1 instanceof PsiWildcardType) { return getLeastUpperBound( ((PsiWildcardType) type1).getExtendsBound(), type2, compared, manager); } if (type2 instanceof PsiWildcardType) { return getLeastUpperBound( type1, ((PsiWildcardType) type2).getExtendsBound(), compared, manager); } if (type1 instanceof PsiArrayType && type2 instanceof PsiArrayType) { final PsiType componentType1 = ((PsiArrayType) type1).getComponentType(); final PsiType componentType2 = ((PsiArrayType) type2).getComponentType(); final PsiType componentType = getLeastUpperBound(componentType1, componentType2, compared, manager); if (componentType1 instanceof PsiPrimitiveType && componentType2 instanceof PsiPrimitiveType && componentType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) { final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); final GlobalSearchScope resolveScope = GlobalSearchScope.allScope(manager.getProject()); final PsiClassType cloneable = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_CLONEABLE, resolveScope); final PsiClassType serializable = factory.createTypeByFQClassName(CommonClassNames.JAVA_IO_SERIALIZABLE, resolveScope); return PsiIntersectionType.createIntersection(componentType, cloneable, serializable); } return componentType.createArrayType(); } if (type1 instanceof PsiIntersectionType) { Set<PsiType> newConjuncts = new LinkedHashSet<PsiType>(); final PsiType[] conjuncts = ((PsiIntersectionType) type1).getConjuncts(); for (PsiType type : conjuncts) { newConjuncts.add(getLeastUpperBound(type, type2, compared, manager)); } return PsiIntersectionType.createIntersection( newConjuncts.toArray(PsiType.createArray(newConjuncts.size()))); } if (type2 instanceof PsiIntersectionType) { return getLeastUpperBound(type2, type1, compared, manager); } if (type1 instanceof PsiClassType && type2 instanceof PsiClassType) { PsiClassType.ClassResolveResult classResolveResult1 = ((PsiClassType) type1).resolveGenerics(); PsiClassType.ClassResolveResult classResolveResult2 = ((PsiClassType) type2).resolveGenerics(); PsiClass aClass = classResolveResult1.getElement(); PsiClass bClass = classResolveResult2.getElement(); if (aClass == null || bClass == null) { return PsiType.getJavaLangObject(manager, GlobalSearchScope.allScope(manager.getProject())); } PsiClass[] supers = getLeastUpperClasses(aClass, bClass); if (supers.length == 0) { return PsiType.getJavaLangObject(manager, aClass.getResolveScope()); } PsiClassType[] conjuncts = new PsiClassType[supers.length]; for (int i = 0; i < supers.length; i++) { PsiClass aSuper = supers[i]; PsiSubstitutor subst1 = TypeConversionUtil.getSuperClassSubstitutor( aSuper, aClass, classResolveResult1.getSubstitutor()); PsiSubstitutor subst2 = TypeConversionUtil.getSuperClassSubstitutor( aSuper, bClass, classResolveResult2.getSubstitutor()); PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(aSuper)) { PsiType mapping1 = subst1.substitute(parameter); PsiType mapping2 = subst2.substitute(parameter); if (mapping1 != null && mapping2 != null) { substitutor = substitutor.put( parameter, getLeastContainingTypeArgument( mapping1, mapping2, compared, manager, type1.equals(mapping1) && type2.equals(mapping2) ? aSuper : null, parameter)); } else { substitutor = substitutor.put(parameter, null); } } conjuncts[i] = JavaPsiFacade.getInstance(manager.getProject()) .getElementFactory() .createType(aSuper, substitutor); } return PsiIntersectionType.createIntersection(conjuncts); } if (type2 instanceof PsiArrayType && !(type1 instanceof PsiArrayType)) { return getLeastUpperBound(type2, type1, compared, manager); } if (type1 instanceof PsiArrayType) { PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); GlobalSearchScope all = GlobalSearchScope.allScope(manager.getProject()); PsiClassType serializable = factory.createTypeByFQClassName(CommonClassNames.JAVA_IO_SERIALIZABLE, all); PsiClassType cloneable = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_CLONEABLE, all); PsiType arraySupers = PsiIntersectionType.createIntersection(serializable, cloneable); return getLeastUpperBound(arraySupers, type2, compared, manager); } return PsiType.getJavaLangObject(manager, GlobalSearchScope.allScope(manager.getProject())); }
@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; }