private static void qualify(PsiMember member, PsiElement renamed, String name) { if (!(renamed instanceof GrReferenceExpression)) return; final PsiClass clazz = member.getContainingClass(); if (clazz == null) return; final GrReferenceExpression refExpr = (GrReferenceExpression) renamed; final PsiElement replaced; if (member.hasModifierProperty(GrModifier.STATIC)) { final GrReferenceExpression newRefExpr = GroovyPsiElementFactory.getInstance(member.getProject()) .createReferenceExpressionFromText(clazz.getQualifiedName() + "." + name); replaced = refExpr.replace(newRefExpr); } else { final PsiClass containingClass = PsiTreeUtil.getParentOfType(renamed, PsiClass.class); if (member.getManager().areElementsEquivalent(containingClass, clazz)) { final GrReferenceExpression newRefExpr = GroovyPsiElementFactory.getInstance(member.getProject()) .createReferenceExpressionFromText("this." + name); replaced = refExpr.replace(newRefExpr); } else { final GrReferenceExpression newRefExpr = GroovyPsiElementFactory.getInstance(member.getProject()) .createReferenceExpressionFromText(clazz.getQualifiedName() + ".this." + name); replaced = refExpr.replace(newRefExpr); } } PsiUtil.shortenReferences((GroovyPsiElement) replaced); }
@Override public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) { if (FileTypeUtils.isInServerPageFile(expression)) { // disable for jsp files IDEADEV-12957 return; } super.visitReferenceExpression(expression); if (expression.getQualifierExpression() == null) { return; } final PsiElement referenceNameElement = expression.getReferenceNameElement(); if (referenceNameElement == null) { return; } final PsiElement containingClass = getContainingContextClass(expression); if (containingClass == null) { return; } final PsiElement element = expression.resolve(); if (!(element instanceof PsiMethod || element instanceof PsiField)) { return; } final PsiMember member = (PsiMember) element; if (!member.hasModifierProperty(PsiModifier.PRIVATE)) { return; } final PsiClass memberClass = ClassUtils.getContainingClass(member); if (memberClass == null) { return; } if (memberClass.equals(containingClass)) { return; } registerError(referenceNameElement, memberClass, member); }
@Override public void visitAnonymousClass(@NotNull PsiAnonymousClass anonymousClass) { if (anonymousClass instanceof PsiEnumConstantInitializer) { return; } final PsiMember containingMember = PsiTreeUtil.getParentOfType(anonymousClass, PsiMember.class); if (containingMember == null || containingMember.hasModifierProperty(PsiModifier.STATIC)) { return; } final PsiJavaCodeReferenceElement reference = anonymousClass.getBaseClassReference(); if (reference.resolve() == null) { // don't warn on broken code return; } final PsiClass containingClass = PsiTreeUtil.getParentOfType(anonymousClass, PsiClass.class); if (containingClass == null) { return; } if (containingClass.getContainingClass() != null && !containingClass.hasModifierProperty(PsiModifier.STATIC)) { // strictly speaking can be named static inner class but not when part of the current // containing class return; } final InnerClassReferenceVisitor visitor = new InnerClassReferenceVisitor(anonymousClass); anonymousClass.accept(visitor); if (!visitor.canInnerClassBeStatic()) { return; } if (hasReferenceToLocalClass(anonymousClass)) { return; } registerClassError(anonymousClass); }
private static boolean processInstanceMember( boolean shouldProcessInstance, @NotNull PsiMember member) { if (shouldProcessInstance) return true; if (member instanceof GrReflectedMethod) { return ((GrReflectedMethod) member).getBaseMethod().hasModifierProperty(PsiModifier.STATIC); } else { return member.hasModifierProperty(PsiModifier.STATIC); } }
@Override public boolean isAbstractWhenDisabled(MemberInfo member) { PsiClass currentSuperClass = getSuperClass(); if (currentSuperClass == null) return false; if (currentSuperClass.isInterface()) { final PsiMember psiMember = member.getMember(); if (psiMember instanceof PsiMethod) { return !psiMember.hasModifierProperty(PsiModifier.STATIC); } } return false; }
@Override protected void visitClassMemberReferenceElement( PsiMember classMember, PsiJavaCodeReferenceElement classMemberReference) { if (classMember != null && !willBeMoved(classMember, myMovedMembers)) { final PsiClass containingClass = classMember.getContainingClass(); if (containingClass != null) { if (!PsiUtil.isAccessibleFromPackage(classMember, myTargetPackage)) { if (classMember.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) { myConflicts.putValue( myMember, RefactoringUIUtil.getDescription(classMember, true) + " won't be accessible"); } else if (classMember.hasModifierProperty(PsiModifier.PROTECTED) && !mySubClass.isInheritor(containingClass, true)) { myConflicts.putValue( myMember, RefactoringUIUtil.getDescription(classMember, true) + " won't be accessible"); } } } } }
protected void visitClassMemberReferenceElement( PsiMember classMember, PsiJavaCodeReferenceElement classMemberReference) { if (classMember != null && RefactoringHierarchyUtil.isMemberBetween(mySuperClass, mySubclass, classMember)) { if (classMember.hasModifierProperty(PsiModifier.STATIC) && !willBeMoved(classMember, myMovedMembers)) { final boolean isAccessible; if (mySuperClass != null) { isAccessible = PsiUtil.isAccessible(classMember, mySuperClass, null); } else if (myTargetPackage != null) { isAccessible = PsiUtil.isAccessibleFromPackage(classMember, myTargetPackage); } else { isAccessible = classMember.hasModifierProperty(PsiModifier.PUBLIC); } if (!isAccessible) { String message = RefactoringBundle.message( "0.uses.1.which.is.not.accessible.from.the.superclass", RefactoringUIUtil.getDescription(myScope, false), RefactoringUIUtil.getDescription(classMember, true)); message = CommonRefactoringUtil.capitalize(message); myConflictsList.putValue(classMember, message); } return; } if (!myAbstractMethods.contains(classMember) && !willBeMoved(classMember, myMovedMembers)) { if (!existsInSuperClass(classMember)) { String message = RefactoringBundle.message( "0.uses.1.which.is.not.moved.to.the.superclass", RefactoringUIUtil.getDescription(myScope, false), RefactoringUIUtil.getDescription(classMember, true)); message = CommonRefactoringUtil.capitalize(message); myConflictsList.putValue(classMember, message); } } } }
@NotNull public static SearchScope getMemberUseScope(@NotNull PsiMember member) { final GlobalSearchScope maximalUseScope = ResolveScopeManager.getElementUseScope(member); PsiFile file = member.getContainingFile(); if (isInServerPage(file)) return maximalUseScope; PsiClass aClass = member.getContainingClass(); if (aClass instanceof PsiAnonymousClass) { // member from anonymous class can be called from outside the class PsiElement methodCallExpr = PsiTreeUtil.getParentOfType(aClass, PsiMethodCallExpression.class); return new LocalSearchScope(methodCallExpr != null ? methodCallExpr : aClass); } if (member.hasModifierProperty(PsiModifier.PUBLIC)) { return maximalUseScope; // class use scope doesn't matter, since another very visible class // can inherit from aClass } else if (member.hasModifierProperty(PsiModifier.PROTECTED)) { return maximalUseScope; // class use scope doesn't matter, since another very visible class // can inherit from aClass } else if (member.hasModifierProperty(PsiModifier.PRIVATE)) { PsiClass topClass = PsiUtil.getTopLevelClass(member); return topClass != null ? new LocalSearchScope(topClass) : new LocalSearchScope(file); } else { if (file instanceof PsiJavaFile) { PsiPackage aPackage = JavaPsiFacade.getInstance(member.getProject()) .findPackage(((PsiJavaFile) file).getPackageName()); if (aPackage != null) { SearchScope scope = PackageScope.packageScope(aPackage, false); scope = scope.intersectWith(maximalUseScope); return scope; } } return maximalUseScope; } }
@Override @NotNull protected UsageInfo[] findUsages() { final List<UsageInfo> result = new ArrayList<>(); for (MemberInfo memberInfo : myMembersToMove) { final PsiMember member = memberInfo.getMember(); if (member.hasModifierProperty(PsiModifier.STATIC)) { for (PsiReference reference : ReferencesSearch.search(member)) { result.add(new UsageInfo(reference)); } } } return result.isEmpty() ? UsageInfo.EMPTY_ARRAY : result.toArray(new UsageInfo[result.size()]); }
@Override public int checkForProblems(@NotNull MemberInfo member) { if (member.isChecked()) return OK; PsiClass currentSuperClass = getSuperClass(); if (currentSuperClass != null && currentSuperClass.isInterface()) { PsiMember element = member.getMember(); if (element.hasModifierProperty(PsiModifier.STATIC)) { return super.checkForProblems(member); } return OK; } else { return super.checkForProblems(member); } }
@NotNull @Override protected UsageInfo[] findUsages() { final List<UsageInfo> result = new ArrayList<UsageInfo>(); for (GrMemberInfo info : myMembersToMove) { final PsiMember member = info.getMember(); if (member.hasModifierProperty(PsiModifier.STATIC)) { for (PsiReference reference : ReferencesSearch.search(member)) { result.add(new UsageInfo(reference)); } } } return DefaultGroovyMethods.asType(result, UsageInfo[].class); }
@NotNull public static SearchScope getMemberUseScope(@NotNull PsiMember member) { PsiFile file = member.getContainingFile(); PsiElement topElement = file == null ? member : file; Project project = topElement.getProject(); final GlobalSearchScope maximalUseScope = ResolveScopeManager.getInstance(project).getUseScope(topElement); if (isInServerPage(file)) return maximalUseScope; PsiClass aClass = member.getContainingClass(); if (aClass instanceof PsiAnonymousClass && !(aClass instanceof PsiEnumConstantInitializer && member instanceof PsiMethod && member.hasModifierProperty(PsiModifier.PUBLIC) && ((PsiMethod) member).findSuperMethods().length > 0)) { // member from anonymous class can be called from outside the class PsiElement methodCallExpr = PsiUtil.isLanguageLevel8OrHigher(aClass) ? PsiTreeUtil.getTopmostParentOfType(aClass, PsiStatement.class) : PsiTreeUtil.getParentOfType(aClass, PsiMethodCallExpression.class); return new LocalSearchScope(methodCallExpr != null ? methodCallExpr : aClass); } PsiModifierList modifierList = member.getModifierList(); int accessLevel = modifierList == null ? PsiUtil.ACCESS_LEVEL_PUBLIC : PsiUtil.getAccessLevel(modifierList); if (accessLevel == PsiUtil.ACCESS_LEVEL_PUBLIC || accessLevel == PsiUtil.ACCESS_LEVEL_PROTECTED) { return maximalUseScope; // class use scope doesn't matter, since another very visible class // can inherit from aClass } if (accessLevel == PsiUtil.ACCESS_LEVEL_PRIVATE) { PsiClass topClass = PsiUtil.getTopLevelClass(member); return topClass != null ? new LocalSearchScope(topClass) : file == null ? maximalUseScope : new LocalSearchScope(file); } if (file instanceof PsiJavaFile) { PsiPackage aPackage = JavaPsiFacade.getInstance(project).findPackage(((PsiJavaFile) file).getPackageName()); if (aPackage != null) { SearchScope scope = PackageScope.packageScope(aPackage, false); return scope.intersectWith(maximalUseScope); } } return maximalUseScope; }
protected void visitClassMemberReferenceElement( PsiMember classMember, PsiJavaCodeReferenceElement classMemberReference) { if (classMember.hasModifierProperty(PsiModifier.STATIC)) { if (!myMembersToMove.contains(classMember) && RefactoringHierarchyUtil.isMemberBetween( myTargetSuperClass, mySourceClass, classMember)) { myReferences.add(classMemberReference); myReferees.add(classMember); myRefereeClasses.add(classMember.getContainingClass()); } else if (myMembersToMove.contains(classMember) || myMembersAfterMove.contains(classMember)) { myReferences.add(classMemberReference); myReferees.add(classMember); myRefereeClasses.add(myTargetSuperClass); } } }
public static boolean isInExcludedPackage( @NotNull final PsiMember member, boolean allowInstanceInnerClasses) { final String name = PsiUtil.getMemberQualifiedName(member); if (name == null) return false; if (!member.hasModifierProperty(PsiModifier.STATIC)) { if (member instanceof PsiMethod || member instanceof PsiField) { return false; } if (allowInstanceInnerClasses && member instanceof PsiClass && member.getContainingClass() != null) { return false; } } return ProjectCodeInsightSettings.getSettings(member.getProject()).isExcluded(name); }
private static boolean referenceExpressionsAreEquivalent( PsiReferenceExpression referenceExpression1, PsiReferenceExpression referenceExpression2) { final PsiElement element1 = referenceExpression1.resolve(); final PsiElement element2 = referenceExpression2.resolve(); if (element1 != null) { if (!element1.equals(element2)) { return false; } } else { return element2 == null; } if (element1 instanceof PsiMember) { final PsiMember member1 = (PsiMember) element1; if (member1.hasModifierProperty(PsiModifier.STATIC)) { return true; } else if (member1 instanceof PsiClass) { return true; } } else { return true; } final PsiExpression qualifier1 = referenceExpression1.getQualifierExpression(); final PsiExpression qualifier2 = referenceExpression2.getQualifierExpression(); if (qualifier1 != null && !(qualifier1 instanceof PsiThisExpression || qualifier1 instanceof PsiSuperExpression)) { if (qualifier2 == null) { return false; } else if (!expressionsAreEquivalent(qualifier1, qualifier2)) { return false; } } else { if (qualifier2 != null && !(qualifier2 instanceof PsiThisExpression || qualifier2 instanceof PsiSuperExpression)) { return false; } } final String text1 = referenceExpression1.getText(); final String text2 = referenceExpression2.getText(); return text1.equals(text2); }
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))); } }
protected void visitClassMemberReferenceElement( PsiMember classMember, PsiJavaCodeReferenceElement classMemberReference) { if (!classMember.hasModifierProperty(PsiModifier.STATIC)) { myElementReference = classMemberReference; } }