private boolean checkAccessibility(final PsiClass aClass) { // We don't care about accessibility in javadoc if (JavaResolveUtil.isInJavaDoc(myPlace)) { return true; } if (PsiImplUtil.isInServerPage(aClass.getContainingFile())) { PsiFile file = FileContextUtil.getContextFile(myPlace); if (PsiImplUtil.isInServerPage(file)) { return true; } } boolean accessible = true; if (aClass instanceof PsiTypeParameter) { accessible = !myStaticContext; } PsiManager manager = aClass.getManager(); if (aClass.hasModifierProperty(PsiModifier.PRIVATE)) { PsiElement parent = aClass.getParent(); while (true) { PsiElement parentScope = parent.getParent(); if (parentScope instanceof PsiJavaFile) break; parent = parentScope; if (!(parentScope instanceof PsiClass)) break; } if (parent instanceof PsiDeclarationStatement) { parent = parent.getParent(); } accessible = false; for (PsiElement placeParent = myPlace; placeParent != null; placeParent = placeParent.getContext()) { if (manager.areElementsEquivalent(placeParent, parent)) accessible = true; } } final JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject()); if (aClass.hasModifierProperty(PsiModifier.PROTECTED)) { accessible = false; if (myPlace != null && facade.arePackagesTheSame(aClass, myPlace)) { accessible = true; } else { if (aClass.getContainingClass() != null) { accessible = myAccessClass == null || myPlace != null && facade.getResolveHelper().isAccessible(aClass, myPlace, myAccessClass); } } } if (aClass.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) { if (myPlace == null || !facade.arePackagesTheSame(aClass, myPlace)) { accessible = false; } } return accessible; }
private boolean isAmbiguousInherited(PsiClass containingClass1) { PsiClass psiClass = PsiTreeUtil.getParentOfType(myPlace, PsiClass.class); while (psiClass != null) { if (psiClass.isInheritor(containingClass1, false)) { return true; } psiClass = psiClass.getContainingClass(); } return false; }
private boolean isAccessible(PsiClass otherClass) { if (otherClass.hasModifierProperty(PsiModifier.PRIVATE)) { final PsiClass containingClass = otherClass.getContainingClass(); PsiClass containingPlaceClass = PsiTreeUtil.getParentOfType(myPlace, PsiClass.class, false); while (containingPlaceClass != null) { if (containingClass == containingPlaceClass) { return true; } containingPlaceClass = PsiTreeUtil.getParentOfType(containingPlaceClass, PsiClass.class); } return false; } return true; }
private Domination dominates( PsiClass aClass, boolean accessible, String fqName, ClassCandidateInfo info) { final PsiClass otherClass = info.getElement(); assert otherClass != null; String otherQName = otherClass.getQualifiedName(); if (fqName.equals(otherQName)) { return Domination.DOMINATED_BY; } final PsiClass containingClass1 = aClass.getContainingClass(); final PsiClass containingClass2 = otherClass.getContainingClass(); if (myAccessClass != null && !Comparing.equal(containingClass1, containingClass2)) { if (myAccessClass.equals(containingClass1)) return Domination.DOMINATES; if (myAccessClass.equals(containingClass2)) return Domination.DOMINATED_BY; } // JLS 8.5: // A class may inherit two or more type declarations with the same name, either from two // interfaces or from its superclass and an interface. // It is a compile-time error to attempt to refer to any ambiguously inherited class or // interface by its simple name. if (containingClass1 != null && containingClass2 != null && containingClass2.isInheritor(containingClass1, true) && !isImported(myCurrentFileContext)) { if (!isAmbiguousInherited(containingClass1)) { // shadowing return Domination.DOMINATED_BY; } } boolean infoAccessible = info.isAccessible() && isAccessible(otherClass); if (infoAccessible && !accessible) { return Domination.DOMINATED_BY; } if (!infoAccessible && accessible) { return Domination.DOMINATES; } // everything wins over class from default package boolean isDefault = StringUtil.getPackageName(fqName).length() == 0; boolean otherDefault = otherQName != null && StringUtil.getPackageName(otherQName).length() == 0; if (isDefault && !otherDefault) { return Domination.DOMINATED_BY; } if (!isDefault && otherDefault) { return Domination.DOMINATES; } // single import wins over on-demand boolean myOnDemand = isOnDemand(myCurrentFileContext, aClass); boolean otherOnDemand = isOnDemand(info.getCurrentFileResolveScope(), otherClass); if (myOnDemand && !otherOnDemand) { return Domination.DOMINATED_BY; } if (!myOnDemand && otherOnDemand) { return Domination.DOMINATES; } return Domination.EQUAL; }