private static void checkMethodCall(RefElement refWhat, final PsiElement element) { if (!(refWhat instanceof RefMethod)) return; final RefMethod refMethod = (RefMethod) refWhat; final PsiElement psiElement = refMethod.getElement(); if (!(psiElement instanceof PsiMethod)) return; final PsiMethod psiMethod = (PsiMethod) psiElement; if (!PsiType.BOOLEAN.equals(psiMethod.getReturnType())) return; element.accept( new JavaRecursiveElementWalkingVisitor() { @Override public void visitMethodCallExpression(PsiMethodCallExpression call) { super.visitMethodCallExpression(call); final PsiReferenceExpression methodExpression = call.getMethodExpression(); if (methodExpression.isReferenceTo(psiMethod)) { if (isInvertedMethodCall(methodExpression)) return; refMethod.putUserData(ALWAYS_INVERTED, Boolean.FALSE); } } @Override public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) { super.visitMethodReferenceExpression(expression); if (expression.isReferenceTo(psiElement)) { refMethod.putUserData(ALWAYS_INVERTED, Boolean.FALSE); } } }); }
private static boolean hasNonInvertedCalls(final RefMethod refMethod) { final Boolean alwaysInverted = refMethod.getUserData(ALWAYS_INVERTED); if (alwaysInverted == null) return true; if (refMethod.isExternalOverride()) return true; if (refMethod.isReferenced() && !alwaysInverted.booleanValue()) return true; final Collection<RefMethod> superMethods = refMethod.getSuperMethods(); for (RefMethod superMethod : superMethods) { if (hasNonInvertedCalls(superMethod)) return true; } return false; }
private static void clearUsedParameters( @NotNull RefMethod refMethod, RefParameter[] params, boolean checkDeep) { RefParameter[] methodParms = refMethod.getParameters(); for (int i = 0; i < methodParms.length; i++) { if (methodParms[i].isUsedForReading()) params[i] = null; } if (checkDeep) { for (RefMethod refOverride : refMethod.getDerivedMethods()) { clearUsedParameters(refOverride, params, checkDeep); } } }
@Override @Nullable public CommonProblemDescriptor[] checkElement( @NotNull final RefEntity refEntity, @NotNull final AnalysisScope scope, @NotNull final InspectionManager manager, @NotNull final GlobalInspectionContext globalContext, @NotNull final ProblemDescriptionsProcessor processor) { if (refEntity instanceof RefJavaElement) { final RefJavaElement refElement = (RefJavaElement) refEntity; if (refElement instanceof RefParameter) return null; if (!refElement.isReferenced()) return null; if (refElement.isSyntheticJSP()) return null; if (refElement.isFinal()) return null; if (!((RefElementImpl) refElement).checkFlag(CanBeFinalAnnotator.CAN_BE_FINAL_MASK)) return null; final PsiMember psiMember = (PsiMember) refElement.getElement(); if (psiMember == null || !CanBeFinalHandler.allowToBeFinal(psiMember)) return null; PsiIdentifier psiIdentifier = null; if (refElement instanceof RefClass) { RefClass refClass = (RefClass) refElement; if (refClass.isInterface() || refClass.isAnonymous() || refClass.isAbstract()) return null; if (!isReportClasses()) return null; psiIdentifier = ((PsiClass) psiMember).getNameIdentifier(); } else if (refElement instanceof RefMethod) { RefMethod refMethod = (RefMethod) refElement; if (refMethod.getOwnerClass().isFinal()) return null; if (!isReportMethods()) return null; psiIdentifier = ((PsiMethod) psiMember).getNameIdentifier(); } else if (refElement instanceof RefField) { if (!isReportFields()) return null; psiIdentifier = ((PsiField) psiMember).getNameIdentifier(); } if (psiIdentifier != null) { return new ProblemDescriptor[] { manager.createProblemDescriptor( psiIdentifier, InspectionsBundle.message("inspection.export.results.can.be.final.description"), new AcceptSuggested(globalContext.getRefManager()), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false) }; } } return null; }
public static ArrayList<RefParameter> getUnusedParameters(RefMethod refMethod) { boolean checkDeep = !refMethod.isStatic() && !refMethod.isConstructor(); ArrayList<RefParameter> res = new ArrayList<RefParameter>(); RefParameter[] methodParameters = refMethod.getParameters(); RefParameter[] result = new RefParameter[methodParameters.length]; System.arraycopy(methodParameters, 0, result, 0, methodParameters.length); clearUsedParameters(refMethod, result, checkDeep); for (RefParameter parameter : result) { if (parameter != null) { res.add(parameter); } } return res; }
private static void traverseSuperMethods( RefMethod refMethod, GlobalJavaInspectionContext globalContext, GlobalJavaInspectionContext.UsagesProcessor processor) { final Collection<RefMethod> superMethods = refMethod.getSuperMethods(); for (RefMethod superMethod : superMethods) { traverseSuperMethods(superMethod, globalContext, processor); } globalContext.enqueueMethodUsagesProcessor(refMethod, processor); }
@Override public CommonProblemDescriptor[] checkElement( @NotNull RefEntity refEntity, @NotNull AnalysisScope scope, @NotNull final InspectionManager manager, @NotNull final GlobalInspectionContext globalContext) { if (refEntity instanceof RefMethod) { RefMethod refMethod = (RefMethod) refEntity; if (!refMethod.isReferenced()) return null; if (hasNonInvertedCalls(refMethod)) return null; if (!refMethod.getSuperMethods().isEmpty()) return null; final PsiMethod psiMethod = (PsiMethod) refMethod.getElement(); final PsiIdentifier psiIdentifier = psiMethod.getNameIdentifier(); if (psiIdentifier != null) { final Collection<RefElement> inReferences = refMethod.getInReferences(); if (inReferences.size() == 1) { final RefElement refElement = inReferences.iterator().next(); final PsiElement usagesContainer = refElement.getElement(); if (usagesContainer == null) return null; if (ReferencesSearch.search(psiMethod, new LocalSearchScope(usagesContainer)) .forEach( new Processor<PsiReference>() { private final Set<PsiReference> myFoundRefs = new HashSet<>(); @Override public boolean process(PsiReference reference) { myFoundRefs.add(reference); return myFoundRefs.size() < 2; } })) return null; } return new ProblemDescriptor[] { manager.createProblemDescriptor( psiIdentifier, InspectionsBundle.message("boolean.method.is.always.inverted.problem.descriptor"), (LocalQuickFix) getQuickFix(null), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false) }; } } return null; }
private boolean isAccessible( RefJavaElement to, @PsiModifier.ModifierConstant String accessModifier) { for (RefElement refElement : to.getInReferences()) { if (!isAccessibleFrom(refElement, to, accessModifier)) return false; } if (to instanceof RefMethod) { RefMethod refMethod = (RefMethod) to; if (refMethod.isAbstract() && (refMethod.getDerivedMethods().isEmpty() || refMethod.getAccessModifier() == PsiModifier.PRIVATE)) return false; for (RefMethod refOverride : refMethod.getDerivedMethods()) { if (!isAccessibleFrom(refOverride, to, accessModifier)) return false; } for (RefMethod refSuper : refMethod.getSuperMethods()) { if (RefJavaUtil.getInstance().compareAccess(refSuper.getAccessModifier(), accessModifier) > 0) return false; } } if (to instanceof RefClass) { RefClass refClass = (RefClass) to; for (RefClass subClass : refClass.getSubClasses()) { if (!isAccessibleFrom(subClass, to, accessModifier)) return false; } List children = refClass.getChildren(); if (children != null) { for (Object refElement : children) { if (!isAccessible((RefJavaElement) refElement, accessModifier)) return false; } } for (final RefElement refElement : refClass.getInTypeReferences()) { if (!isAccessibleFrom(refElement, refClass, accessModifier)) return false; } List<RefJavaElement> classExporters = ((RefClassImpl) refClass).getClassExporters(); if (classExporters != null) { for (RefJavaElement refExporter : classExporters) { if (getAccessLevel(accessModifier) < getAccessLevel(refExporter.getAccessModifier())) return false; } } } return true; }
@Nullable public CommonProblemDescriptor[] checkElement( RefEntity refEntity, AnalysisScope scope, InspectionManager manager, GlobalInspectionContext globalContext, ProblemDescriptionsProcessor processor) { ArrayList<ProblemDescriptor> problems = null; if (refEntity instanceof RefMethod) { final RefMethod refMethod = (RefMethod) refEntity; if (refMethod.hasSuperMethods()) return null; if (refMethod.isEntry()) return null; RefParameter[] parameters = refMethod.getParameters(); for (RefParameter refParameter : parameters) { String value = refParameter.getActualValueIfSame(); if (value != null) { if (problems == null) problems = new ArrayList<ProblemDescriptor>(1); final String paramName = refParameter.getName(); problems.add( manager.createProblemDescriptor( refParameter.getElement(), InspectionsBundle.message( "inspection.same.parameter.problem.descriptor", "<code>" + paramName + "</code>", "<code>" + value + "</code>"), new InlineParameterValueFix(paramName, value), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false)); } } } return problems == null ? null : problems.toArray(new CommonProblemDescriptor[problems.size()]); }
@Nullable public CommonProblemDescriptor[] checkElement( final RefEntity refEntity, final AnalysisScope scope, final InspectionManager manager, final GlobalInspectionContext globalContext, final ProblemDescriptionsProcessor processor) { if (refEntity instanceof RefMethod) { final RefMethod refMethod = (RefMethod) refEntity; if (refMethod.isSyntheticJSP()) return null; if (refMethod.isExternalOverride()) return null; if (!(refMethod.isStatic() || refMethod.isConstructor()) && !refMethod.getSuperMethods().isEmpty()) return null; if ((refMethod.isAbstract() || refMethod.getOwnerClass().isInterface()) && refMethod.getDerivedMethods().isEmpty()) return null; if (RefUtil.isEntryPoint(refMethod)) return null; if (refMethod.isAppMain()) return null; final ArrayList<RefParameter> unusedParameters = getUnusedParameters(refMethod); if (unusedParameters.isEmpty()) return null; final List<ProblemDescriptor> result = new ArrayList<ProblemDescriptor>(); for (RefParameter refParameter : unusedParameters) { final PsiIdentifier psiIdentifier = refParameter.getElement().getNameIdentifier(); if (psiIdentifier != null) { result.add( manager.createProblemDescriptor( psiIdentifier, refMethod.isAbstract() ? InspectionsBundle.message("inspection.unused.parameter.composer") : InspectionsBundle.message("inspection.unused.parameter.composer1"), new AcceptSuggested( globalContext.getRefManager(), processor, refParameter.toString()), ProblemHighlightType.LIKE_UNUSED_SYMBOL, false)); } } return result.toArray(new CommonProblemDescriptor[result.size()]); } return null; }
@Override @Nullable public CommonProblemDescriptor[] checkElement( @NotNull final RefEntity refEntity, @NotNull final AnalysisScope scope, @NotNull final InspectionManager manager, @NotNull final GlobalInspectionContext globalContext, @NotNull final ProblemDescriptionsProcessor processor) { if (refEntity instanceof RefJavaElement) { final RefJavaElement refElement = (RefJavaElement) refEntity; if (refElement instanceof RefParameter) return null; if (refElement.isSyntheticJSP()) return null; // ignore entry points. if (refElement.isEntry()) return null; // ignore implicit constructors. User should not be able to see them. if (refElement instanceof RefImplicitConstructor) return null; if (refElement instanceof RefField && ((RefField) refElement).getElement() instanceof PsiEnumConstant) return null; // ignore library override methods. if (refElement instanceof RefMethod) { RefMethod refMethod = (RefMethod) refElement; if (refMethod.isExternalOverride()) return null; if (refMethod.isEntry()) return null; } // ignore anonymous classes. They do not have access modifiers. if (refElement instanceof RefClass) { RefClass refClass = (RefClass) refElement; if (refClass.isAnonymous() || refClass.isEntry() || refClass.isTestCase() || refClass.isServlet() || refClass.isApplet() || refClass.isLocalClass()) return null; if (isTopLevelClass(refClass) && !SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES) return null; } // ignore unreferenced code. They could be a potential entry points. if (refElement.getInReferences().isEmpty()) return null; // ignore interface members. They always have public access modifier. if (refElement.getOwner() instanceof RefClass) { RefClass refClass = (RefClass) refElement.getOwner(); if (refClass.isInterface()) return null; } String access = getPossibleAccess(refElement); if (access != refElement.getAccessModifier() && access != null) { final PsiElement element = refElement.getElement(); final PsiElement nameIdentifier = element != null ? HighlightUsagesHandler.getNameIdentifier(element) : null; if (nameIdentifier != null) { return new ProblemDescriptor[] { manager.createProblemDescriptor( nameIdentifier, access.equals(PsiModifier.PRIVATE) ? CAN_BE_PRIVATE : access.equals(PsiModifier.PACKAGE_LOCAL) ? CAN_BE_PACKAGE_LOCAL : CAN_BE_PROTECTED, new AcceptSuggestedAccess(globalContext.getRefManager(), access), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false) }; } } } return null; }