private boolean isArrayLookup( PsiElement element, String indexName, PsiVariable arrayVariable) { if (element == null) { return false; } if (!(element instanceof PsiArrayAccessExpression)) { return false; } final PsiArrayAccessExpression arrayAccess = (PsiArrayAccessExpression)element; final PsiExpression indexExpression = arrayAccess.getIndexExpression(); if (indexExpression == null) { return false; } if (!indexName.equals(indexExpression.getText())) { return false; } final PsiExpression arrayExpression = arrayAccess.getArrayExpression(); if (!(arrayExpression instanceof PsiReferenceExpression)) { return false; } final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)arrayExpression; final PsiExpression qualifier = referenceExpression.getQualifierExpression(); if (qualifier != null && !(qualifier instanceof PsiThisExpression) && !(qualifier instanceof PsiSuperExpression)) { return false; } final PsiElement target = referenceExpression.resolve(); return arrayVariable.equals(target); }
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 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) { 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 boolean isAddedToCollection(PsiExpression expression) { final PsiElement parent = expression.getParent(); if (!(parent instanceof PsiExpressionList)) { return false; } final PsiExpressionList expressionList = (PsiExpressionList) parent; final PsiElement grandParent = expressionList.getParent(); if (!(grandParent instanceof PsiMethodCallExpression)) { return false; } final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) grandParent; final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); @NonNls final String methodName = methodExpression.getReferenceName(); if (!"put".equals(methodName) && !"set".equals(methodName) && !"add".equals(methodName)) { return false; } final PsiExpression qualifier = methodExpression.getQualifierExpression(); return TypeUtils.expressionHasTypeOrSubtype( qualifier, CommonClassNames.JAVA_UTIL_COLLECTION, CommonClassNames.JAVA_UTIL_MAP) != null; }
@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 PsiArrayType arrayType = (PsiArrayType)arrayReference.getType(); if (arrayType == null) { return null; } 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(); }
@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 = 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(); }
private static boolean shortcutReplace(PsiExpression expression, String classToConstruct) { if (!(expression instanceof PsiMethodCallExpression)) { return false; } final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) expression; final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); final PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); if (qualifierExpression == null) { return false; } if (classToConstruct.equals(CommonClassNames.JAVA_LANG_INTEGER)) { if (MethodCallUtils.isCallToMethod( methodCallExpression, CommonClassNames.JAVA_LANG_INTEGER, PsiType.INT, "intValue")) { expression.replace(qualifierExpression); return true; } } else if (classToConstruct.equals(CommonClassNames.JAVA_LANG_SHORT)) { if (MethodCallUtils.isCallToMethod( methodCallExpression, CommonClassNames.JAVA_LANG_SHORT, PsiType.SHORT, "shortValue")) { expression.replace(qualifierExpression); return true; } } else if (classToConstruct.equals(CommonClassNames.JAVA_LANG_BYTE)) { if (MethodCallUtils.isCallToMethod( methodCallExpression, CommonClassNames.JAVA_LANG_BYTE, PsiType.BYTE, "byteValue")) { expression.replace(qualifierExpression); return true; } } else if (classToConstruct.equals(CommonClassNames.JAVA_LANG_CHARACTER)) { if (MethodCallUtils.isCallToMethod( methodCallExpression, CommonClassNames.JAVA_LANG_CHARACTER, PsiType.CHAR, "charValue")) { expression.replace(qualifierExpression); return true; } } else if (classToConstruct.equals(CommonClassNames.JAVA_LANG_LONG)) { if (MethodCallUtils.isCallToMethod( methodCallExpression, CommonClassNames.JAVA_LANG_LONG, PsiType.LONG, "longValue")) { expression.replace(qualifierExpression); return true; } } else if (classToConstruct.equals(CommonClassNames.JAVA_LANG_FLOAT)) { if (MethodCallUtils.isCallToMethod( methodCallExpression, CommonClassNames.JAVA_LANG_FLOAT, PsiType.FLOAT, "floatValue")) { expression.replace(qualifierExpression); return true; } } else if (classToConstruct.equals(CommonClassNames.JAVA_LANG_DOUBLE)) { if (MethodCallUtils.isCallToMethod( methodCallExpression, CommonClassNames.JAVA_LANG_DOUBLE, PsiType.DOUBLE, "doubleValue")) { expression.replace(qualifierExpression); return true; } } return false; }