private static boolean hasCorrectType( @Nullable PsiAnnotationMemberValue value, PsiType expectedType) { if (value == null) return false; if (expectedType instanceof PsiClassType && expectedType.equalsToText(CommonClassNames.JAVA_LANG_CLASS) && !(value instanceof PsiClassObjectAccessExpression)) { return false; } if (value instanceof PsiAnnotation) { final PsiJavaCodeReferenceElement nameRef = ((PsiAnnotation) value).getNameReferenceElement(); if (nameRef == null) return true; if (expectedType instanceof PsiClassType) { final PsiClass aClass = ((PsiClassType) expectedType).resolve(); if (aClass != null && nameRef.isReferenceTo(aClass)) return true; } if (expectedType instanceof PsiArrayType) { final PsiType componentType = ((PsiArrayType) expectedType).getComponentType(); if (componentType instanceof PsiClassType) { final PsiClass aClass = ((PsiClassType) componentType).resolve(); if (aClass != null && nameRef.isReferenceTo(aClass)) return true; } } return false; } if (value instanceof PsiArrayInitializerMemberValue) { return expectedType instanceof PsiArrayType; } if (value instanceof PsiExpression) { final PsiExpression expression = (PsiExpression) value; return expression.getType() != null && TypeConversionUtil.areTypesAssignmentCompatible(expectedType, expression) || expectedType instanceof PsiArrayType && TypeConversionUtil.areTypesAssignmentCompatible( ((PsiArrayType) expectedType).getComponentType(), expression); } return true; }
static boolean isArgumentInVarargPosition( PsiExpression[] expressions, int ei, PsiParameter varargParam, PsiSubstitutor substitutor) { if (varargParam == null) return false; final PsiExpression expression = expressions[ei]; if (expression == null || TypeConversionUtil.areTypesAssignmentCompatible( substitutor.substitute(((PsiEllipsisType) varargParam.getType()).getComponentType()), expression)) { final int lastExprIdx = expressions.length - 1; if (ei == lastExprIdx) return true; return expressions[lastExprIdx].getType() != PsiType.NULL; } return false; }
@Nullable public static HighlightInfo checkMemberValueType( @Nullable PsiAnnotationMemberValue value, PsiType expectedType) { if (value == null) return null; if (expectedType instanceof PsiClassType && expectedType.equalsToText(CommonClassNames.JAVA_LANG_CLASS)) { if (!(value instanceof PsiClassObjectAccessExpression)) { String description = JavaErrorMessages.message("annotation.non.class.literal.attribute.value"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(value) .descriptionAndTooltip(description) .create(); } } if (value instanceof PsiAnnotation) { PsiJavaCodeReferenceElement nameRef = ((PsiAnnotation) value).getNameReferenceElement(); if (nameRef == null) return null; if (expectedType instanceof PsiClassType) { PsiClass aClass = ((PsiClassType) expectedType).resolve(); if (aClass != null && nameRef.isReferenceTo(aClass)) return null; } if (expectedType instanceof PsiArrayType) { PsiType componentType = ((PsiArrayType) expectedType).getComponentType(); if (componentType instanceof PsiClassType) { PsiClass aClass = ((PsiClassType) componentType).resolve(); if (aClass != null && nameRef.isReferenceTo(aClass)) return null; } } String description = JavaErrorMessages.message( "annotation.incompatible.types", formatReference(nameRef), JavaHighlightUtil.formatType(expectedType)); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(value) .descriptionAndTooltip(description) .create(); } if (value instanceof PsiArrayInitializerMemberValue) { if (expectedType instanceof PsiArrayType) return null; String description = JavaErrorMessages.message( "annotation.illegal.array.initializer", JavaHighlightUtil.formatType(expectedType)); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(value) .descriptionAndTooltip(description) .create(); } if (value instanceof PsiExpression) { PsiExpression expr = (PsiExpression) value; PsiType type = expr.getType(); if (type != null && TypeConversionUtil.areTypesAssignmentCompatible(expectedType, expr) || expectedType instanceof PsiArrayType && TypeConversionUtil.areTypesAssignmentCompatible( ((PsiArrayType) expectedType).getComponentType(), expr)) { return null; } String description = JavaErrorMessages.message( "annotation.incompatible.types", JavaHighlightUtil.formatType(type), JavaHighlightUtil.formatType(expectedType)); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(value) .descriptionAndTooltip(description) .create(); } LOG.error("Unknown annotation member value: " + value); return null; }
private NamesByExprInfo suggestVariableNameByExpressionPlace( PsiExpression expr, final VariableKind variableKind, boolean correctKeywords) { if (expr.getParent() instanceof PsiExpressionList) { PsiExpressionList list = (PsiExpressionList) expr.getParent(); PsiElement listParent = list.getParent(); PsiSubstitutor subst = PsiSubstitutor.EMPTY; PsiMethod method = null; if (listParent instanceof PsiMethodCallExpression) { final JavaResolveResult resolveResult = ((PsiMethodCallExpression) listParent).getMethodExpression().advancedResolve(false); method = (PsiMethod) resolveResult.getElement(); subst = resolveResult.getSubstitutor(); } else { if (listParent instanceof PsiAnonymousClass) { listParent = listParent.getParent(); } if (listParent instanceof PsiNewExpression) { method = ((PsiNewExpression) listParent).resolveConstructor(); } } if (method != null) { final PsiElement navElement = method.getNavigationElement(); if (navElement instanceof PsiMethod) { method = (PsiMethod) navElement; } PsiExpression[] expressions = list.getExpressions(); int index = -1; for (int i = 0; i < expressions.length; i++) { if (expressions[i] == expr) { index = i; break; } } PsiParameter[] parameters = method.getParameterList().getParameters(); if (index < parameters.length) { String name = parameters[index].getName(); if (name != null && TypeConversionUtil.areTypesAssignmentCompatible( subst.substitute(parameters[index].getType()), expr)) { name = variableNameToPropertyName(name, VariableKind.PARAMETER); String[] names = getSuggestionsByName(name, variableKind, false, correctKeywords); if (expressions.length == 1) { final String methodName = method.getName(); String[] words = NameUtil.nameToWords(methodName); if (words.length > 0) { final String firstWord = words[0]; if (SET_PREFIX.equals(firstWord)) { final String propertyName = methodName.substring(firstWord.length()); final String[] setterNames = getSuggestionsByName(propertyName, variableKind, false, correctKeywords); names = ArrayUtil.mergeArrays(names, setterNames); } } } return new NamesByExprInfo(name, names); } } } } else if (expr.getParent() instanceof PsiAssignmentExpression && variableKind == VariableKind.PARAMETER) { final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression) expr.getParent(); if (expr == assignmentExpression.getRExpression()) { final PsiExpression leftExpression = assignmentExpression.getLExpression(); if (leftExpression instanceof PsiReferenceExpression && ((PsiReferenceExpression) leftExpression).getQualifier() == null) { String name = leftExpression.getText(); if (name != null) { final PsiElement resolve = ((PsiReferenceExpression) leftExpression).resolve(); if (resolve instanceof PsiVariable) { name = variableNameToPropertyName(name, getVariableKind((PsiVariable) resolve)); } String[] names = getSuggestionsByName(name, variableKind, false, correctKeywords); return new NamesByExprInfo(name, names); } } } } return new NamesByExprInfo(null, ArrayUtil.EMPTY_STRING_ARRAY); }
protected boolean findNewParamsPlace( PsiExpression[] expressions, PsiMethod targetMethod, PsiSubstitutor substitutor, StringBuilder buf, HashSet<ParameterInfoImpl> newParams, PsiParameter[] parameters, List<ParameterInfoImpl> result) { // find which parameters to introduce and where Set<String> existingNames = new HashSet<String>(); for (PsiParameter parameter : parameters) { existingNames.add(parameter.getName()); } int ei = 0; int pi = 0; PsiParameter varargParam = targetMethod.isVarArgs() ? parameters[parameters.length - 1] : null; while (ei < expressions.length || pi < parameters.length) { if (buf.length() > 0) buf.append(", "); PsiExpression expression = ei < expressions.length ? expressions[ei] : null; PsiParameter parameter = pi < parameters.length ? parameters[pi] : null; PsiType paramType = parameter == null ? null : substitutor.substitute(parameter.getType()); boolean parameterAssignable = paramType != null && (expression == null || TypeConversionUtil.areTypesAssignmentCompatible(paramType, expression)); if (parameterAssignable) { final PsiType type = parameter.getType(); result.add(new ParameterInfoImpl(pi, parameter.getName(), type)); buf.append(escapePresentableType(type)); pi++; ei++; } else if (isArgumentInVarargPosition(expressions, ei, varargParam, substitutor)) { if (pi == parameters.length - 1) { assert varargParam != null; final PsiType type = varargParam.getType(); result.add(new ParameterInfoImpl(pi, varargParam.getName(), type)); buf.append(escapePresentableType(type)); } pi++; ei++; } else if (expression != null) { if (varargParam != null && pi >= parameters.length) return false; if (PsiPolyExpressionUtil.isPolyExpression(expression)) return false; PsiType exprType = RefactoringUtil.getTypeByExpression(expression); if (exprType == null) return false; if (exprType instanceof PsiDisjunctionType) { exprType = ((PsiDisjunctionType) exprType).getLeastUpperBound(); } JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(expression.getProject()); String name = suggestUniqueParameterName(codeStyleManager, expression, exprType, existingNames); final ParameterInfoImpl newParameterInfo = new ParameterInfoImpl(-1, name, exprType, expression.getText().replace('\n', ' ')); result.add(newParameterInfo); newParams.add(newParameterInfo); buf.append("<b>").append(escapePresentableType(exprType)).append("</b>"); ei++; } } if (result.size() != expressions.length && varargParam == null) return false; return true; }
private ParameterInfoImpl[] getNewParametersInfo( PsiExpression[] expressions, PsiMethod targetMethod, PsiSubstitutor substitutor, final StringBuilder buf, final HashSet<ParameterInfoImpl> newParams, final HashSet<ParameterInfoImpl> removedParams, final HashSet<ParameterInfoImpl> changedParams) { PsiParameter[] parameters = targetMethod.getParameterList().getParameters(); List<ParameterInfoImpl> result = new ArrayList<ParameterInfoImpl>(); if (expressions.length < parameters.length) { // find which parameters to remove int ei = 0; int pi = 0; while (ei < expressions.length && pi < parameters.length) { PsiExpression expression = expressions[ei]; PsiParameter parameter = parameters[pi]; PsiType paramType = substitutor.substitute(parameter.getType()); if (buf.length() > 0) buf.append(", "); final PsiType parameterType = PsiUtil.convertAnonymousToBaseType(paramType); final String presentableText = escapePresentableType(parameterType); final ParameterInfoImpl parameterInfo = new ParameterInfoImpl(pi, parameter.getName(), parameter.getType()); if (TypeConversionUtil.areTypesAssignmentCompatible(paramType, expression)) { buf.append(presentableText); result.add(parameterInfo); pi++; ei++; } else { buf.append("<s>").append(presentableText).append("</s>"); removedParams.add(parameterInfo); pi++; } } if (result.size() != expressions.length) return null; for (int i = pi; i < parameters.length; i++) { if (buf.length() > 0) buf.append(", "); buf.append("<s>").append(escapePresentableType(parameters[i].getType())).append("</s>"); final ParameterInfoImpl parameterInfo = new ParameterInfoImpl(pi, parameters[i].getName(), parameters[i].getType()); removedParams.add(parameterInfo); } } else if (expressions.length > parameters.length) { if (!findNewParamsPlace( expressions, targetMethod, substitutor, buf, newParams, parameters, result)) return null; } else { // parameter type changed for (int i = 0; i < parameters.length; i++) { if (buf.length() > 0) buf.append(", "); PsiParameter parameter = parameters[i]; PsiExpression expression = expressions[i]; PsiType paramType = substitutor.substitute(parameter.getType()); final String presentableText = escapePresentableType(paramType); if (TypeConversionUtil.areTypesAssignmentCompatible(paramType, expression)) { result.add(new ParameterInfoImpl(i, parameter.getName(), paramType)); buf.append(presentableText); } else { if (PsiPolyExpressionUtil.isPolyExpression(expression)) return null; PsiType exprType = RefactoringUtil.getTypeByExpression(expression); if (exprType == null) return null; if (exprType instanceof PsiDisjunctionType) { exprType = ((PsiDisjunctionType) exprType).getLeastUpperBound(); } final ParameterInfoImpl changedParameterInfo = new ParameterInfoImpl(i, parameter.getName(), exprType); result.add(changedParameterInfo); changedParams.add(changedParameterInfo); buf.append("<s>") .append(presentableText) .append("</s> <b>") .append(escapePresentableType(exprType)) .append("</b>"); } } // do not perform silly refactorings boolean isSilly = true; for (int i = 0; i < result.size(); i++) { PsiParameter parameter = parameters[i]; PsiType paramType = substitutor.substitute(parameter.getType()); ParameterInfoImpl parameterInfo = result.get(i); String typeText = parameterInfo.getTypeText(); if (!paramType.equalsToText(typeText) && !paramType.getPresentableText().equals(typeText)) { isSilly = false; break; } } if (isSilly) return null; } return result.toArray(new ParameterInfoImpl[result.size()]); }