private static Map<String, PsiType> getCompatibleTypeNames( @NotNull PsiType type, @Nullable PsiType min, PsiManager manager, GlobalSearchScope scope) { if (type instanceof PsiDisjunctionType) type = ((PsiDisjunctionType) type).getLeastUpperBound(); // if initial type is not assignable to min type we don't take into consideration min type. if (min != null && !TypesUtil.isAssignable(min, type, manager, scope)) { min = null; } Map<String, PsiType> map = new LinkedHashMap<String, PsiType>(); final PsiPrimitiveType unboxed = PsiPrimitiveType.getUnboxedType(type); if (unboxed != null) type = unboxed; final Set<PsiType> set = new LinkedHashSet<PsiType>(); set.add(type); while (!set.isEmpty()) { PsiType cur = set.iterator().next(); set.remove(cur); if (!map.containsValue(cur) && (min == null || TypesUtil.isAssignable(min, cur, manager, scope))) { if (isPartiallySubstituted(cur)) { LOG.assertTrue(cur instanceof PsiClassType); PsiClassType rawType = ((PsiClassType) cur).rawType(); map.put(rawType.getPresentableText(), rawType); } else { map.put(cur.getPresentableText(), cur); } for (PsiType superType : cur.getSuperTypes()) { if (!map.containsValue(superType)) { set.add(superType); } } } } return map; }
@Override public PsiType fun(GrMethodBaseImpl method) { PsiType nominal = method.getNominalType(); if (nominal != null) { if (!(nominal instanceof PsiClassType && hasTypeParametersToInfer((PsiClassType) nominal))) { return nominal; } } if (!GppTypeConverter.hasTypedContext(method)) { LOG.assertTrue(method.isValid(), "invalid method"); final GrOpenBlock block = method.getBlock(); if (block != null) { LOG.assertTrue(block.isValid(), "invalid code block"); PsiType inferred = GroovyPsiManager.inferType(method, new MethodTypeInferencer(block)); if (inferred != null) { if (nominal == null || nominal.isAssignableFrom(inferred)) { return inferred; } } } } if (nominal != null) { return nominal; } return TypesUtil.getJavaLangObject(method); }
@Override @NotNull protected String buildErrorString(Object... infos) { final PsiType expectedType = (PsiType) infos[0]; final String typeText = expectedType.getPresentableText(); return InspectionGadgetsBundle.message("overly.strong.type.cast.problem.descriptor", typeText); }
private void reportNullableReturns( DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set<PsiElement> reportedAnchors, @NotNull PsiElement block) { final PsiMethod method = getScopeMethod(block); if (method == null || NullableStuffInspectionBase.isNullableNotInferred(method, true)) return; boolean notNullRequired = NullableNotNullManager.isNotNull(method); if (!notNullRequired && !SUGGEST_NULLABLE_ANNOTATIONS) return; PsiType returnType = method.getReturnType(); // no warnings in void lambdas, where the expression is not returned anyway if (block instanceof PsiExpression && block.getParent() instanceof PsiLambdaExpression && returnType == PsiType.VOID) return; // no warnings for Void methods, where only null can be possibly returned if (returnType == null || returnType.equalsToText(CommonClassNames.JAVA_LANG_VOID)) return; for (PsiElement statement : visitor.getProblems(NullabilityProblem.nullableReturn)) { assert statement instanceof PsiExpression; final PsiExpression expr = (PsiExpression) statement; if (!reportedAnchors.add(expr)) continue; if (notNullRequired) { final String text = isNullLiteralExpression(expr) ? InspectionsBundle.message("dataflow.message.return.null.from.notnull") : InspectionsBundle.message("dataflow.message.return.nullable.from.notnull"); holder.registerProblem(expr, text); } else if (AnnotationUtil.isAnnotatingApplicable(statement)) { final NullableNotNullManager manager = NullableNotNullManager.getInstance(expr.getProject()); final String defaultNullable = manager.getDefaultNullable(); final String presentableNullable = StringUtil.getShortName(defaultNullable); final String text = isNullLiteralExpression(expr) ? InspectionsBundle.message( "dataflow.message.return.null.from.notnullable", presentableNullable) : InspectionsBundle.message( "dataflow.message.return.nullable.from.notnullable", presentableNullable); final LocalQuickFix[] fixes = PsiTreeUtil.getParentOfType(expr, PsiMethod.class, PsiLambdaExpression.class) instanceof PsiLambdaExpression ? LocalQuickFix.EMPTY_ARRAY : new LocalQuickFix[] { new AnnotateMethodFix( defaultNullable, ArrayUtil.toStringArray(manager.getNotNulls())) { @Override public int shouldAnnotateBaseMethod( PsiMethod method, PsiMethod superMethod, Project project) { return 1; } } }; holder.registerProblem(expr, text, fixes); } } }
@NotNull @Override public PsiType getType() { PsiType type = super.getType(); if (type instanceof PsiClassType && ((PsiClassType) type).resolve() == null) { return PsiType.getJavaLangObject(myManager, getResolveScope()); } return type; }
private void checkExpression(@NotNull PsiExpression expression) { if (expression.getParent() instanceof PsiParenthesizedExpression) { return; } final PsiType expressionType = expression.getType(); if (expressionType == null || expressionType.equals(PsiType.VOID) || !TypeConversionUtil.isPrimitiveAndNotNull(expressionType)) { return; } final PsiPrimitiveType primitiveType = (PsiPrimitiveType) expressionType; final PsiClassType boxedType = primitiveType.getBoxedType(expression); if (boxedType == null) { return; } final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, false); if (expectedType == null || ClassUtils.isPrimitive(expectedType)) { return; } if (!expectedType.isAssignableFrom(boxedType)) { // JLS 5.2 Assignment Conversion // check if a narrowing primitive conversion is applicable if (!(expectedType instanceof PsiClassType) || !PsiUtil.isConstantExpression(expression)) { return; } final PsiClassType classType = (PsiClassType) expectedType; final String className = classType.getCanonicalText(); if (!convertableBoxedClassNames.contains(className)) { return; } if (!PsiType.BYTE.equals(expressionType) && !PsiType.CHAR.equals(expressionType) && !PsiType.SHORT.equals(expressionType) && !PsiType.INT.equals(expressionType)) { return; } } if (ignoreAddedToCollection && isAddedToCollection(expression)) { return; } registerError(expression); }
@Override public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { final PsiElement castTypeElement = descriptor.getPsiElement(); final PsiTypeCastExpression expression = (PsiTypeCastExpression) castTypeElement.getParent(); if (expression == null) { return; } final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, true); if (expectedType == null) { return; } final PsiExpression operand = expression.getOperand(); if (operand == null) { return; } @NonNls final String newExpression = '(' + expectedType.getCanonicalText() + ')' + operand.getText(); replaceExpressionAndShorten(expression, newExpression); }
private boolean isCheckedType(PsiType type) { if (!(type instanceof PsiClassType)) return false; StringTokenizer tokenizer = new StringTokenizer(CHECKED_CLASSES, ";"); while (tokenizer.hasMoreTokens()) { String className = tokenizer.nextToken(); if (type.equalsToText(className)) return true; } return false; }
@Override @NotNull public Map<String, NamedArgumentDescriptor> getNamedParameters() { final GrMethodStub stub = getStub(); if (stub != null) { String[] namedParameters = stub.getNamedParameters(); if (namedParameters.length == 0) return Collections.emptyMap(); Map<String, NamedArgumentDescriptor> result = ContainerUtil.newHashMap(); for (String parameter : namedParameters) { result.put(parameter, GrNamedArgumentSearchVisitor.CODE_NAMED_ARGUMENTS_DESCR); } return result; } GrOpenBlock body = getBlock(); if (body == null) return Collections.emptyMap(); GrParameter[] parameters = getParameters(); if (parameters.length == 0) return Collections.emptyMap(); GrParameter firstParameter = parameters[0]; PsiType type = firstParameter.getTypeGroovy(); GrTypeElement typeElement = firstParameter.getTypeElementGroovy(); // equalsToText can't be called here because of stub creating if (type != null && typeElement != null && type.getPresentableText() != null && !type.getPresentableText().endsWith("Map")) { return Collections.emptyMap(); } GrNamedArgumentSearchVisitor visitor = new GrNamedArgumentSearchVisitor(firstParameter.getNameIdentifierGroovy().getText()); body.accept(visitor); return visitor.getResult(); }
private boolean hasOnlyMain(PsiClass aClass) { final PsiMethod[] methods = aClass.getMethods(); if (methods.length == 0) { return false; } for (PsiMethod method : methods) { if (method.isConstructor()) { continue; } if (!method.hasModifierProperty(PsiModifier.STATIC)) { return false; } if (method.hasModifierProperty(PsiModifier.PRIVATE)) { continue; } if (!method.hasModifierProperty(PsiModifier.PUBLIC)) { return false; } final String name = method.getName(); if (!name.equals(HardcodedMethodConstants.MAIN)) { return false; } final PsiType returnType = method.getReturnType(); if (!PsiType.VOID.equals(returnType)) { return false; } final PsiParameterList parameterList = method.getParameterList(); if (parameterList.getParametersCount() != 1) { return false; } final PsiParameter[] parameters = parameterList.getParameters(); final PsiParameter parameter = parameters[0]; final PsiType type = parameter.getType(); if (!type.equalsToText("java.lang.String[]")) { return false; } } return true; }
@NotNull @Override protected InspectionGadgetsFix[] buildFixes(Object... infos) { final PsiElement context = (PsiElement) infos[1]; final SmartTypePointerManager pointerManager = SmartTypePointerManager.getInstance(context.getProject()); final List<PsiType> maskedTypes = (List<PsiType>) infos[0]; final List<InspectionGadgetsFix> fixes = new ArrayList<>(); for (PsiType thrown : maskedTypes) { final String typeText = thrown.getCanonicalText(); if (CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION.equals(typeText)) { fixes.add(new ReplaceWithRuntimeExceptionFix()); } else { fixes.add(new AddCatchSectionFix(pointerManager.createSmartTypePointer(thrown), typeText)); } } final InspectionGadgetsFix fix = SuppressForTestsScopeFix.build(this, context); if (fix != null) { fixes.add(fix); } return fixes.toArray(new InspectionGadgetsFix[fixes.size()]); }
private void checkExpression(PsiExpression expression) { if (expression == null) return; final PsiType type = expression.getType(); if (!(type instanceof PsiClassType)) return; if (IGNORE_TOSTRING && MethodUtils.isToString(PsiTreeUtil.getParentOfType(expression, PsiMethod.class))) return; if (IGNORE_EXCEPTION && (ExceptionUtils.isExceptionArgument(expression) || PsiTreeUtil.getParentOfType( expression, PsiThrowStatement.class, true, PsiCodeBlock.class, PsiClass.class) != null)) return; if (IGNORE_ASSERT && PsiTreeUtil.getParentOfType( expression, PsiAssertStatement.class, true, PsiCodeBlock.class, PsiClass.class) != null) { return; } if (IGNORE_NONNLS && NonNlsUtils.isNonNlsAnnotatedUse(expression)) return; final PsiClassType classType = (PsiClassType) type; if (type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return; final PsiClass referencedClass = classType.resolve(); if (referencedClass == null || referencedClass instanceof PsiTypeParameter) return; if (referencedClass.isEnum() || referencedClass.isInterface()) return; if (referencedClass.hasModifierProperty(PsiModifier.ABSTRACT) && !(expression instanceof PsiSuperExpression)) return; if (hasGoodToString(referencedClass)) return; registerError(expression); }
@Override public void doFix(Project project, ProblemDescriptor descriptor) { final PsiExpression expression = (PsiExpression) descriptor.getPsiElement(); final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, false); if (expectedType == null) { return; } final String expectedTypeText = expectedType.getCanonicalText(); final String classToConstruct; if (s_boxingClasses.containsValue(expectedTypeText)) { classToConstruct = expectedTypeText; } else { final PsiType type = expression.getType(); if (type == null) { return; } final String expressionTypeText = type.getCanonicalText(); classToConstruct = s_boxingClasses.get(expressionTypeText); } if (shortcutReplace(expression, classToConstruct)) { return; } final PsiExpression strippedExpression = ParenthesesUtils.stripParentheses(expression); if (strippedExpression == null) { return; } @NonNls final String expressionText = strippedExpression.getText(); @NonNls final String newExpression; if ("true".equals(expressionText)) { newExpression = "java.lang.Boolean.TRUE"; } else if ("false".equals(expressionText)) { newExpression = "java.lang.Boolean.FALSE"; } else { newExpression = classToConstruct + ".valueOf(" + expressionText + ')'; } replaceExpression(expression, newExpression); }
private static LookupElementBuilder createGenerateMethodElement( PsiMethod prototype, PsiSubstitutor substitutor, Icon icon, String typeText, InsertHandler<LookupElement> insertHandler) { String methodName = prototype.getName(); String visibility = VisibilityUtil.getVisibilityModifier(prototype.getModifierList()); String modifiers = (visibility == PsiModifier.PACKAGE_LOCAL ? "" : visibility + " "); PsiType type = substitutor.substitute(prototype.getReturnType()); String signature = modifiers + (type == null ? "" : type.getPresentableText() + " ") + methodName; String parameters = PsiFormatUtil.formatMethod( prototype, substitutor, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_NAME); String overrideSignature = " @Override " + signature; // leading space to make it a middle match, under all annotation // suggestions LookupElementBuilder element = LookupElementBuilder.create(prototype, signature) .withLookupString(methodName) .withLookupString(signature) .withLookupString(overrideSignature) .withInsertHandler(insertHandler) .appendTailText(parameters, false) .appendTailText(" {...}", true) .withTypeText(typeText) .withIcon(icon); element.putUserData(GENERATE_ELEMENT, true); return element; }
@NotNull public static PsiClassType[] getSuperTypes(@NotNull PsiClass psiClass) { if (psiClass instanceof PsiAnonymousClass) { PsiClassType baseClassType = ((PsiAnonymousClass) psiClass).getBaseClassType(); PsiClass baseClass = baseClassType.resolve(); if (baseClass == null || !baseClass.isInterface()) { return new PsiClassType[] {baseClassType}; } else { PsiClassType objectType = PsiType.getJavaLangObject(psiClass.getManager(), psiClass.getResolveScope()); return new PsiClassType[] {objectType, baseClassType}; } } PsiClassType[] extendsTypes = psiClass.getExtendsListTypes(); PsiClassType[] implementsTypes = psiClass.getImplementsListTypes(); boolean hasExtends = extendsTypes.length != 0; int extendsListLength = extendsTypes.length + (hasExtends ? 0 : 1); PsiClassType[] result = new PsiClassType[extendsListLength + implementsTypes.length]; System.arraycopy(extendsTypes, 0, result, 0, extendsTypes.length); if (!hasExtends) { if (CommonClassNames.JAVA_LANG_OBJECT.equals(psiClass.getQualifiedName())) { return PsiClassType.EMPTY_ARRAY; } PsiManager manager = psiClass.getManager(); PsiClassType objectType = PsiType.getJavaLangObject(manager, psiClass.getResolveScope()); result[0] = objectType; } System.arraycopy(implementsTypes, 0, result, extendsListLength, implementsTypes.length); for (int i = 0; i < result.length; i++) { PsiClassType type = result[i]; result[i] = (PsiClassType) PsiUtil.captureToplevelWildcards(type, psiClass); } return result; }
@Override public void visitLiteralExpression(@NotNull PsiLiteralExpression value) { super.visitLiteralExpression(value); final String text = value.getText(); if (!PsiKeyword.NULL.equals(text)) { return; } PsiElement parent = value.getParent(); while (parent instanceof PsiParenthesizedExpression || parent instanceof PsiConditionalExpression || parent instanceof PsiTypeCastExpression) { parent = parent.getParent(); } if (parent == null || !(parent instanceof PsiReturnStatement)) { return; } final PsiMethod method = PsiTreeUtil.getParentOfType(value, PsiMethod.class); if (method == null) { return; } final PsiType returnType = method.getReturnType(); if (returnType == null) { return; } final boolean isArray = returnType.getArrayDimensions() > 0; if (AnnotationUtil.isAnnotated(method, AnnotationUtil.NULLABLE, false)) { return; } if (m_reportCollectionMethods && CollectionUtils.isCollectionClassOrInterface(returnType)) { registerError(value, value); } else if (m_reportArrayMethods && isArray) { registerError(value, value); } else if (m_reportObjectMethods && !isArray) { registerError(value, value); } }
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PsiTypeItem that = (PsiTypeItem) o; if (myType == null) { if (that.myType != null) return false; } else { if (!myType.equals(that.myType)) return false; } return true; }
private boolean isIteratorNext(PsiElement element, String iteratorName, PsiType contentType) { if (element == null) { return false; } if (element instanceof PsiTypeCastExpression) { final PsiTypeCastExpression castExpression = (PsiTypeCastExpression) element; final PsiType type = castExpression.getType(); if (type == null) { return false; } if (!type.equals(contentType)) { return false; } final PsiExpression operand = castExpression.getOperand(); return isIteratorNext(operand, iteratorName, contentType); } if (!(element instanceof PsiMethodCallExpression)) { return false; } final PsiMethodCallExpression callExpression = (PsiMethodCallExpression) element; final PsiExpressionList argumentList = callExpression.getArgumentList(); final PsiExpression[] args = argumentList.getExpressions(); if (args.length != 0) { return false; } final PsiReferenceExpression reference = callExpression.getMethodExpression(); final PsiExpression qualifier = reference.getQualifierExpression(); if (qualifier == null) { return false; } if (!iteratorName.equals(qualifier.getText())) { return false; } final String referenceName = reference.getReferenceName(); return HardcodedMethodConstants.NEXT.equals(referenceName); }
private boolean isListElementDeclaration( PsiStatement statement, PsiVariable listVariable, String indexName, PsiType type) { if (!(statement instanceof PsiDeclarationStatement)) { return false; } final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) statement; final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); if (declaredElements.length != 1) { return false; } final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return false; } final PsiVariable variable = (PsiVariable) declaredElement; final PsiExpression initializer = variable.getInitializer(); if (!isListGetLookup(initializer, indexName, listVariable)) { return false; } return type != null && type.equals(variable.getType()); }
private static boolean compareParamTypes( @NotNull PsiManager manager, @NotNull PsiType type1, @NotNull PsiType type2) { if (type1 instanceof PsiArrayType) { return type2 instanceof PsiArrayType && compareParamTypes( manager, ((PsiArrayType) type1).getComponentType(), ((PsiArrayType) type2).getComponentType()); } if (!(type1 instanceof PsiClassType) || !(type2 instanceof PsiClassType)) { return type1.equals(type2); } PsiClass class1 = ((PsiClassType) type1).resolve(); PsiClass class2 = ((PsiClassType) type2).resolve(); if (class1 instanceof PsiTypeParameter && class2 instanceof PsiTypeParameter) { return Comparing.equal(class1.getName(), class2.getName()) && ((PsiTypeParameter) class1).getIndex() == ((PsiTypeParameter) class2).getIndex(); } return manager.areElementsEquivalent(class1, class2); }
@Nullable private String createListIterationText(@NotNull PsiForStatement forStatement) { final PsiBinaryExpression condition = (PsiBinaryExpression) ParenthesesUtils.stripParentheses(forStatement.getCondition()); if (condition == null) { return null; } final PsiExpression lhs = ParenthesesUtils.stripParentheses(condition.getLOperand()); if (lhs == null) { return null; } final PsiExpression rhs = ParenthesesUtils.stripParentheses(condition.getROperand()); if (rhs == null) { return null; } final IElementType tokenType = condition.getOperationTokenType(); final String indexName; PsiExpression collectionSize; if (JavaTokenType.LT.equals(tokenType)) { indexName = lhs.getText(); collectionSize = rhs; } else if (JavaTokenType.GT.equals(tokenType)) { indexName = rhs.getText(); collectionSize = lhs; } else { return null; } if (collectionSize instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) collectionSize; final PsiElement target = referenceExpression.resolve(); if (target instanceof PsiVariable) { final PsiVariable variable = (PsiVariable) target; collectionSize = ParenthesesUtils.stripParentheses(variable.getInitializer()); } } if (!(collectionSize instanceof PsiMethodCallExpression)) { return null; } final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) ParenthesesUtils.stripParentheses(collectionSize); if (methodCallExpression == null) { return null; } final PsiReferenceExpression listLengthExpression = methodCallExpression.getMethodExpression(); final PsiExpression qualifier = ParenthesesUtils.stripParentheses(listLengthExpression.getQualifierExpression()); final PsiReferenceExpression listReference; if (qualifier instanceof PsiReferenceExpression) { listReference = (PsiReferenceExpression) qualifier; } else { listReference = null; } PsiType parameterType; if (listReference == null) { parameterType = extractListTypeFromContainingClass(forStatement); } else { final PsiType type = listReference.getType(); if (type == null) { return null; } parameterType = extractContentTypeFromType(type); } if (parameterType == null) { parameterType = TypeUtils.getObjectType(forStatement); } final String typeString = parameterType.getCanonicalText(); final PsiVariable listVariable; if (listReference == null) { listVariable = null; } else { final PsiElement target = listReference.resolve(); if (!(target instanceof PsiVariable)) { return null; } listVariable = (PsiVariable) target; } final PsiStatement body = forStatement.getBody(); final PsiStatement firstStatement = getFirstStatement(body); final boolean isDeclaration = isListElementDeclaration(firstStatement, listVariable, indexName, parameterType); final String contentVariableName; @NonNls final String finalString; final PsiStatement statementToSkip; if (isDeclaration) { final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) firstStatement; assert declarationStatement != null; final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return null; } final PsiVariable variable = (PsiVariable) declaredElement; contentVariableName = variable.getName(); statementToSkip = declarationStatement; if (variable.hasModifierProperty(PsiModifier.FINAL)) { finalString = "final "; } else { finalString = ""; } } else { final String collectionName; if (listReference == null) { collectionName = null; } else { collectionName = listReference.getReferenceName(); } contentVariableName = createNewVariableName(forStatement, parameterType, collectionName); finalString = ""; statementToSkip = null; } @NonNls final StringBuilder out = new StringBuilder(); out.append("for("); out.append(finalString); out.append(typeString); out.append(' '); out.append(contentVariableName); out.append(": "); @NonNls final String listName; if (listReference == null) { listName = "this"; } else { listName = listReference.getText(); } out.append(listName); out.append(')'); if (body != null) { replaceCollectionGetAccess( body, contentVariableName, listVariable, indexName, statementToSkip, out); } return out.toString(); }
@Nullable private String createArrayIterationText(@NotNull PsiForStatement forStatement) { final PsiExpression condition = forStatement.getCondition(); final PsiBinaryExpression strippedCondition = (PsiBinaryExpression) ParenthesesUtils.stripParentheses(condition); if (strippedCondition == null) { return null; } final PsiExpression lhs = ParenthesesUtils.stripParentheses(strippedCondition.getLOperand()); if (lhs == null) { return null; } final PsiExpression rhs = ParenthesesUtils.stripParentheses(strippedCondition.getROperand()); if (rhs == null) { return null; } final IElementType tokenType = strippedCondition.getOperationTokenType(); final PsiReferenceExpression arrayLengthExpression; final String indexName; if (tokenType.equals(JavaTokenType.LT)) { arrayLengthExpression = (PsiReferenceExpression) ParenthesesUtils.stripParentheses(rhs); indexName = lhs.getText(); } else if (tokenType.equals(JavaTokenType.GT)) { arrayLengthExpression = (PsiReferenceExpression) ParenthesesUtils.stripParentheses(lhs); indexName = rhs.getText(); } else { return null; } if (arrayLengthExpression == null) { return null; } PsiReferenceExpression arrayReference = (PsiReferenceExpression) arrayLengthExpression.getQualifierExpression(); if (arrayReference == null) { final PsiElement target = arrayLengthExpression.resolve(); if (!(target instanceof PsiVariable)) { return null; } final PsiVariable variable = (PsiVariable) target; final PsiExpression initializer = variable.getInitializer(); if (!(initializer instanceof PsiReferenceExpression)) { return null; } final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) initializer; arrayReference = (PsiReferenceExpression) referenceExpression.getQualifierExpression(); if (arrayReference == null) { return null; } } final PsiType type = arrayReference.getType(); if (!(type instanceof PsiArrayType)) { return null; } final PsiArrayType arrayType = (PsiArrayType) type; final PsiType componentType = arrayType.getComponentType(); final String typeText = componentType.getCanonicalText(); final PsiElement target = arrayReference.resolve(); if (!(target instanceof PsiVariable)) { return null; } final PsiVariable arrayVariable = (PsiVariable) target; final PsiStatement body = forStatement.getBody(); final PsiStatement firstStatement = getFirstStatement(body); final boolean isDeclaration = isArrayElementDeclaration(firstStatement, arrayVariable, indexName); final String contentVariableName; @NonNls final String finalString; final PsiStatement statementToSkip; if (isDeclaration) { final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) firstStatement; assert declarationStatement != null; final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return null; } final PsiVariable variable = (PsiVariable) declaredElement; if (VariableAccessUtils.variableIsAssigned(variable, forStatement)) { final String collectionName = arrayReference.getReferenceName(); contentVariableName = createNewVariableName(forStatement, componentType, collectionName); final Project project = forStatement.getProject(); final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project); if (codeStyleSettings.GENERATE_FINAL_LOCALS) { finalString = "final "; } else { finalString = ""; } statementToSkip = null; } else { contentVariableName = variable.getName(); statementToSkip = declarationStatement; if (variable.hasModifierProperty(PsiModifier.FINAL)) { finalString = "final "; } else { finalString = ""; } } } else { final String collectionName = arrayReference.getReferenceName(); contentVariableName = createNewVariableName(forStatement, componentType, collectionName); final Project project = forStatement.getProject(); final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project); if (codeStyleSettings.GENERATE_FINAL_LOCALS) { finalString = "final "; } else { finalString = ""; } statementToSkip = null; } @NonNls final StringBuilder out = new StringBuilder(); out.append("for("); out.append(finalString); out.append(typeText); out.append(' '); out.append(contentVariableName); out.append(": "); final String arrayName = arrayReference.getText(); out.append(arrayName); out.append(')'); if (body != null) { replaceArrayAccess( body, contentVariableName, arrayVariable, indexName, statementToSkip, out); } return out.toString(); }
@Nullable private String createCollectionIterationText(@NotNull PsiForStatement forStatement) throws IncorrectOperationException { final PsiStatement body = forStatement.getBody(); final PsiStatement firstStatement = getFirstStatement(body); final PsiStatement initialization = forStatement.getInitialization(); if (!(initialization instanceof PsiDeclarationStatement)) { return null; } final PsiDeclarationStatement declaration = (PsiDeclarationStatement) initialization; final PsiElement declaredIterator = declaration.getDeclaredElements()[0]; if (!(declaredIterator instanceof PsiVariable)) { return null; } final PsiVariable iteratorVariable = (PsiVariable) declaredIterator; final PsiMethodCallExpression initializer = (PsiMethodCallExpression) iteratorVariable.getInitializer(); if (initializer == null) { return null; } final PsiType iteratorType = initializer.getType(); if (iteratorType == null) { return null; } final PsiType iteratorContentType = extractContentTypeFromType(iteratorType); final PsiType iteratorVariableType = iteratorVariable.getType(); final PsiType contentType; final PsiClassType javaLangObject = TypeUtils.getObjectType(forStatement); if (iteratorContentType == null) { final PsiType iteratorVariableContentType = extractContentTypeFromType(iteratorVariableType); if (iteratorVariableContentType == null) { contentType = javaLangObject; } else { contentType = iteratorVariableContentType; } } else { contentType = iteratorContentType; } final PsiReferenceExpression methodExpression = initializer.getMethodExpression(); final PsiExpression collection = methodExpression.getQualifierExpression(); final String iteratorName = iteratorVariable.getName(); final boolean isDeclaration = isIteratorNextDeclaration(firstStatement, iteratorName, contentType); final PsiStatement statementToSkip; @NonNls final String finalString; final String contentVariableName; if (isDeclaration) { final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) firstStatement; assert declarationStatement != null; final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return null; } final PsiVariable variable = (PsiVariable) declaredElement; contentVariableName = variable.getName(); statementToSkip = declarationStatement; if (variable.hasModifierProperty(PsiModifier.FINAL)) { finalString = "final "; } else { finalString = ""; } } else { if (collection instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) collection; final String collectionName = referenceExpression.getReferenceName(); contentVariableName = createNewVariableName(forStatement, contentType, collectionName); } else { contentVariableName = createNewVariableName(forStatement, contentType, null); } final Project project = forStatement.getProject(); final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project); if (codeStyleSettings.GENERATE_FINAL_LOCALS) { finalString = "final "; } else { finalString = ""; } statementToSkip = null; } final String contentTypeString = contentType.getCanonicalText(); @NonNls final StringBuilder out = new StringBuilder(); out.append("for("); out.append(finalString); out.append(contentTypeString); out.append(' '); out.append(contentVariableName); out.append(": "); if (!contentType.equals(javaLangObject)) { @NonNls final String iterableTypeString = "java.lang.Iterable<" + contentTypeString + '>'; if (iteratorContentType == null) { out.append('('); out.append(iterableTypeString); out.append(')'); } } if (collection == null) { out.append("this"); } else { out.append(collection.getText()); } out.append(')'); replaceIteratorNext( body, contentVariableName, iteratorName, statementToSkip, out, contentType); return out.toString(); }
private static void setupPatternMethods( PsiManager manager, GlobalSearchScope searchScope, List<PsiMethod> patternMethods, IntArrayList indices) { final PsiClass collectionClass = JavaPsiFacade.getInstance(manager.getProject()) .findClass("java.util.Collection", searchScope); PsiType[] javaLangObject = {PsiType.getJavaLangObject(manager, searchScope)}; MethodSignature removeSignature = MethodSignatureUtil.createMethodSignature( "remove", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); if (collectionClass != null) { PsiMethod remove = MethodSignatureUtil.findMethodBySignature(collectionClass, removeSignature, false); addMethod(remove, 0, patternMethods, indices); MethodSignature containsSignature = MethodSignatureUtil.createMethodSignature( "contains", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); PsiMethod contains = MethodSignatureUtil.findMethodBySignature(collectionClass, containsSignature, false); addMethod(contains, 0, patternMethods, indices); } final PsiClass listClass = JavaPsiFacade.getInstance(manager.getProject()).findClass("java.util.List", searchScope); if (listClass != null) { MethodSignature indexofSignature = MethodSignatureUtil.createMethodSignature( "indexOf", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); PsiMethod indexof = MethodSignatureUtil.findMethodBySignature(listClass, indexofSignature, false); addMethod(indexof, 0, patternMethods, indices); MethodSignature lastindexofSignature = MethodSignatureUtil.createMethodSignature( "lastIndexOf", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); PsiMethod lastindexof = MethodSignatureUtil.findMethodBySignature(listClass, lastindexofSignature, false); addMethod(lastindexof, 0, patternMethods, indices); } final PsiClass mapClass = JavaPsiFacade.getInstance(manager.getProject()).findClass("java.util.Map", searchScope); if (mapClass != null) { PsiMethod remove = MethodSignatureUtil.findMethodBySignature(mapClass, removeSignature, false); addMethod(remove, 0, patternMethods, indices); MethodSignature getSignature = MethodSignatureUtil.createMethodSignature( "get", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); PsiMethod get = MethodSignatureUtil.findMethodBySignature(mapClass, getSignature, false); addMethod(get, 0, patternMethods, indices); MethodSignature containsKeySignature = MethodSignatureUtil.createMethodSignature( "containsKey", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); PsiMethod containsKey = MethodSignatureUtil.findMethodBySignature(mapClass, containsKeySignature, false); addMethod(containsKey, 0, patternMethods, indices); MethodSignature containsValueSignature = MethodSignatureUtil.createMethodSignature( "containsValue", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); PsiMethod containsValue = MethodSignatureUtil.findMethodBySignature(mapClass, containsValueSignature, false); addMethod(containsValue, 1, patternMethods, indices); } }
private boolean checkCondition( @Nullable PsiExpression condition, @NotNull PsiStatement context, List<PsiExpression> notUpdated) { if (condition == null) { return false; } if (PsiUtil.isConstantExpression(condition) || PsiKeyword.NULL.equals(condition.getText())) { return true; } if (condition instanceof PsiInstanceOfExpression) { final PsiInstanceOfExpression instanceOfExpression = (PsiInstanceOfExpression) condition; final PsiExpression operand = instanceOfExpression.getOperand(); return checkCondition(operand, context, notUpdated); } else if (condition instanceof PsiParenthesizedExpression) { // catch stuff like "while ((x)) { ... }" final PsiExpression expression = ((PsiParenthesizedExpression) condition).getExpression(); return checkCondition(expression, context, notUpdated); } else if (condition instanceof PsiPolyadicExpression) { // while (value != x) { ... } // while (value != (x + y)) { ... } // while (b1 && b2) { ... } final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression) condition; for (PsiExpression operand : polyadicExpression.getOperands()) { if (!checkCondition(operand, context, notUpdated)) { return false; } } return true; } else if (condition instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) condition; final PsiElement element = referenceExpression.resolve(); if (element instanceof PsiField) { final PsiField field = (PsiField) element; final PsiType type = field.getType(); if (field.hasModifierProperty(PsiModifier.FINAL) && type.getArrayDimensions() == 0) { if (field.hasModifierProperty(PsiModifier.STATIC)) { return true; } final PsiExpression qualifier = referenceExpression.getQualifierExpression(); if (qualifier == null) { return true; } else if (checkCondition(qualifier, context, notUpdated)) { return true; } } } else if (element instanceof PsiVariable) { final PsiVariable variable = (PsiVariable) element; if (variable.hasModifierProperty(PsiModifier.FINAL)) { // final variables cannot be updated, don't bother to // flag them return true; } else if (element instanceof PsiLocalVariable || element instanceof PsiParameter) { if (!VariableAccessUtils.variableIsAssigned(variable, context)) { notUpdated.add(referenceExpression); return true; } } } } else if (condition instanceof PsiPrefixExpression) { final PsiPrefixExpression prefixExpression = (PsiPrefixExpression) condition; final IElementType tokenType = prefixExpression.getOperationTokenType(); if (JavaTokenType.EXCL.equals(tokenType) || JavaTokenType.PLUS.equals(tokenType) || JavaTokenType.MINUS.equals(tokenType)) { final PsiExpression operand = prefixExpression.getOperand(); return checkCondition(operand, context, notUpdated); } } else if (condition instanceof PsiArrayAccessExpression) { // Actually the contents of the array could change nevertheless // if it is accessed through a different reference like this: // int[] local_ints = new int[]{1, 2}; // int[] other_ints = local_ints; // while (local_ints[0] > 0) { other_ints[0]--; } // // Keep this check? final PsiArrayAccessExpression accessExpression = (PsiArrayAccessExpression) condition; final PsiExpression indexExpression = accessExpression.getIndexExpression(); return checkCondition(indexExpression, context, notUpdated) && checkCondition(accessExpression.getArrayExpression(), context, notUpdated); } else if (condition instanceof PsiConditionalExpression) { final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression) condition; final PsiExpression thenExpression = conditionalExpression.getThenExpression(); final PsiExpression elseExpression = conditionalExpression.getElseExpression(); if (thenExpression == null || elseExpression == null) { return false; } return checkCondition(conditionalExpression.getCondition(), context, notUpdated) && checkCondition(thenExpression, context, notUpdated) && checkCondition(elseExpression, context, notUpdated); } else if (condition instanceof PsiThisExpression) { return true; } else if (condition instanceof PsiMethodCallExpression && !ignoreIterators) { final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) condition; if (!IteratorUtils.isCallToHasNext(methodCallExpression)) { return false; } final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); final PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); if (qualifierExpression instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) qualifierExpression; final PsiElement element = referenceExpression.resolve(); if (!(element instanceof PsiVariable)) { return false; } final PsiVariable variable = (PsiVariable) element; if (!IteratorUtils.containsCallToScannerNext(context, variable, true)) { notUpdated.add(qualifierExpression); return true; } } else { if (!IteratorUtils.containsCallToScannerNext(context, null, true)) { notUpdated.add(methodCallExpression); return true; } } } return false; }
private static String[] getFieldNames(final RadComponent component, final String currentName) { final ArrayList<String> result = new ArrayList<String>(); if (currentName != null) { result.add(currentName); } final IRootContainer root = FormEditingUtil.getRoot(component); final String className = root.getClassToBind(); if (className == null) { return ArrayUtil.toStringArray(result); } final PsiClass aClass = FormEditingUtil.findClassToBind(component.getModule(), className); if (aClass == null) { return ArrayUtil.toStringArray(result); } final PsiField[] fields = aClass.getFields(); for (final PsiField field : fields) { if (field.hasModifierProperty(PsiModifier.STATIC)) { continue; } final String fieldName = field.getName(); if (Comparing.equal(currentName, fieldName)) { continue; } if (!FormEditingUtil.isBindingUnique(component, fieldName, root)) { continue; } final String componentClassName; if (component instanceof RadErrorComponent) { componentClassName = component.getComponentClassName(); } else if (component instanceof RadHSpacer || component instanceof RadVSpacer) { componentClassName = Spacer.class.getName(); } else { componentClassName = component.getComponentClass().getName(); } final PsiType componentType; try { componentType = JavaPsiFacade.getInstance(component.getProject()) .getElementFactory() .createTypeFromText(componentClassName, null); } catch (IncorrectOperationException e) { continue; } final PsiType fieldType = field.getType(); if (!fieldType.isAssignableFrom(componentType)) { continue; } result.add(fieldName); } String text = FormInspectionUtil.getText(component.getModule(), component); if (text != null) { String binding = BindingProperty.suggestBindingFromText(component, text); if (binding != null && !result.contains(binding)) { result.add(binding); } } final String[] names = ArrayUtil.toStringArray(result); Arrays.sort(names); return names; }
@Override public void visitTypeCastExpression(@NotNull PsiTypeCastExpression expression) { super.visitTypeCastExpression(expression); final PsiExpression operand = expression.getOperand(); if (operand == null) { return; } final PsiType operandType = operand.getType(); if (operandType == null) { return; } final PsiType type = expression.getType(); if (type == null) { return; } final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, true); if (expectedType == null) { return; } if (expectedType.equals(type)) { return; } final PsiClass resolved = PsiUtil.resolveClassInType(expectedType); if (resolved != null && !resolved.isPhysical()) { return; } if (expectedType.isAssignableFrom(operandType)) { // then it's redundant, and caught by the built-in exception return; } if (isTypeParameter(expectedType)) { return; } if (expectedType instanceof PsiArrayType) { final PsiArrayType arrayType = (PsiArrayType) expectedType; final PsiType componentType = arrayType.getDeepComponentType(); if (isTypeParameter(componentType)) { return; } } if (type instanceof PsiPrimitiveType || expectedType instanceof PsiPrimitiveType) { return; } if (PsiPrimitiveType.getUnboxedType(type) != null || PsiPrimitiveType.getUnboxedType(expectedType) != null) { return; } if (expectedType instanceof PsiClassType) { final PsiClassType expectedClassType = (PsiClassType) expectedType; final PsiClassType expectedRawType = expectedClassType.rawType(); if (type.equals(expectedRawType)) { return; } if (type instanceof PsiClassType) { final PsiClassType classType = (PsiClassType) type; final PsiClassType rawType = classType.rawType(); if (rawType.equals(expectedRawType)) { return; } } if (type instanceof PsiArrayType) { return; } } if (ignoreInMatchingInstanceof && InstanceOfUtils.hasAgreeingInstanceof(expression)) { return; } final PsiTypeElement castTypeElement = expression.getCastType(); if (castTypeElement == null) { return; } registerError(castTypeElement, expectedType); }
@Override public String toString() { return myType == null ? "def" : myType.getPresentableText(); }
@Override protected String validateAndCommitData() { PsiManager manager = PsiManager.getInstance(myProject); PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); String name = getMethodName(); if (!JavaPsiFacade.getInstance(manager.getProject()).getNameHelper().isIdentifier(name)) { return RefactoringMessageUtil.getIncorrectIdentifierMessage(name); } if (myMethod.canChangeReturnType() == MethodDescriptor.ReadWriteOption.ReadWrite) { try { ((PsiTypeCodeFragment) myReturnTypeCodeFragment).getType(); } catch (PsiTypeCodeFragment.TypeSyntaxException e) { myReturnTypeField.requestFocus(); return RefactoringBundle.message( "changeSignature.wrong.return.type", myReturnTypeCodeFragment.getText()); } catch (PsiTypeCodeFragment.NoTypeException e) { myReturnTypeField.requestFocus(); return RefactoringBundle.message("changeSignature.no.return.type"); } } List<ParameterTableModelItemBase<ParameterInfoImpl>> parameterInfos = myParametersTableModel.getItems(); final int newParametersNumber = parameterInfos.size(); for (int i = 0; i < newParametersNumber; i++) { final ParameterTableModelItemBase<ParameterInfoImpl> item = parameterInfos.get(i); if (!JavaPsiFacade.getInstance(manager.getProject()) .getNameHelper() .isIdentifier(item.parameter.getName())) { return RefactoringMessageUtil.getIncorrectIdentifierMessage(item.parameter.getName()); } final PsiType type; try { type = ((PsiTypeCodeFragment) parameterInfos.get(i).typeCodeFragment).getType(); } catch (PsiTypeCodeFragment.TypeSyntaxException e) { return RefactoringBundle.message( "changeSignature.wrong.type.for.parameter", item.typeCodeFragment.getText(), item.parameter.getName()); } catch (PsiTypeCodeFragment.NoTypeException e) { return RefactoringBundle.message( "changeSignature.no.type.for.parameter", item.parameter.getName()); } item.parameter.setType(type); if (type instanceof PsiEllipsisType && i != newParametersNumber - 1) { return RefactoringBundle.message("changeSignature.vararg.not.last"); } if (item.parameter.oldParameterIndex < 0) { item.parameter.defaultValue = ApplicationManager.getApplication() .runWriteAction( new Computable<String>() { @Override public String compute() { return JavaCodeStyleManager.getInstance(myProject) .qualifyClassReferences(item.defaultValueCodeFragment) .getText(); } }); String def = item.parameter.defaultValue; def = def.trim(); if (!(type instanceof PsiEllipsisType)) { try { if (!StringUtil.isEmpty(def)) { factory.createExpressionFromText(def, null); } } catch (IncorrectOperationException e) { return e.getMessage(); } } } } ThrownExceptionInfo[] exceptionInfos = myExceptionsModel.getThrownExceptions(); PsiTypeCodeFragment[] typeCodeFragments = myExceptionsModel.getTypeCodeFragments(); for (int i = 0; i < exceptionInfos.length; i++) { ThrownExceptionInfo exceptionInfo = exceptionInfos[i]; PsiTypeCodeFragment typeCodeFragment = typeCodeFragments[i]; try { PsiType type = typeCodeFragment.getType(); if (!(type instanceof PsiClassType)) { return RefactoringBundle.message( "changeSignature.wrong.type.for.exception", typeCodeFragment.getText()); } PsiClassType throwable = JavaPsiFacade.getInstance(myProject) .getElementFactory() .createTypeByFQClassName("java.lang.Throwable", type.getResolveScope()); if (!throwable.isAssignableFrom(type)) { return RefactoringBundle.message( "changeSignature.not.throwable.type", typeCodeFragment.getText()); } exceptionInfo.setType((PsiClassType) type); } catch (PsiTypeCodeFragment.TypeSyntaxException e) { return RefactoringBundle.message( "changeSignature.wrong.type.for.exception", typeCodeFragment.getText()); } catch (PsiTypeCodeFragment.NoTypeException e) { return RefactoringBundle.message("changeSignature.no.type.for.exception"); } } // warnings try { if (myMethod.canChangeReturnType() == MethodDescriptor.ReadWriteOption.ReadWrite) { if (!RefactoringUtil.isResolvableType( ((PsiTypeCodeFragment) myReturnTypeCodeFragment).getType())) { if (Messages.showOkCancelDialog( myProject, RefactoringBundle.message( "changeSignature.cannot.resolve.return.type", myReturnTypeCodeFragment.getText()), RefactoringBundle.message("changeSignature.refactoring.name"), Messages.getWarningIcon()) != 0) { return EXIT_SILENTLY; } } } for (ParameterTableModelItemBase<ParameterInfoImpl> item : parameterInfos) { if (!RefactoringUtil.isResolvableType( ((PsiTypeCodeFragment) item.typeCodeFragment).getType())) { if (Messages.showOkCancelDialog( myProject, RefactoringBundle.message( "changeSignature.cannot.resolve.parameter.type", item.typeCodeFragment.getText(), item.parameter.getName()), RefactoringBundle.message("changeSignature.refactoring.name"), Messages.getWarningIcon()) != 0) { return EXIT_SILENTLY; } } } } catch (PsiTypeCodeFragment.IncorrectTypeException ignored) { } return null; }
@Override public int hashCode() { return myType == null ? 0 : myType.hashCode(); }