public static boolean proveArrayTypeDistinct(Project project, PsiArrayType type, PsiType bound) { final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); final GlobalSearchScope searchScope = GlobalSearchScope.allScope(project); final Set<PsiClass> possibleClasses = new HashSet<PsiClass>(); possibleClasses.add(facade.findClass(CommonClassNames.JAVA_IO_SERIALIZABLE, searchScope)); possibleClasses.add(facade.findClass(CommonClassNames.JAVA_LANG_CLONEABLE, searchScope)); possibleClasses.add(facade.findClass(CommonClassNames.JAVA_LANG_OBJECT, searchScope)); if (type.getArrayDimensions() == bound.getArrayDimensions()) { final PsiType componentType = type.getComponentType(); final PsiType boundComponentType = ((PsiArrayType) bound).getComponentType(); if (boundComponentType instanceof PsiClassType && componentType instanceof PsiClassType) { return proveExtendsBoundsDistinct( boundComponentType, componentType, ((PsiClassType) boundComponentType).resolve(), ((PsiClassType) componentType).resolve()); } else { return !bound.equals(type); } } else if (bound.getArrayDimensions() + 1 == type.getArrayDimensions() && bound.getDeepComponentType() instanceof PsiClassType) { return !possibleClasses.contains(((PsiClassType) bound.getDeepComponentType()).resolve()); } else if (bound.getArrayDimensions() == type.getArrayDimensions() + 1 && type.getDeepComponentType() instanceof PsiClassType) { return !possibleClasses.contains(((PsiClassType) type.getDeepComponentType()).resolve()); } else if (bound instanceof PsiClassType) { return !possibleClasses.contains(((PsiClassType) bound).resolve()); } else if (bound instanceof PsiWildcardType) { final PsiType boundBound = ((PsiWildcardType) bound).getBound(); return boundBound != null && !boundBound.equals(type); } return true; }
@Nullable private static String getTypeName(PsiType type, boolean withIndices) { type = type.getDeepComponentType(); if (type instanceof PsiClassType) { final PsiClassType classType = (PsiClassType) type; final String className = classType.getClassName(); if (className != null || !withIndices) return className; final PsiClass aClass = classType.resolve(); return aClass instanceof PsiAnonymousClass ? ((PsiAnonymousClass) aClass).getBaseClassType().getClassName() : null; } else if (type instanceof PsiPrimitiveType) { return type.getPresentableText(); } else if (type instanceof PsiWildcardType) { return getTypeName(((PsiWildcardType) type).getExtendsBound(), withIndices); } else if (type instanceof PsiIntersectionType) { return getTypeName(((PsiIntersectionType) type).getRepresentative(), withIndices); } else if (type instanceof PsiCapturedWildcardType) { return getTypeName(((PsiCapturedWildcardType) type).getWildcard(), withIndices); } else if (type instanceof PsiDisjunctionType) { return getTypeName(((PsiDisjunctionType) type).getLeastUpperBound(), withIndices); } else { return null; } }
public static boolean canBeMigrated(final PsiElement e) { if (e == null) { return false; } final PsiElement element = normalizeElement(e); if (!element.getManager().isInProject(element)) { return false; } final PsiType type = TypeMigrationLabeler.getElementType(element); if (type != null) { final PsiType elemenType = type instanceof PsiArrayType ? type.getDeepComponentType() : type; if (elemenType instanceof PsiPrimitiveType) { return !elemenType.equals(PsiType.VOID); } final PsiClass aClass = ((PsiClassType) elemenType).resolve(); return aClass != null /* && !aClass.hasTypeParameters()*/; } return false; }
@Nullable private static PsiClassType getComponentType(PsiType type) { type = type.getDeepComponentType(); if (type instanceof PsiClassType) return (PsiClassType) type; return null; }
@Nullable public static HighlightInfo checkMissingReturnStatement(PsiCodeBlock body, PsiType returnType) { if (body == null || returnType == null || PsiType.VOID.equals(returnType.getDeepComponentType())) { return null; } // do not compute constant expressions for if() statement condition // see JLS 14.20 Unreachable Statements try { ControlFlow controlFlow = getControlFlowNoConstantEvaluate(body); if (!ControlFlowUtil.returnPresent(controlFlow)) { PsiJavaToken rBrace = body.getRBrace(); PsiElement context = rBrace == null ? body.getLastChild() : rBrace; String message = JavaErrorMessages.message("missing.return.statement"); HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(context) .descriptionAndTooltip(message) .create(); PsiElement parent = body.getParent(); if (parent instanceof PsiMethod) { PsiMethod method = (PsiMethod) parent; QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createAddReturnFix(method)); QuickFixAction.registerQuickFixAction( info, QUICK_FIX_FACTORY.createMethodReturnFix(method, PsiType.VOID, true)); } return info; } } catch (AnalysisCanceledException ignored) { } return null; }
@Override public String handleEmptyLookup( @NotNull final CompletionParameters parameters, final Editor editor) { if (!(parameters.getOriginalFile() instanceof PsiJavaFile)) return null; final String ad = advertise(parameters); final String suffix = ad == null ? "" : "; " + StringUtil.decapitalize(ad); if (parameters.getCompletionType() == CompletionType.SMART) { if (!ApplicationManager.getApplication().isUnitTestMode()) { final Project project = parameters.getPosition().getProject(); final PsiFile file = parameters.getOriginalFile(); PsiExpression expression = PsiTreeUtil.getContextOfType(parameters.getPosition(), PsiExpression.class, true); if (expression != null && expression.getParent() instanceof PsiExpressionList) { int lbraceOffset = expression.getParent().getTextRange().getStartOffset(); ShowParameterInfoHandler.invoke(project, editor, file, lbraceOffset, null); } if (expression instanceof PsiLiteralExpression) { return LangBundle.message("completion.no.suggestions") + suffix; } if (expression instanceof PsiInstanceOfExpression) { final PsiInstanceOfExpression instanceOfExpression = (PsiInstanceOfExpression) expression; if (PsiTreeUtil.isAncestor( instanceOfExpression.getCheckType(), parameters.getPosition(), false)) { return LangBundle.message("completion.no.suggestions") + suffix; } } } final Set<PsiType> expectedTypes = JavaCompletionUtil.getExpectedTypes(parameters); if (expectedTypes != null) { PsiType type = expectedTypes.size() == 1 ? expectedTypes.iterator().next() : null; if (type != null) { final PsiType deepComponentType = type.getDeepComponentType(); if (deepComponentType instanceof PsiClassType) { if (((PsiClassType) deepComponentType).resolve() != null) { return CompletionBundle.message( "completion.no.suggestions.of.type", type.getPresentableText()) + suffix; } return CompletionBundle.message("completion.unknown.type", type.getPresentableText()) + suffix; } if (!PsiType.NULL.equals(type)) { return CompletionBundle.message( "completion.no.suggestions.of.type", type.getPresentableText()) + suffix; } } } } return LangBundle.message("completion.no.suggestions") + suffix; }
@Override public void visitForStatement(@NotNull PsiForStatement statement) { super.visitForStatement(statement); final PsiStatement initialization = statement.getInitialization(); if (!(initialization instanceof PsiDeclarationStatement)) { return; } final PsiDeclarationStatement declaration = (PsiDeclarationStatement) initialization; final PsiElement[] declaredElements = declaration.getDeclaredElements(); if (declaredElements.length != 1) { return; } final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiLocalVariable)) { return; } final PsiLocalVariable variable = (PsiLocalVariable) declaredElement; final PsiExpression initialValue = variable.getInitializer(); if (initialValue == null) { return; } final PsiExpression condition = statement.getCondition(); if (!ExpressionUtils.isVariableLessThanComparison(condition, variable)) { return; } final PsiStatement update = statement.getUpdate(); if (!VariableAccessUtils.variableIsIncremented(variable, update)) { return; } final PsiArrayAccessExpression arrayAccessExpression = getArrayAccessExpression(statement); if (arrayAccessExpression == null) { return; } final PsiExpression arrayExpression = arrayAccessExpression.getArrayExpression(); final PsiType type = arrayExpression.getType(); if (!(type instanceof PsiArrayType) || type.getDeepComponentType() instanceof PsiPrimitiveType) { return; } final PsiStatement body = statement.getBody(); if (!bodyIsArrayToCollectionCopy(body, variable, true)) { return; } registerStatementError(statement); }
@Override public void addTypeReference(PsiElement psiElement, PsiType psiType, RefManager refManager) { RefClass ownerClass = getOwnerClass(refManager, psiElement); if (ownerClass != null) { psiType = psiType.getDeepComponentType(); if (psiType instanceof PsiClassType) { PsiClass psiClass = PsiUtil.resolveClassInType(psiType); if (psiClass != null && refManager.belongsToScope(psiClass)) { RefClassImpl refClass = (RefClassImpl) refManager.getReference(psiClass); if (refClass != null) { refClass.addTypeReference(ownerClass); } } } } }
private static void generateNamesForArrayType( PsiType type, Set<String> possibleNames, NameValidator validator) { int arrayDim = type.getArrayDimensions(); if (arrayDim == 0) return; PsiType deepType = type.getDeepComponentType(); String candidateName = cleanTypeName(deepType.getPresentableText()); if (deepType instanceof PsiClassType) { PsiClass clazz = ((PsiClassType) deepType).resolve(); if (clazz == null) return; candidateName = GroovyNamesUtil.fromLowerLetter(clazz.getName()); } candidateName = StringUtil.pluralize(GroovyNamesUtil.fromLowerLetter(candidateName)); generateCamelNames(possibleNames, validator, candidateName); ArrayList<String> camelizedName = GroovyNamesUtil.camelizeString(candidateName); candidateName = camelizedName.get(camelizedName.size() - 1); candidateName = "arrayOf" + fromUpperLetter(candidateName); possibleNames.add(validator.validateName(candidateName, true)); }
private static void changeNewOperatorType( PsiNewExpression originalExpression, PsiType toType, final Editor editor) throws IncorrectOperationException { PsiNewExpression newExpression; PsiElementFactory factory = JavaPsiFacade.getInstance(originalExpression.getProject()).getElementFactory(); int caretOffset; TextRange selection; if (toType instanceof PsiArrayType) { final PsiExpression[] originalExpressionArrayDimensions = originalExpression.getArrayDimensions(); caretOffset = 0; @NonNls String text = "new " + toType.getDeepComponentType().getCanonicalText() + "["; if (originalExpressionArrayDimensions.length > 0) { text += originalExpressionArrayDimensions[0].getText(); } else { text += "0"; caretOffset = -2; } text += "]"; for (int i = 1; i < toType.getArrayDimensions(); i++) { text += "["; String arrayDimension = ""; if (originalExpressionArrayDimensions.length > i) { arrayDimension = originalExpressionArrayDimensions[i].getText(); text += arrayDimension; } text += "]"; if (caretOffset < 0) { caretOffset -= arrayDimension.length() + 2; } } newExpression = (PsiNewExpression) factory.createExpressionFromText(text, originalExpression); if (caretOffset < 0) { selection = new TextRange(caretOffset, caretOffset + 1); } else { selection = null; } } else { final PsiAnonymousClass anonymousClass = originalExpression.getAnonymousClass(); newExpression = (PsiNewExpression) factory.createExpressionFromText( "new " + toType.getCanonicalText() + "()" + (anonymousClass != null ? "{}" : ""), originalExpression); PsiExpressionList argumentList = originalExpression.getArgumentList(); if (argumentList == null) return; newExpression.getArgumentList().replace(argumentList); if (anonymousClass == null) { // just to prevent useless inference if (PsiDiamondTypeUtil.canCollapseToDiamond(newExpression, originalExpression, toType)) { final PsiElement paramList = PsiDiamondTypeUtil.replaceExplicitWithDiamond( newExpression.getClassOrAnonymousClassReference().getParameterList()); newExpression = PsiTreeUtil.getParentOfType(paramList, PsiNewExpression.class); } } if (anonymousClass != null) { final PsiAnonymousClass newAnonymousClass = (PsiAnonymousClass) newExpression.getAnonymousClass().replace(anonymousClass); final PsiClass aClass = PsiUtil.resolveClassInType(toType); assert aClass != null; newAnonymousClass .getBaseClassReference() .replace(factory.createClassReferenceElement(aClass)); } selection = null; caretOffset = -1; } PsiElement element = originalExpression.replace(newExpression); editor.getCaretModel().moveToOffset(element.getTextRange().getEndOffset() + caretOffset); editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); if (selection != null) { selection = selection.shiftRight(element.getTextRange().getEndOffset()); editor.getSelectionModel().setSelection(selection.getStartOffset(), selection.getEndOffset()); } }
public static void processSubTypes( PsiType psiType, final PsiElement context, boolean getRawSubtypes, @NotNull final PrefixMatcher matcher, Consumer<PsiType> consumer) { int arrayDim = psiType.getArrayDimensions(); psiType = psiType.getDeepComponentType(); if (!(psiType instanceof PsiClassType)) return; final Condition<String> shortNameCondition = new Condition<String>() { @Override public boolean value(String s) { return matcher.prefixMatches(s); } }; final PsiClassType baseType = (PsiClassType) psiType; final PsiClassType.ClassResolveResult baseResult = ApplicationManager.getApplication() .runReadAction( new Computable<PsiClassType.ClassResolveResult>() { @Override public PsiClassType.ClassResolveResult compute() { return JavaCompletionUtil.originalize(baseType).resolveGenerics(); } }); final PsiClass baseClass = baseResult.getElement(); final PsiSubstitutor baseSubstitutor = baseResult.getSubstitutor(); if (baseClass == null) return; final GlobalSearchScope scope = ApplicationManager.getApplication() .runReadAction( new Computable<GlobalSearchScope>() { @Override public GlobalSearchScope compute() { return context.getResolveScope(); } }); final Processor<PsiClass> inheritorsProcessor = createInheritorsProcessor( context, baseType, arrayDim, getRawSubtypes, consumer, baseClass, baseSubstitutor); if (matcher.getPrefix().length() > 2) { AllClassesGetter.processJavaClasses( matcher, context.getProject(), scope, new Processor<PsiClass>() { @Override public boolean process(PsiClass psiClass) { if (psiClass.isInheritor(baseClass, true)) { return inheritorsProcessor.process(psiClass); } return true; } }); } else { final Query<PsiClass> baseQuery = ClassInheritorsSearch.search( new ClassInheritorsSearch.SearchParameters( baseClass, scope, true, false, false, shortNameCondition)); final Query<PsiClass> query = new FilteredQuery<PsiClass>( baseQuery, new Condition<PsiClass>() { @Override public boolean value(final PsiClass psiClass) { return !(psiClass instanceof PsiTypeParameter); } }); query.forEach(inheritorsProcessor); } }
@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; }