@Override public void visitMethod(@NotNull PsiMethod method) { super.visitMethod(method); final PsiCodeBlock body = method.getBody(); if (body == null) { return; } if (method.getNameIdentifier() == null) { return; } final PsiMethod leastConcreteSuperMethod = getLeastConcreteSuperMethod(method); if (leastConcreteSuperMethod == null) { return; } final PsiClass objectClass = ClassUtils.findObjectClass(method); final PsiMethod[] superMethods = method.findSuperMethods(objectClass); if (superMethods.length > 0) { return; } if (ignoreEmptySuperMethods) { final PsiMethod superMethod = (PsiMethod) leastConcreteSuperMethod.getNavigationElement(); if (MethodUtils.isTrivial(superMethod, true)) { return; } } if (onlyReportWhenAnnotated) { if (!AnnotationUtil.isAnnotated(leastConcreteSuperMethod, annotations)) { return; } } if (containsSuperCall(body, leastConcreteSuperMethod)) { return; } registerMethodError(method); }
@Override public void visitLiteralExpression(@NotNull PsiLiteralExpression expression) { super.visitLiteralExpression(expression); final PsiType type = expression.getType(); if (!ClassUtils.isPrimitiveNumericType(type)) { return; } if (PsiType.CHAR.equals(type)) { return; } if (isSpecialCaseLiteral(expression)) { return; } if (ExpressionUtils.isDeclaredConstant(expression)) { return; } if (ignoreInHashCode) { final PsiMethod containingMethod = PsiTreeUtil.getParentOfType(expression, PsiMethod.class); if (MethodUtils.isHashCode(containingMethod)) { return; } } if (ignoreInTestCode && TestUtils.isInTestCode(expression)) { return; } final PsiElement parent = expression.getParent(); if (parent instanceof PsiPrefixExpression) { registerError(parent); } else { registerError(expression); } }
@Override public void visitMethod(@NotNull PsiMethod method) { super.visitMethod(method); if (method.isConstructor() || method.hasModifierProperty(PsiModifier.STATIC)) { return; } if (method.hasModifierProperty(PsiModifier.NATIVE) && isInspectionEnabled("NativeMethodNamingConvention", method)) { return; } final PsiIdentifier nameIdentifier = method.getNameIdentifier(); if (nameIdentifier == null) { return; } if (TestUtils.isRunnable(method)) { if (TestUtils.isJUnit4TestMethod(method) && isInspectionEnabled("JUnit4MethodNamingConvention", method)) { return; } if (TestUtils.isJUnit3TestMethod(method) && isInspectionEnabled("JUnit3MethodNamingConvention", method)) { return; } } if (isTestNGTestMethod(method) && isInspectionEnabled("TestNGMethodNamingConvention", method)) { return; } final String name = method.getName(); if (isValid(name)) { return; } if (!isOnTheFly() && MethodUtils.hasSuper(method)) { return; } if (LibraryUtil.isOverrideOfLibraryMethod(method)) { return; } registerMethodError(method, name); }
private void checkExpression(PsiExpression expression) { if (expression == null) return; final PsiType type = expression.getType(); if (!(type instanceof PsiClassType)) return; if (IGNORE_TOSTRING && MethodUtils.isToString(PsiTreeUtil.getParentOfType(expression, PsiMethod.class))) return; if (IGNORE_EXCEPTION && (ExceptionUtils.isExceptionArgument(expression) || PsiTreeUtil.getParentOfType( expression, PsiThrowStatement.class, true, PsiCodeBlock.class, PsiClass.class) != null)) return; if (IGNORE_ASSERT && PsiTreeUtil.getParentOfType( expression, PsiAssertStatement.class, true, PsiCodeBlock.class, PsiClass.class) != null) { return; } if (IGNORE_NONNLS && NonNlsUtils.isNonNlsAnnotatedUse(expression)) return; final PsiClassType classType = (PsiClassType) type; if (type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return; final PsiClass referencedClass = classType.resolve(); if (referencedClass == null || referencedClass instanceof PsiTypeParameter) return; if (referencedClass.isEnum() || referencedClass.isInterface()) return; if (referencedClass.hasModifierProperty(PsiModifier.ABSTRACT) && !(expression instanceof PsiSuperExpression)) return; if (hasGoodToString(referencedClass)) return; registerError(expression); }
private void checkMember(@NotNull final PsiMember member) { if (member.hasModifierProperty(PsiModifier.PRIVATE) || member.hasModifierProperty(PsiModifier.NATIVE)) return; if (member instanceof PsiMethod && member instanceof SyntheticElement || !member.isPhysical()) return; if (member instanceof PsiMethod) { PsiMethod method = (PsiMethod) member; if (!method.getHierarchicalMethodSignature().getSuperSignatures().isEmpty()) { log(member.getName() + " overrides"); return; // overrides } if (MethodUtils.isOverridden(method)) { log(member.getName() + " overridden"); return; } } if (member instanceof PsiEnumConstant) return; if (member instanceof PsiClass && (member instanceof PsiAnonymousClass || member instanceof PsiTypeParameter || member instanceof PsiSyntheticClass || PsiUtil.isLocalClass((PsiClass) member))) { return; } final PsiClass memberClass = member.getContainingClass(); if (memberClass != null && (memberClass.isInterface() || memberClass.isEnum() || memberClass.isAnnotationType() || PsiUtil.isLocalClass(memberClass) && member instanceof PsiClass)) { return; } final PsiFile memberFile = member.getContainingFile(); Project project = memberFile.getProject(); if (myDeadCodeInspection.isEntryPoint(member)) { log(member.getName() + " is entry point"); return; } PsiModifierList memberModifierList = member.getModifierList(); if (memberModifierList == null) return; final int currentLevel = PsiUtil.getAccessLevel(memberModifierList); final AtomicInteger maxLevel = new AtomicInteger(PsiUtil.ACCESS_LEVEL_PRIVATE); final AtomicBoolean foundUsage = new AtomicBoolean(); PsiDirectory memberDirectory = memberFile.getContainingDirectory(); final PsiPackage memberPackage = memberDirectory == null ? null : JavaDirectoryService.getInstance().getPackage(memberDirectory); log(member.getName() + ": checking effective level for " + member); boolean result = UnusedSymbolUtil.processUsages( project, memberFile, member, new EmptyProgressIndicator(), null, new Processor<UsageInfo>() { @Override public boolean process(UsageInfo info) { foundUsage.set(true); PsiFile psiFile = info.getFile(); if (psiFile == null) return true; if (!(psiFile instanceof PsiJavaFile)) { log(" refd from " + psiFile.getName() + "; set to public"); maxLevel.set(PsiUtil.ACCESS_LEVEL_PUBLIC); if (memberClass != null) { childMembersAreUsedOutsideMyPackage.add(memberClass); } return false; // referenced from XML, has to be public } // int offset = info.getNavigationOffset(); // if (offset == -1) return true; PsiElement element = info.getElement(); if (element == null) return true; @PsiUtil.AccessLevel int level = getEffectiveLevel(element, psiFile, memberFile, memberClass, memberPackage); log( " ref in file " + psiFile.getName() + "; level = " + PsiUtil.getAccessModifier(level) + "; (" + element + ")"); while (true) { int oldLevel = maxLevel.get(); if (level <= oldLevel || maxLevel.compareAndSet(oldLevel, level)) break; } if (level == PsiUtil.ACCESS_LEVEL_PUBLIC && memberClass != null) { childMembersAreUsedOutsideMyPackage.add(memberClass); } return level != PsiUtil.ACCESS_LEVEL_PUBLIC; } }); if (!foundUsage.get()) { log(member.getName() + " unused; ignore"); return; // do not propose private for unused method } int max = maxLevel.get(); if (max == PsiUtil.ACCESS_LEVEL_PRIVATE && memberClass == null) { max = PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL; } log(member.getName() + ": effective level is '" + PsiUtil.getAccessModifier(max) + "'"); if (max < currentLevel) { if (max == PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL && member instanceof PsiClass && childMembersAreUsedOutsideMyPackage.contains(member)) { log(member.getName() + " children used outside my package; ignore"); return; // e.g. some public method is used outside my package (without importing class) } PsiElement toHighlight = currentLevel == PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL ? ((PsiNameIdentifierOwner) member).getNameIdentifier() : ContainerUtil.find( memberModifierList.getChildren(), new Condition<PsiElement>() { @Override public boolean value(PsiElement element) { return element instanceof PsiKeyword && element.getText().equals(PsiUtil.getAccessModifier(currentLevel)); } }); assert toHighlight != null : member + " ; " + ((PsiNameIdentifierOwner) member).getNameIdentifier() + "; " + memberModifierList.getText(); myHolder.registerProblem( toHighlight, "Access can be " + PsiUtil.getAccessModifier(max), new ChangeModifierFix(PsiUtil.getAccessModifier(max))); } }