protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) { final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>(); checkExistingMethods(conflicts, true); checkExistingMethods(conflicts, false); final Collection<PsiClass> classes = ClassInheritorsSearch.search(myClass).findAll(); for (FieldDescriptor fieldDescriptor : myFieldDescriptors) { final Set<PsiMethod> setters = new HashSet<PsiMethod>(); final Set<PsiMethod> getters = new HashSet<PsiMethod>(); for (PsiClass aClass : classes) { final PsiMethod getterOverrider = myDescriptor.isToEncapsulateGet() ? aClass.findMethodBySignature(fieldDescriptor.getGetterPrototype(), false) : null; if (getterOverrider != null) { getters.add(getterOverrider); } final PsiMethod setterOverrider = myDescriptor.isToEncapsulateSet() ? aClass.findMethodBySignature(fieldDescriptor.getSetterPrototype(), false) : null; if (setterOverrider != null) { setters.add(setterOverrider); } } if (!getters.isEmpty() || !setters.isEmpty()) { final PsiField field = fieldDescriptor.getField(); for (PsiReference reference : ReferencesSearch.search(field)) { final PsiElement place = reference.getElement(); if (place instanceof PsiReferenceExpression) { final PsiExpression qualifierExpression = ((PsiReferenceExpression) place).getQualifierExpression(); final PsiClass ancestor; if (qualifierExpression == null) { ancestor = PsiTreeUtil.getParentOfType(place, PsiClass.class, false); } else { ancestor = PsiUtil.resolveClassInType(qualifierExpression.getType()); } final boolean isGetter = !PsiUtil.isAccessedForWriting((PsiExpression) place); for (PsiMethod overridden : isGetter ? getters : setters) { if (InheritanceUtil.isInheritorOrSelf(myClass, ancestor, true)) { conflicts.putValue( overridden, "There is already a " + RefactoringUIUtil.getDescription(overridden, true) + " which would hide generated " + (isGetter ? "getter" : "setter") + " for " + place.getText()); break; } } } } } } return showConflicts(conflicts, refUsages.get()); }
private static String createInitializerReplacementText( PsiType varType, PsiExpression initializer) { final PsiType initializerType = initializer.getType(); final PsiClassType rawType = initializerType instanceof PsiClassType ? ((PsiClassType) initializerType).rawType() : null; final PsiClassType rawVarType = varType instanceof PsiClassType ? ((PsiClassType) varType).rawType() : null; if (rawType != null && rawVarType != null && rawType.equalsToText(CommonClassNames.JAVA_UTIL_ARRAY_LIST) && rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_LIST)) { return "toList()"; } else if (rawType != null && rawVarType != null && rawType.equalsToText(CommonClassNames.JAVA_UTIL_HASH_SET) && rawVarType.equalsToText(CommonClassNames.JAVA_UTIL_SET)) { return "toSet()"; } else if (rawType != null) { return "toCollection(" + rawType.getClassName() + "::new)"; } else { return "toCollection(() -> " + initializer.getText() + ")"; } }
public static boolean isValidPropertyReference( @NotNull Project project, @NotNull PsiLiteralExpression expression, @NotNull String key, @NotNull Ref<String> outResourceBundle) { final HashMap<String, Object> annotationAttributeValues = new HashMap<String, Object>(); annotationAttributeValues.put(AnnotationUtil.PROPERTY_KEY_RESOURCE_BUNDLE_PARAMETER, null); if (mustBePropertyKey(project, expression, annotationAttributeValues)) { final Object resourceBundleName = annotationAttributeValues.get(AnnotationUtil.PROPERTY_KEY_RESOURCE_BUNDLE_PARAMETER); if (!(resourceBundleName instanceof PsiExpression)) { return false; } PsiExpression expr = (PsiExpression) resourceBundleName; final Object value = JavaPsiFacade.getInstance(expr.getProject()) .getConstantEvaluationHelper() .computeConstantExpression(expr); if (value == null) { return false; } String bundleName = value.toString(); outResourceBundle.set(bundleName); return isPropertyRef(expression, key, bundleName); } return true; }
private static boolean checkRawAcceptable( PsiLambdaExpression expression, PsiType functionalInterfaceType) { PsiElement parent = expression.getParent(); while (parent instanceof PsiParenthesizedExpression) { parent = parent.getParent(); } if (parent instanceof PsiExpressionList) { final PsiElement gParent = parent.getParent(); if (gParent instanceof PsiMethodCallExpression) { final PsiExpression qualifierExpression = ((PsiMethodCallExpression) gParent).getMethodExpression().getQualifierExpression(); final PsiType type = qualifierExpression != null ? qualifierExpression.getType() : null; if (type instanceof PsiClassType && ((PsiClassType) type).isRaw()) { return true; } final PsiMethod method = ((PsiMethodCallExpression) gParent).resolveMethod(); if (method != null) { int lambdaIdx = getLambdaIdx((PsiExpressionList) parent, expression); final PsiParameter[] parameters = method.getParameterList().getParameters(); final PsiType normalizedType = getNormalizedType(parameters[adjustLambdaIdx(lambdaIdx, method, parameters)]); if (normalizedType instanceof PsiClassType && ((PsiClassType) normalizedType).isRaw()) return true; } } if (functionalInterfaceType instanceof PsiClassType && ((PsiClassType) functionalInterfaceType).isRaw()) { return false; } } return true; }
private static boolean isCollectCall(PsiStatement body, final PsiParameter parameter) { PsiIfStatement ifStatement = extractIfStatement(body); final PsiMethodCallExpression methodCallExpression = extractAddCall(body, ifStatement); if (methodCallExpression != null) { final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); final PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); PsiClass qualifierClass = null; if (qualifierExpression instanceof PsiReferenceExpression) { if (ReferencesSearch.search(parameter, new LocalSearchScope(qualifierExpression)) .findFirst() != null) { return false; } final PsiElement resolve = ((PsiReferenceExpression) qualifierExpression).resolve(); if (resolve instanceof PsiVariable) { if (ReferencesSearch.search( resolve, new LocalSearchScope(methodCallExpression.getArgumentList())) .findFirst() != null) { return false; } } qualifierClass = PsiUtil.resolveClassInType(qualifierExpression.getType()); } else if (qualifierExpression == null) { final PsiClass enclosingClass = PsiTreeUtil.getParentOfType(body, PsiClass.class); if (PsiUtil.getEnclosingStaticElement(body, enclosingClass) == null) { qualifierClass = enclosingClass; } } if (qualifierClass != null && InheritanceUtil.isInheritor( qualifierClass, false, CommonClassNames.JAVA_UTIL_COLLECTION)) { while (ifStatement != null && PsiTreeUtil.isAncestor(body, ifStatement, false)) { final PsiExpression condition = ifStatement.getCondition(); if (condition != null && isConditionDependsOnUpdatedCollections(condition, qualifierExpression)) return false; ifStatement = PsiTreeUtil.getParentOfType(ifStatement, PsiIfStatement.class); } final PsiElement resolve = methodExpression.resolve(); if (resolve instanceof PsiMethod && "add".equals(((PsiMethod) resolve).getName()) && ((PsiMethod) resolve).getParameterList().getParametersCount() == 1) { final PsiExpression[] args = methodCallExpression.getArgumentList().getExpressions(); if (args.length == 1) { if (args[0] instanceof PsiCallExpression) { final PsiMethod method = ((PsiCallExpression) args[0]).resolveMethod(); return method != null && !method.hasTypeParameters() && !isThrowsCompatible(method); } return true; } } } } return false; }
private static String getIteratedValueText(PsiExpression iteratedValue) { return iteratedValue instanceof PsiCallExpression || iteratedValue instanceof PsiReferenceExpression || iteratedValue instanceof PsiQualifiedExpression || iteratedValue instanceof PsiParenthesizedExpression ? iteratedValue.getText() : "(" + iteratedValue.getText() + ")"; }
@Nullable private String[] suggestVariableNameFromLiterals( PsiExpression expr, VariableKind variableKind, boolean correctKeywords) { final PsiElement[] literals = PsiTreeUtil.collectElements( expr, new PsiElementFilter() { @Override public boolean isAccepted(PsiElement element) { if (isStringPsiLiteral(element) && StringUtil.isJavaIdentifier(StringUtil.unquoteString(element.getText()))) { final PsiElement exprList = element.getParent(); if (exprList instanceof PsiExpressionList) { final PsiElement call = exprList.getParent(); if (call instanceof PsiNewExpression) { return true; } else if (call instanceof PsiMethodCallExpression) { // TODO: exclude or not getA().getB("name").getC(); or // getA(getB("name").getC()); It works fine for now in the most cases return true; } } } return false; } }); if (literals.length == 1) { final String text = StringUtil.unquoteString(literals[0].getText()); return getSuggestionsByName( text, variableKind, expr.getType() instanceof PsiArrayType, correctKeywords); } return null; }
private static String compoundLambdaOrMethodReference( PsiParameter parameter, PsiExpression expression, String samQualifiedName, PsiType[] samParamTypes) { String result = ""; final Project project = parameter.getProject(); final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); final PsiClass functionClass = psiFacade.findClass(samQualifiedName, GlobalSearchScope.allScope(project)); for (int i = 0; i < samParamTypes.length; i++) { if (samParamTypes[i] instanceof PsiPrimitiveType) { samParamTypes[i] = ((PsiPrimitiveType) samParamTypes[i]).getBoxedType(expression); } } final PsiClassType functionalInterfaceType = functionClass != null ? psiFacade.getElementFactory().createType(functionClass, samParamTypes) : null; final PsiParameter[] parameters = {parameter}; final String methodReferenceText = LambdaCanBeMethodReferenceInspection.convertToMethodReference( expression, parameters, functionalInterfaceType, null); if (methodReferenceText != null) { LOG.assertTrue(functionalInterfaceType != null); result += "(" + functionalInterfaceType.getCanonicalText() + ")" + methodReferenceText; } else { result += parameter.getName() + " -> " + expression.getText(); } return result; }
private NamesByExprInfo suggestVariableNameByExpression( PsiExpression expr, VariableKind variableKind, boolean correctKeywords) { final LinkedHashSet<String> names = new LinkedHashSet<String>(); final String[] fromLiterals = suggestVariableNameFromLiterals(expr, variableKind, correctKeywords); if (fromLiterals != null) { ContainerUtil.addAll(names, fromLiterals); } ContainerUtil.addAll( names, suggestVariableNameByExpressionOnly(expr, variableKind, correctKeywords, false).names); ContainerUtil.addAll( names, suggestVariableNameByExpressionPlace(expr, variableKind, correctKeywords).names); PsiType type = expr.getType(); if (type != null) { ContainerUtil.addAll(names, suggestVariableNameByType(type, variableKind, correctKeywords)); } ContainerUtil.addAll( names, suggestVariableNameByExpressionOnly(expr, variableKind, correctKeywords, true).names); String[] namesArray = ArrayUtil.toStringArray(names); String propertyName = suggestVariableNameByExpressionOnly(expr, variableKind, correctKeywords, false).propertyName != null ? suggestVariableNameByExpressionOnly(expr, variableKind, correctKeywords, false) .propertyName : suggestVariableNameByExpressionPlace(expr, variableKind, correctKeywords) .propertyName; return new NamesByExprInfo(propertyName, namesArray); }
private static boolean isGoodExpression( PsiExpression expression, @NotNull AllowedValues allowedValues, @NotNull PsiElement scope, @NotNull PsiManager manager) { expression = PsiUtil.deparenthesizeExpression(expression); if (expression == null) return true; if (expression instanceof PsiConditionalExpression) { PsiExpression thenExpression = ((PsiConditionalExpression) expression).getThenExpression(); boolean thenAllowed = thenExpression == null || isAllowed(scope, thenExpression, allowedValues, manager); if (!thenAllowed) return false; PsiExpression elseExpression = ((PsiConditionalExpression) expression).getElseExpression(); return elseExpression == null || isAllowed(scope, elseExpression, allowedValues, manager); } if (isOneOf(expression, allowedValues, manager)) return true; if (allowedValues.canBeOred) { PsiExpression zero = getLiteralExpression(expression, manager, "0"); if (same(expression, zero, manager)) return true; PsiExpression mOne = getLiteralExpression(expression, manager, "-1"); if (same(expression, mOne, manager)) return true; if (expression instanceof PsiPolyadicExpression) { IElementType tokenType = ((PsiPolyadicExpression) expression).getOperationTokenType(); if (JavaTokenType.OR.equals(tokenType) || JavaTokenType.AND.equals(tokenType)) { for (PsiExpression operand : ((PsiPolyadicExpression) expression).getOperands()) { if (!isAllowed(scope, operand, allowedValues, manager)) return false; } return true; } } if (expression instanceof PsiPrefixExpression && JavaTokenType.TILDE.equals( ((PsiPrefixExpression) expression).getOperationTokenType())) { PsiExpression operand = ((PsiPrefixExpression) expression).getOperand(); return operand == null || isAllowed(scope, operand, allowedValues, manager); } } PsiElement resolved = null; if (expression instanceof PsiReference) { resolved = ((PsiReference) expression).resolve(); } else if (expression instanceof PsiCallExpression) { resolved = ((PsiCallExpression) expression).resolveMethod(); } AllowedValues allowedForRef; if (resolved instanceof PsiModifierListOwner && (allowedForRef = getAllowedValues( (PsiModifierListOwner) resolved, getType((PsiModifierListOwner) resolved), null)) != null && allowedForRef.isSubsetOf(allowedValues, manager)) return true; return PsiType.NULL.equals(expression.getType()); }
@Override public SuggestedNameInfo suggestVariableName( @NotNull final VariableKind kind, @Nullable final String propertyName, @Nullable final PsiExpression expr, @Nullable PsiType type, final boolean correctKeywords) { LinkedHashSet<String> names = new LinkedHashSet<String>(); if (expr != null && type == null) { type = expr.getType(); } if (propertyName != null) { String[] namesByName = getSuggestionsByName(propertyName, kind, false, correctKeywords); sortVariableNameSuggestions(namesByName, kind, propertyName, null); ContainerUtil.addAll(names, namesByName); } final NamesByExprInfo namesByExpr; if (expr != null) { namesByExpr = suggestVariableNameByExpression(expr, kind, correctKeywords); if (namesByExpr.propertyName != null) { sortVariableNameSuggestions(namesByExpr.names, kind, namesByExpr.propertyName, null); } ContainerUtil.addAll(names, namesByExpr.names); } else { namesByExpr = null; } if (type != null) { String[] namesByType = suggestVariableNameByType(type, kind, correctKeywords); sortVariableNameSuggestions(namesByType, kind, null, type); ContainerUtil.addAll(names, namesByType); } final String _propertyName; if (propertyName != null) { _propertyName = propertyName; } else { _propertyName = namesByExpr != null ? namesByExpr.propertyName : null; } addNamesFromStatistics(names, kind, _propertyName, type); String[] namesArray = ArrayUtil.toStringArray(names); sortVariableNameSuggestions(namesArray, kind, _propertyName, type); final PsiType _type = type; return new SuggestedNameInfo(namesArray) { @Override public void nameChosen(String name) { if (_propertyName != null || _type != null && _type.isValid()) { JavaStatisticsManager.incVariableNameUseCount(name, kind, _propertyName, _type); } } }; }
private static void checkExpression( PsiExpression expression, PsiModifierListOwner owner, PsiType type, ProblemsHolder holder) { AllowedValues allowed = getAllowedValues(owner, type, null); if (allowed == null) return; PsiElement scope = PsiUtil.getTopLevelEnclosingCodeBlock(expression, null); if (scope == null) scope = expression; if (!isAllowed(scope, expression, allowed, expression.getManager())) { registerProblem(expression, allowed, holder); } }
public static Set<String> suggestExpressionOfType( final PsiClassType type, final PsiLiteralExpression context) { PsiVariable[] variables = MacroUtil.getVariablesVisibleAt(context, ""); Set<String> result = new LinkedHashSet<String>(); for (PsiVariable var : variables) { PsiType varType = var.getType(); if (type == null || type.isAssignableFrom(varType)) { result.add(var.getNameIdentifier().getText()); } } PsiExpression[] expressions = MacroUtil.getStandardExpressionsOfType(context, type); for (PsiExpression expression : expressions) { result.add(expression.getText()); } if (type != null) { addAvailableMethodsOfType(type, context, result); } return result; }
@NotNull private static PsiExpression getTopLevel(Project project, @NotNull PsiExpression expression) { int i = 0; while (expression.getParent() instanceof PsiExpression) { i++; final PsiExpression parent = (PsiExpression) expression.getParent(); if (parent instanceof PsiConditionalExpression && ((PsiConditionalExpression) parent).getCondition() == expression) break; expression = parent; if (expression instanceof PsiAssignmentExpression) break; if (i > 10 && expression instanceof PsiBinaryExpression) { ParameterizedCachedValue<PsiExpression, Pair<Project, PsiExpression>> value = expression.getUserData(TOP_LEVEL_EXPRESSION); if (value != null && value.hasUpToDateValue()) { return getToplevelExpression( project, expression); // optimization: use caching for big hierarchies } } } return expression; }
private static void checkMagicParameterArgument( @NotNull PsiParameter parameter, PsiExpression argument, @NotNull AllowedValues allowedValues, @NotNull ProblemsHolder holder) { final PsiManager manager = PsiManager.getInstance(holder.getProject()); if (!argument.getTextRange().isEmpty() && !isAllowed(parameter.getDeclarationScope(), argument, allowedValues, manager)) { registerProblem(argument, allowedValues, holder); } }
@Nullable private static PsiType getQualifierCastType( PsiJavaReference javaReference, CompletionParameters parameters) { if (javaReference instanceof PsiReferenceExpression) { final PsiReferenceExpression refExpr = (PsiReferenceExpression) javaReference; final PsiExpression qualifier = refExpr.getQualifierExpression(); if (qualifier != null) { final Project project = qualifier.getProject(); PsiType type = null; final PairFunction<PsiExpression, CompletionParameters, PsiType> evaluator = refExpr.getContainingFile().getCopyableUserData(DYNAMIC_TYPE_EVALUATOR); if (evaluator != null) { type = evaluator.fun(qualifier, parameters); } if (type == null) { type = GuessManager.getInstance(project).getControlFlowExpressionType(qualifier); } return type; } } return null; }
@Override public CachedValueProvider.Result<PsiExpression> compute( Pair<Project, PsiExpression> pair) { PsiExpression param = pair.second; Project project = pair.first; PsiExpression topLevel = getTopLevel(project, param); ParameterizedCachedValue<PsiExpression, Pair<Project, PsiExpression>> cachedValue = param.getUserData(TOP_LEVEL_EXPRESSION); assert cachedValue != null; int i = 0; for (PsiElement element = param; element != topLevel; element = element.getParent(), i++) { if (i % 10 == 0) { // optimization: store up link to the top level expression in each 10nth // element element.putUserData(TOP_LEVEL_EXPRESSION, cachedValue); } } return CachedValueProvider.Result.create( topLevel, PsiManager.getInstance(project).getModificationTracker()); }
private void checkForSuperCall(PsiMethod method) { if (isConstructor()) { PsiCodeBlock body = method.getBody(); if (body == null) return; PsiStatement[] statements = body.getStatements(); boolean isBaseExplicitlyCalled = false; if (statements.length > 0) { PsiStatement first = statements[0]; if (first instanceof PsiExpressionStatement) { PsiExpression firstExpression = ((PsiExpressionStatement) first).getExpression(); if (firstExpression instanceof PsiMethodCallExpression) { PsiExpression qualifierExpression = ((PsiMethodCallExpression) firstExpression) .getMethodExpression() .getQualifierExpression(); if (qualifierExpression instanceof PsiReferenceExpression) { @NonNls String text = qualifierExpression.getText(); if ("super".equals(text) || text.equals("this")) { isBaseExplicitlyCalled = true; } } } } } if (!isBaseExplicitlyCalled) { for (RefClass superClass : getOwnerClass().getBaseClasses()) { RefMethodImpl superDefaultConstructor = (RefMethodImpl) superClass.getDefaultConstructor(); if (superDefaultConstructor != null) { superDefaultConstructor.addInReference(this); addOutReference(superDefaultConstructor); } } } } }
@NotNull public static PsiExpression getToplevelExpression( @NotNull final Project project, @NotNull final PsiExpression expression) { if (expression instanceof PsiBinaryExpression || expression.getParent() instanceof PsiBinaryExpression) { // can be large, cache return CachedValuesManager.getManager(project) .getParameterizedCachedValue( expression, TOP_LEVEL_EXPRESSION, TOP_LEVEL_PROVIDER, true, Pair.create(project, expression)); } return getTopLevel(project, expression); }
private static String createMapperFunctionalExpressionText( PsiParameter parameter, PsiExpression expression) { String iteration = ""; if (!isIdentityMapping(parameter, expression)) { iteration += ".map("; iteration += compoundLambdaOrMethodReference( parameter, expression, "java.util.function.Function", new PsiType[] {parameter.getType(), expression.getType()}); iteration += ")"; } return iteration; }
@NotNull public static QualifierResolveResult getQualifierResolveResult( @NotNull PsiMethodReferenceExpression methodReferenceExpression) { PsiClass containingClass = null; PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; final PsiExpression expression = methodReferenceExpression.getQualifierExpression(); if (expression != null) { final PsiType expressionType = getExpandedType(expression.getType(), expression); PsiClassType.ClassResolveResult result = PsiUtil.resolveGenericsClassInType(expressionType); containingClass = result.getElement(); if (containingClass != null) { substitutor = result.getSubstitutor(); } if (containingClass == null && expression instanceof PsiReferenceExpression) { final JavaResolveResult resolveResult = ((PsiReferenceExpression) expression).advancedResolve(false); final PsiElement resolve = resolveResult.getElement(); if (resolve instanceof PsiClass) { containingClass = (PsiClass) resolve; substitutor = resolveResult.getSubstitutor(); return new QualifierResolveResult(containingClass, substitutor, true); } } } else { final PsiTypeElement typeElement = methodReferenceExpression.getQualifierType(); if (typeElement != null) { PsiType type = getExpandedType(typeElement.getType(), typeElement); PsiClassType.ClassResolveResult result = PsiUtil.resolveGenericsClassInType(type); containingClass = result.getElement(); if (containingClass != null) { return new QualifierResolveResult(containingClass, result.getSubstitutor(), true); } } } return new QualifierResolveResult(containingClass, substitutor, false); }
private static boolean isConditionDependsOnUpdatedCollections( PsiExpression condition, PsiExpression qualifierExpression) { final PsiElement collection = qualifierExpression instanceof PsiReferenceExpression ? ((PsiReferenceExpression) qualifierExpression).resolve() : null; if (collection != null) { return ReferencesSearch.search(collection, new LocalSearchScope(condition)).findFirst() != null; } final boolean[] dependsOnCollection = {false}; condition.accept( new JavaRecursiveElementWalkingVisitor() { @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) { super.visitMethodCallExpression(expression); final PsiExpression callQualifier = expression.getMethodExpression().getQualifierExpression(); if (callQualifier == null || callQualifier instanceof PsiThisExpression && ((PsiThisExpression) callQualifier).getQualifier() == null || callQualifier instanceof PsiSuperExpression && ((PsiSuperExpression) callQualifier).getQualifier() == null) { dependsOnCollection[0] = true; } } @Override public void visitThisExpression(PsiThisExpression expression) { super.visitThisExpression(expression); if (expression.getQualifier() == null && expression.getParent() instanceof PsiExpressionList) { dependsOnCollection[0] = true; } } @Override public void visitClass(PsiClass aClass) {} @Override public void visitLambdaExpression(PsiLambdaExpression expression) {} }); return dependsOnCollection[0]; }
public static boolean isPassedToAnnotatedParam( @NotNull Project project, @NotNull PsiExpression expression, final String annFqn, @Nullable Map<String, Object> annotationAttributeValues, @Nullable final Set<PsiModifierListOwner> nonNlsTargets) { expression = getToplevelExpression(project, expression); final PsiElement parent = expression.getParent(); if (!(parent instanceof PsiExpressionList)) return false; int idx = -1; final PsiExpression[] args = ((PsiExpressionList) parent).getExpressions(); for (int i = 0; i < args.length; i++) { PsiExpression arg = args[i]; if (PsiTreeUtil.isAncestor(arg, expression, false)) { idx = i; break; } } if (idx == -1) return false; PsiElement grParent = parent.getParent(); if (grParent instanceof PsiAnonymousClass) { grParent = grParent.getParent(); } if (grParent instanceof PsiCall) { PsiMethod method = ((PsiCall) grParent).resolveMethod(); if (method != null && isMethodParameterAnnotatedWith( method, idx, null, annFqn, annotationAttributeValues, nonNlsTargets)) { return true; } } return false; }
private static boolean processValuesFlownTo( @NotNull final PsiExpression argument, PsiElement scope, @NotNull final Processor<PsiExpression> processor) { SliceAnalysisParams params = new SliceAnalysisParams(); params.dataFlowToThis = true; params.scope = new AnalysisScope(new LocalSearchScope(scope), argument.getProject()); SliceRootNode rootNode = new SliceRootNode( scope.getProject(), new DuplicateMap(), SliceManager.createRootUsage(argument, params)); Collection<? extends AbstractTreeNode> children = rootNode.getChildren().iterator().next().getChildren(); for (AbstractTreeNode child : children) { SliceUsage usage = (SliceUsage) child.getValue(); PsiElement element = usage.getElement(); if (element instanceof PsiExpression && !processor.process((PsiExpression) element)) return false; } return !children.isEmpty(); }
protected void checkSameSignatures(@NotNull List<CandidateInfo> conflicts) { // candidates should go in order of class hierarchy traversal // in order for this to work Map<MethodSignature, CandidateInfo> signatures = new THashMap<MethodSignature, CandidateInfo>(conflicts.size()); Set<PsiMethod> superMethods = new HashSet<PsiMethod>(); for (CandidateInfo conflict : conflicts) { final PsiMethod method = ((MethodCandidateInfo) conflict).getElement(); for (HierarchicalMethodSignature methodSignature : method.getHierarchicalMethodSignature().getSuperSignatures()) { final PsiMethod superMethod = methodSignature.getMethod(); final PsiClass aClass = superMethod.getContainingClass(); if (aClass != null && !CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) { superMethods.add(superMethod); } } } nextConflict: for (int i = 0; i < conflicts.size(); i++) { ProgressManager.checkCanceled(); CandidateInfo info = conflicts.get(i); PsiMethod method = (PsiMethod) info.getElement(); if (!method.hasModifierProperty(PsiModifier.STATIC) && superMethods.contains(method)) { conflicts.remove(i); i--; continue; } PsiClass class1 = method.getContainingClass(); PsiSubstitutor infoSubstitutor = ((MethodCandidateInfo) info).getSubstitutor(false); MethodSignature signature = method.getSignature(infoSubstitutor); CandidateInfo existing = signatures.get(signature); if (existing == null) { signatures.put(signature, info); continue; } PsiMethod existingMethod = (PsiMethod) existing.getElement(); PsiClass existingClass = existingMethod.getContainingClass(); if (class1 != null && existingClass != null) { // prefer interface methods to methods from Object if (class1.isInterface() && CommonClassNames.JAVA_LANG_OBJECT.equals(existingClass.getQualifiedName())) { signatures.put(signature, info); continue; } else if (existingClass.isInterface() && CommonClassNames.JAVA_LANG_OBJECT.equals(class1.getQualifiedName())) { conflicts.remove(info); i--; continue; } } if (method == existingMethod) { PsiElement scope1 = info.getCurrentFileResolveScope(); PsiElement scope2 = existing.getCurrentFileResolveScope(); if (scope1 instanceof PsiClass && scope2 instanceof PsiClass && PsiTreeUtil.isAncestor(scope1, scope2, true) && !existing .isAccessible()) { // prefer methods from outer class to inaccessible base class // methods signatures.put(signature, info); continue; } } // filter out methods with incorrect inferred bounds (for unrelated methods only) boolean existingTypeParamAgree = areTypeParametersAgree(existing); boolean infoTypeParamAgree = areTypeParametersAgree(info); if (existingTypeParamAgree && !infoTypeParamAgree && !PsiSuperMethodImplUtil.isSuperMethodSmart(method, existingMethod)) { conflicts.remove(i); i--; continue; } if (!existingTypeParamAgree && infoTypeParamAgree && !PsiSuperMethodImplUtil.isSuperMethodSmart(existingMethod, method)) { signatures.put(signature, info); int index = conflicts.indexOf(existing); conflicts.remove(index); i--; continue; } if (InheritanceUtil.isInheritorOrSelf(class1, existingClass, true) || InheritanceUtil.isInheritorOrSelf(existingClass, class1, true)) { PsiParameter[] parameters = method.getParameterList().getParameters(); final PsiParameter[] existingParameters = existingMethod.getParameterList().getParameters(); for (int i1 = 0, parametersLength = parameters.length; i1 < parametersLength; i1++) { if (parameters[i1].getType() instanceof PsiArrayType && !(existingParameters[i1].getType() instanceof PsiArrayType)) { // prefer more specific type signatures.put(signature, info); continue nextConflict; } } PsiType returnType1 = method.getReturnType(); PsiType returnType2 = existingMethod.getReturnType(); if (returnType1 != null && returnType2 != null) { returnType1 = infoSubstitutor.substitute(returnType1); returnType2 = ((MethodCandidateInfo) existing).getSubstitutor(false).substitute(returnType2); if (!returnType1.equals(returnType2) && returnType1.isAssignableFrom(returnType2)) { conflicts.remove(i); i--; continue; } } // prefer derived class signatures.put(signature, info); } else { final PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(myArgumentsList, PsiMethodCallExpression.class); if (methodCallExpression != null) { final PsiReferenceExpression expression = methodCallExpression.getMethodExpression(); final PsiExpression qualifierExpression = expression.getQualifierExpression(); PsiClass currentClass; if (qualifierExpression != null) { currentClass = PsiUtil.resolveClassInClassTypeOnly(qualifierExpression.getType()); } else { currentClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class); } if (currentClass != null && existingClass != null && class1 != null) { final PsiSubstitutor eSubstitutor = TypeConversionUtil.getMaybeSuperClassSubstitutor( existingClass, currentClass, PsiSubstitutor.EMPTY, null); final PsiSubstitutor cSubstitutor = TypeConversionUtil.getMaybeSuperClassSubstitutor( class1, currentClass, PsiSubstitutor.EMPTY, null); if (eSubstitutor != null && cSubstitutor != null && MethodSignatureUtil.areSignaturesEqual( existingMethod.getSignature(eSubstitutor), method.getSignature(cSubstitutor))) { final PsiType returnType = eSubstitutor.substitute(existingMethod.getReturnType()); final PsiType returnType1 = cSubstitutor.substitute(method.getReturnType()); if (returnType != null && returnType1 != null && !returnType1.equals(returnType)) { if (TypeConversionUtil.isAssignable(returnType, returnType1, false)) { if (class1.isInterface() && !existingClass.isInterface()) continue; conflicts.remove(existing); } else { if (!TypeConversionUtil.isAssignable(returnType1, returnType, false)) continue; conflicts.remove(i); } i--; break; } } } } } } }
@Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { final PsiForeachStatement foreachStatement = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiForeachStatement.class); if (foreachStatement != null) { if (!FileModificationService.getInstance().preparePsiElementForWrite(foreachStatement)) return; final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); PsiStatement body = foreachStatement.getBody(); final PsiExpression iteratedValue = foreachStatement.getIteratedValue(); if (body != null && iteratedValue != null) { final PsiParameter parameter = foreachStatement.getIterationParameter(); final PsiIfStatement ifStatement = extractIfStatement(body); final PsiMethodCallExpression methodCallExpression = extractAddCall(body, ifStatement); if (methodCallExpression == null) return; if (isAddAllCall(foreachStatement, body)) { restoreComments(foreachStatement, body); final PsiExpression qualifierExpression = methodCallExpression.getMethodExpression().getQualifierExpression(); final String qualifierText = qualifierExpression != null ? qualifierExpression.getText() : ""; final String callText = StringUtil.getQualifiedName( qualifierText, "addAll(" + getIteratedValueText(iteratedValue) + ");"); PsiElement result = foreachStatement.replace( elementFactory.createStatementFromText(callText, foreachStatement)); reformatWhenNeeded(project, result); return; } final StringBuilder builder = new StringBuilder(getIteratedValueText(iteratedValue) + ".stream()"); builder.append(createFiltersChainText(body, parameter, ifStatement)); builder.append( createMapperFunctionalExpressionText( parameter, methodCallExpression.getArgumentList().getExpressions()[0])); builder.append(".collect(java.util.stream.Collectors."); PsiElement result = null; try { final PsiExpression qualifierExpression = methodCallExpression.getMethodExpression().getQualifierExpression(); if (qualifierExpression instanceof PsiReferenceExpression) { final PsiElement resolve = ((PsiReferenceExpression) qualifierExpression).resolve(); if (resolve instanceof PsiVariable) { if (resolve instanceof PsiLocalVariable && foreachStatement.equals( PsiTreeUtil.skipSiblingsForward( resolve.getParent(), PsiWhiteSpace.class))) { final PsiExpression initializer = ((PsiVariable) resolve).getInitializer(); if (initializer instanceof PsiNewExpression) { final PsiExpressionList argumentList = ((PsiNewExpression) initializer).getArgumentList(); if (argumentList != null && argumentList.getExpressions().length == 0) { restoreComments(foreachStatement, body); final String callText = builder.toString() + createInitializerReplacementText( ((PsiVariable) resolve).getType(), initializer) + ")"; result = initializer.replace( elementFactory.createExpressionFromText(callText, null)); simplifyRedundantCast(result); foreachStatement.delete(); return; } } } } } restoreComments(foreachStatement, body); final String qualifierText = qualifierExpression != null ? qualifierExpression.getText() : ""; final String callText = StringUtil.getQualifiedName( qualifierText, "addAll(" + builder.toString() + "toList()));"); result = foreachStatement.replace( elementFactory.createStatementFromText(callText, foreachStatement)); simplifyRedundantCast(result); } finally { reformatWhenNeeded(project, result); } } } }
private NamesByExprInfo suggestVariableNameByExpressionOnly( PsiExpression expr, final VariableKind variableKind, boolean correctKeywords, boolean useAllMethodNames) { if (expr instanceof PsiMethodCallExpression) { PsiReferenceExpression methodExpr = ((PsiMethodCallExpression) expr).getMethodExpression(); String methodName = methodExpr.getReferenceName(); if (methodName != null) { if ("of".equals(methodName) || "ofNullable".equals(methodName)) { if (isJavaUtilMethodCall((PsiMethodCallExpression) expr)) { PsiExpression[] expressions = ((PsiMethodCallExpression) expr).getArgumentList().getExpressions(); if (expressions.length > 0) { return suggestVariableNameByExpressionOnly( expressions[0], variableKind, correctKeywords, useAllMethodNames); } } } if ("map".equals(methodName) || "flatMap".equals(methodName) || "filter".equals(methodName)) { if (isJavaUtilMethodCall((PsiMethodCallExpression) expr)) { return new NamesByExprInfo(null); } } String[] words = NameUtil.nameToWords(methodName); if (words.length > 0) { final String firstWord = words[0]; if (GET_PREFIX.equals(firstWord) || IS_PREFIX.equals(firstWord) || FIND_PREFIX.equals(firstWord) || CREATE_PREFIX.equals(firstWord)) { if (words.length > 1) { final String propertyName = methodName.substring(firstWord.length()); String[] names = getSuggestionsByName(propertyName, variableKind, false, correctKeywords); final PsiExpression qualifierExpression = methodExpr.getQualifierExpression(); if (qualifierExpression instanceof PsiReferenceExpression && ((PsiReferenceExpression) qualifierExpression).resolve() instanceof PsiVariable) { names = ArrayUtil.append( names, StringUtil.sanitizeJavaIdentifier( changeIfNotIdentifier( qualifierExpression.getText() + StringUtil.capitalize(propertyName)))); } return new NamesByExprInfo(propertyName, names); } } else if (words.length == 1 || useAllMethodNames) { return new NamesByExprInfo( methodName, getSuggestionsByName(methodName, variableKind, false, correctKeywords)); } } } } else if (expr instanceof PsiReferenceExpression) { String propertyName = ((PsiReferenceExpression) expr).getReferenceName(); PsiElement refElement = ((PsiReferenceExpression) expr).resolve(); if (refElement instanceof PsiVariable) { VariableKind refVariableKind = getVariableKind((PsiVariable) refElement); propertyName = variableNameToPropertyName(propertyName, refVariableKind); } if (refElement != null && propertyName != null) { String[] names = getSuggestionsByName(propertyName, variableKind, false, correctKeywords); return new NamesByExprInfo(propertyName, names); } } else if (expr instanceof PsiArrayAccessExpression) { PsiExpression arrayExpr = ((PsiArrayAccessExpression) expr).getArrayExpression(); if (arrayExpr instanceof PsiReferenceExpression) { String arrayName = ((PsiReferenceExpression) arrayExpr).getReferenceName(); PsiElement refElement = ((PsiReferenceExpression) arrayExpr).resolve(); if (refElement instanceof PsiVariable) { VariableKind refVariableKind = getVariableKind((PsiVariable) refElement); arrayName = variableNameToPropertyName(arrayName, refVariableKind); } if (arrayName != null) { String name = StringUtil.unpluralize(arrayName); if (name != null) { String[] names = getSuggestionsByName(name, variableKind, false, correctKeywords); return new NamesByExprInfo(name, names); } } } } else if (expr instanceof PsiLiteralExpression && variableKind == VariableKind.STATIC_FINAL_FIELD) { final PsiLiteralExpression literalExpression = (PsiLiteralExpression) expr; final Object value = literalExpression.getValue(); if (value instanceof String) { final String stringValue = (String) value; String[] names = getSuggestionsByValue(stringValue); if (names.length > 0) { return new NamesByExprInfo(null, constantValueToConstantName(names)); } } } else if (expr instanceof PsiParenthesizedExpression) { return suggestVariableNameByExpressionOnly( ((PsiParenthesizedExpression) expr).getExpression(), variableKind, correctKeywords, useAllMethodNames); } else if (expr instanceof PsiTypeCastExpression) { return suggestVariableNameByExpressionOnly( ((PsiTypeCastExpression) expr).getOperand(), variableKind, correctKeywords, useAllMethodNames); } else if (expr instanceof PsiLiteralExpression) { final String text = StringUtil.stripQuotesAroundValue(expr.getText()); if (isIdentifier(text)) { return new NamesByExprInfo( text, getSuggestionsByName(text, variableKind, false, correctKeywords)); } } return new NamesByExprInfo(null, ArrayUtil.EMPTY_STRING_ARRAY); }
@Nullable public static String getSuspiciousMethodCallMessage( @NotNull PsiMethodCallExpression methodCall, PsiType argType, boolean reportConvertibleMethodCalls, @NotNull List<PsiMethod> patternMethods, @NotNull IntArrayList indices) { final PsiReferenceExpression methodExpression = methodCall.getMethodExpression(); final PsiExpression qualifier = methodExpression.getQualifierExpression(); if (qualifier == null || qualifier instanceof PsiThisExpression || qualifier instanceof PsiSuperExpression) return null; if (argType instanceof PsiPrimitiveType) { argType = ((PsiPrimitiveType) argType).getBoxedType(methodCall); } if (!(argType instanceof PsiClassType)) return null; final JavaResolveResult resolveResult = methodExpression.advancedResolve(false); PsiMethod calleeMethod = (PsiMethod) resolveResult.getElement(); if (calleeMethod == null) return null; PsiMethod contextMethod = PsiTreeUtil.getParentOfType(methodCall, PsiMethod.class); //noinspection SynchronizationOnLocalVariableOrMethodParameter synchronized (patternMethods) { if (patternMethods.isEmpty()) { setupPatternMethods( methodCall.getManager(), methodCall.getResolveScope(), patternMethods, indices); } } for (int i = 0; i < patternMethods.size(); i++) { PsiMethod patternMethod = patternMethods.get(i); if (!patternMethod.getName().equals(methodExpression.getReferenceName())) continue; int index = indices.get(i); // we are in collections method implementation if (contextMethod != null && isInheritorOrSelf(contextMethod, patternMethod)) return null; final PsiClass calleeClass = calleeMethod.getContainingClass(); PsiSubstitutor substitutor = resolveResult.getSubstitutor(); final PsiClass patternClass = patternMethod.getContainingClass(); assert patternClass != null; assert calleeClass != null; substitutor = TypeConversionUtil.getClassSubstitutor(patternClass, calleeClass, substitutor); if (substitutor == null) continue; if (!patternMethod .getSignature(substitutor) .equals(calleeMethod.getSignature(PsiSubstitutor.EMPTY))) continue; PsiTypeParameter[] typeParameters = patternClass.getTypeParameters(); if (typeParameters.length <= index) return null; final PsiTypeParameter typeParameter = typeParameters[index]; PsiType typeParamMapping = substitutor.substitute(typeParameter); if (typeParamMapping == null) return null; PsiParameter[] parameters = patternMethod.getParameterList().getParameters(); if (parameters.length == 1 && "removeAll".equals(patternMethod.getName())) { PsiType paramType = parameters[0].getType(); if (InheritanceUtil.isInheritor(paramType, CommonClassNames.JAVA_UTIL_COLLECTION)) { PsiType qualifierType = qualifier.getType(); if (qualifierType != null) { final PsiType itemType = JavaGenericsUtil.getCollectionItemType(argType, calleeMethod.getResolveScope()); final PsiType qualifierItemType = JavaGenericsUtil.getCollectionItemType( qualifierType, calleeMethod.getResolveScope()); if (qualifierItemType != null && itemType != null && !qualifierItemType.isAssignableFrom(itemType)) { return InspectionsBundle.message( "inspection.suspicious.collections.method.calls.problem.descriptor", PsiFormatUtil.formatType(qualifierType, 0, PsiSubstitutor.EMPTY), PsiFormatUtil.formatType(itemType, 0, PsiSubstitutor.EMPTY)); } } return null; } } String message = null; if (typeParamMapping instanceof PsiCapturedWildcardType) { typeParamMapping = ((PsiCapturedWildcardType) typeParamMapping).getWildcard(); } if (!typeParamMapping.isAssignableFrom(argType)) { if (typeParamMapping.isConvertibleFrom(argType)) { if (reportConvertibleMethodCalls) { message = InspectionsBundle.message( "inspection.suspicious.collections.method.calls.problem.descriptor1", PsiFormatUtil.formatMethod( calleeMethod, substitutor, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_CONTAINING_CLASS, PsiFormatUtilBase.SHOW_TYPE)); } } else { PsiType qualifierType = qualifier.getType(); if (qualifierType != null) { message = InspectionsBundle.message( "inspection.suspicious.collections.method.calls.problem.descriptor", PsiFormatUtil.formatType(qualifierType, 0, PsiSubstitutor.EMPTY), PsiFormatUtil.formatType(argType, 0, PsiSubstitutor.EMPTY)); } } } return message; } 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); }
private void checkExistingMethods(MultiMap<PsiElement, String> conflicts, boolean isGetter) { if (isGetter) { if (!myDescriptor.isToEncapsulateGet()) return; } else { if (!myDescriptor.isToEncapsulateSet()) return; } for (FieldDescriptor descriptor : myFieldDescriptors) { PsiMethod prototype = isGetter ? descriptor.getGetterPrototype() : descriptor.getSetterPrototype(); final PsiType prototypeReturnType = prototype.getReturnType(); PsiMethod existing = myClass.findMethodBySignature(prototype, true); if (existing != null) { final PsiType returnType = existing.getReturnType(); if (!RefactoringUtil.equivalentTypes( prototypeReturnType, returnType, myClass.getManager())) { final String descr = PsiFormatUtil.formatMethod( existing, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS | PsiFormatUtilBase.SHOW_TYPE, PsiFormatUtilBase.SHOW_TYPE); String message = isGetter ? RefactoringBundle.message( "encapsulate.fields.getter.exists", CommonRefactoringUtil.htmlEmphasize(descr), CommonRefactoringUtil.htmlEmphasize(prototype.getName())) : RefactoringBundle.message( "encapsulate.fields.setter.exists", CommonRefactoringUtil.htmlEmphasize(descr), CommonRefactoringUtil.htmlEmphasize(prototype.getName())); conflicts.putValue(existing, message); } } else { PsiClass containingClass = myClass.getContainingClass(); while (containingClass != null && existing == null) { existing = containingClass.findMethodBySignature(prototype, true); if (existing != null) { for (PsiReference reference : ReferencesSearch.search(existing)) { final PsiElement place = reference.getElement(); LOG.assertTrue(place instanceof PsiReferenceExpression); final PsiExpression qualifierExpression = ((PsiReferenceExpression) place).getQualifierExpression(); final PsiClass inheritor; if (qualifierExpression == null) { inheritor = PsiTreeUtil.getParentOfType(place, PsiClass.class, false); } else { inheritor = PsiUtil.resolveClassInType(qualifierExpression.getType()); } if (InheritanceUtil.isInheritorOrSelf(inheritor, myClass, true)) { conflicts.putValue( existing, "There is already a " + RefactoringUIUtil.getDescription(existing, true) + " which would be hidden by generated " + (isGetter ? "getter" : "setter")); break; } } } containingClass = containingClass.getContainingClass(); } } } }