@NotNull public JavaResolveResult[] getResult() { if (myResult != null) return myResult; if (myCandidates == null) return myResult = JavaResolveResult.EMPTY_ARRAY; if (myHasAccessibleCandidate && myHasInaccessibleCandidate) { for (Iterator<ClassCandidateInfo> iterator = myCandidates.iterator(); iterator.hasNext();) { CandidateInfo info = iterator.next(); if (!info.isAccessible()) iterator.remove(); } myHasInaccessibleCandidate = false; } myResult = myCandidates.toArray(new JavaResolveResult[myCandidates.size()]); return myResult; }
@NotNull private JavaResolveResult doAdvancedResolve(@NotNull PsiFile containingFile) { final PsiElement psiElement = getElement(); if (!psiElement.isValid()) return JavaResolveResult.EMPTY; final String elementText = psiElement.getText(); final PsiElement context = getContext(); if (context instanceof PsiClass) { if (isStaticClassReference(elementText, false)) { final PsiClass psiClass = ((PsiClass)context).findInnerClassByName(getCanonicalText(), false); if (psiClass != null) { return new ClassCandidateInfo(psiClass, PsiSubstitutor.EMPTY, false, psiElement); } PsiElement member = doResolveMember((PsiClass)context, myText); return member == null ? JavaResolveResult.EMPTY : new CandidateInfo(member, PsiSubstitutor.EMPTY, false, false, psiElement); } else if (!myInStaticImport && myJavaClassReferenceSet.isAllowDollarInNames()) { return JavaResolveResult.EMPTY; } } final int endOffset = getRangeInElement().getEndOffset(); LOG.assertTrue(endOffset <= elementText.length(), elementText); final int startOffset = myJavaClassReferenceSet.getReference(0).getRangeInElement().getStartOffset(); final String qName = elementText.substring(startOffset, endOffset); if (!qName.contains(".")) { final String defaultPackage = JavaClassReferenceProvider.DEFAULT_PACKAGE.getValue(getOptions()); if (StringUtil.isNotEmpty(defaultPackage)) { final JavaResolveResult resolveResult = advancedResolveInner(psiElement, defaultPackage + "." + qName, containingFile); if (resolveResult != JavaResolveResult.EMPTY) { return resolveResult; } } } return advancedResolveInner(psiElement, qName, containingFile); }
private JavaResolveResult doAdvancedResolve() { final PsiElement psiElement = getElement(); if (!psiElement.isValid()) return JavaResolveResult.EMPTY; final String elementText = psiElement.getText(); final PsiElement context = getContext(); if (context instanceof PsiClass) { if (isStaticClassReference(elementText, false)) { final PsiClass psiClass = ((PsiClass)context).findInnerClassByName(getCanonicalText(), false); if (psiClass != null) return new ClassCandidateInfo(psiClass, PsiSubstitutor.EMPTY, false, psiElement); PsiElement member = doResolveMember((PsiClass)context, myText); return member == null ? JavaResolveResult.EMPTY : new CandidateInfo(member, PsiSubstitutor.EMPTY, false, false, psiElement); } else if (!myInStaticImport && myJavaClassReferenceSet.isAllowDollarInNames()) { return JavaResolveResult.EMPTY; } } final int endOffset = getRangeInElement().getEndOffset(); LOG.assertTrue(endOffset <= elementText.length(), elementText); final int startOffset = myJavaClassReferenceSet.getReference(0).getRangeInElement().getStartOffset(); final String qName = elementText.substring(startOffset, endOffset); if (!qName.contains(".")) { final String defaultPackage = JavaClassReferenceProvider.DEFAULT_PACKAGE.getValue(getOptions()); if (StringUtil.isNotEmpty(defaultPackage)) { final JavaResolveResult resolveResult = advancedResolveInner(psiElement, defaultPackage + "." + qName); if (resolveResult != JavaResolveResult.EMPTY) { return resolveResult; } } } return advancedResolveInner(psiElement, qName); }
@NotNull public JavaResolveResult[] getResult() { if(myResult != null) { return myResult; } if(myCandidates == null) { return myResult = JavaResolveResult.EMPTY_ARRAY; } if(myHasAccessibleCandidate && myHasInaccessibleCandidate) { for(Iterator<ClassCandidateInfo> iterator = myCandidates.iterator(); iterator.hasNext(); ) { CandidateInfo info = iterator.next(); if(!info.isAccessible()) { iterator.remove(); } } myHasInaccessibleCandidate = false; } myResult = myCandidates.toArray(new JavaResolveResult[myCandidates.size()]); return myResult; }
private Domination dominates(@NotNull PsiClass aClass, boolean accessible, @NotNull String fqName, @NotNull ClassCandidateInfo info) { final PsiClass otherClass = info.getElement(); 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).isEmpty(); boolean otherDefault = otherQName != null && StringUtil.getPackageName(otherQName).isEmpty(); 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; }
@Override public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) { if (!(element instanceof PsiClass)) return true; final PsiClass aClass = (PsiClass)element; final String name = aClass.getName(); if (!myClassName.equals(name)) { return true; } boolean accessible = myPlace == null || checkAccessibility(aClass); if (myCandidates == null) { myCandidates = new SmartList<ClassCandidateInfo>(); } else { String fqName = aClass.getQualifiedName(); if (fqName != null) { for (int i = myCandidates.size()-1; i>=0; i--) { ClassCandidateInfo info = myCandidates.get(i); Domination domination = dominates(aClass, accessible && isAccessible(aClass), fqName, info); if (domination == Domination.DOMINATED_BY) { return true; } else if (domination == Domination.DOMINATES) { myCandidates.remove(i); } } } } myHasAccessibleCandidate |= accessible; myHasInaccessibleCandidate |= !accessible; myCandidates.add(new ClassCandidateInfo(aClass, state.get(PsiSubstitutor.KEY), !accessible, myCurrentFileContext)); myResult = null; if (!accessible) return true; if (aClass.hasModifierProperty(PsiModifier.PRIVATE)) { final PsiClass containingPlaceClass = PsiTreeUtil.getParentOfType(myPlace, PsiClass.class, false); if (containingPlaceClass != null && !PsiTreeUtil.isAncestor(containingPlaceClass, aClass, false)){ return true; } } return myCurrentFileContext instanceof PsiImportStatementBase; }
private JavaResolveResult advancedResolveInner(@NotNull PsiElement psiElement, @NotNull String qName, @NotNull PsiFile containingFile) { final PsiManager manager = containingFile.getManager(); final GlobalSearchScope scope = getScope(containingFile); if (myIndex == myJavaClassReferenceSet.getReferences().length - 1) { final PsiClass aClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(qName, scope); if (aClass != null) { return new ClassCandidateInfo(aClass, PsiSubstitutor.EMPTY, false, psiElement); } else { if (!JavaClassReferenceProvider.ADVANCED_RESOLVE.getBooleanValue(getOptions())) { return JavaResolveResult.EMPTY; } } } PsiElement resolveResult = JavaPsiFacade.getInstance(manager.getProject()).findPackage(qName); if (resolveResult == null) { resolveResult = JavaPsiFacade.getInstance(manager.getProject()).findClass(qName, scope); } if (myInStaticImport && resolveResult == null) { resolveResult = resolveMember(qName, manager, getElement().getResolveScope()); } if (resolveResult == null) { if (containingFile instanceof PsiJavaFile) { if (containingFile instanceof ServerPageFile) { containingFile = containingFile.getViewProvider().getPsi(JavaLanguage.INSTANCE); if (containingFile == null) return JavaResolveResult.EMPTY; } final ClassResolverProcessor processor = new ClassResolverProcessor(getCanonicalText(), psiElement, containingFile); PsiClass contextClass = myJavaClassReferenceSet.getProvider().getContextClass(psiElement); if (contextClass != null) { PsiScopesUtil.treeWalkUp(processor, contextClass, null); } else { containingFile.processDeclarations(processor, ResolveState.initial(), null, psiElement); } if (processor.getResult().length == 1) { final JavaResolveResult javaResolveResult = processor.getResult()[0]; if (javaResolveResult != JavaResolveResult.EMPTY && getOptions() != null) { final Boolean value = JavaClassReferenceProvider.RESOLVE_QUALIFIED_CLASS_NAME.getValue(getOptions()); final PsiClass psiClass = (PsiClass)javaResolveResult.getElement(); if (value != null && value.booleanValue() && psiClass != null) { final String qualifiedName = psiClass.getQualifiedName(); if (!qName.equals(qualifiedName)) { return JavaResolveResult.EMPTY; } } } return javaResolveResult; } } } return resolveResult != null ? new CandidateInfo(resolveResult, PsiSubstitutor.EMPTY, false, false, psiElement) : JavaResolveResult.EMPTY; }
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).isEmpty(); boolean otherDefault = otherQName != null && StringUtil.getPackageName(otherQName).isEmpty(); 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; }
@Override public boolean execute(@NotNull PsiElement element, ResolveState state) { if (!(element instanceof PsiClass)) return true; final PsiClass aClass = (PsiClass)element; final String name = aClass.getName(); if (!myClassName.equals(name)) { return true; } boolean accessible = myPlace == null || checkAccessibility(aClass); if (myCandidates == null) { myCandidates = new SmartList<ClassCandidateInfo>(); } else { String fqName = aClass.getQualifiedName(); if (fqName != null) { for (int i = myCandidates.size()-1; i>=0; i--) { ClassCandidateInfo info = myCandidates.get(i); Domination domination = dominates(aClass, accessible && isAccessible(aClass), fqName, info); if (domination == Domination.DOMINATED_BY) { return true; } else if (domination == Domination.DOMINATES) { myCandidates.remove(i); } } } } myHasAccessibleCandidate |= accessible; myHasInaccessibleCandidate |= !accessible; myCandidates.add(new ClassCandidateInfo(aClass, state.get(PsiSubstitutor.KEY), !accessible, myCurrentFileContext)); myResult = null; if (!accessible) return true; if (aClass.hasModifierProperty(PsiModifier.PRIVATE)) { final PsiClass containingPlaceClass = PsiTreeUtil.getParentOfType(myPlace, PsiClass.class, false); if (containingPlaceClass != null && !PsiTreeUtil.isAncestor(containingPlaceClass, aClass, false)){ return true; } } return myCurrentFileContext instanceof PsiImportStatementBase; }
private JavaResolveResult advancedResolveInner(final PsiElement psiElement, final String qName) { final PsiManager manager = psiElement.getManager(); final GlobalSearchScope scope = getScope(); if (myIndex == myJavaClassReferenceSet.getReferences().length - 1) { final PsiClass aClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(qName, scope); if (aClass != null) { return new ClassCandidateInfo(aClass, PsiSubstitutor.EMPTY, false, psiElement); } else { if (!JavaClassReferenceProvider.ADVANCED_RESOLVE.getBooleanValue(getOptions())) { return JavaResolveResult.EMPTY; } } } PsiElement resolveResult = JavaPsiFacade.getInstance(manager.getProject()).findPackage(qName); if (resolveResult == null) { resolveResult = JavaPsiFacade.getInstance(manager.getProject()).findClass(qName, scope); } if (myInStaticImport && resolveResult == null) { resolveResult = resolveMember(qName, manager, getElement().getResolveScope()); } if (resolveResult == null) { PsiFile containingFile = psiElement.getContainingFile(); if (containingFile instanceof PsiJavaFile) { if (containingFile instanceof JspFile) { containingFile = containingFile.getViewProvider().getPsi(JavaLanguage.INSTANCE); if (containingFile == null) return JavaResolveResult.EMPTY; } final ClassResolverProcessor processor = new ClassResolverProcessor(getCanonicalText(), psiElement, containingFile); containingFile.processDeclarations(processor, ResolveState.initial(), null, psiElement); if (processor.getResult().length == 1) { final JavaResolveResult javaResolveResult = processor.getResult()[0]; if (javaResolveResult != JavaResolveResult.EMPTY && getOptions() != null) { final Boolean value = JavaClassReferenceProvider.RESOLVE_QUALIFIED_CLASS_NAME.getValue(getOptions()); final PsiClass psiClass = (PsiClass)javaResolveResult.getElement(); if (value != null && value.booleanValue() && psiClass != null) { final String qualifiedName = psiClass.getQualifiedName(); if (!qName.equals(qualifiedName)) { return JavaResolveResult.EMPTY; } } } return javaResolveResult; } } } return resolveResult != null ? new CandidateInfo(resolveResult, PsiSubstitutor.EMPTY, false, false, psiElement) : JavaResolveResult.EMPTY; }
private Domination dominates(@NotNull PsiClass aClass, boolean accessible, @NotNull String fqName, @NotNull ClassCandidateInfo info) { final PsiClass otherClass = info.getElement(); 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).isEmpty(); boolean otherDefault = otherQName != null && StringUtil.getPackageName(otherQName).isEmpty(); 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; }
@Override public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) { if(!(element instanceof PsiClass)) { return true; } final PsiClass aClass = (PsiClass) element; final String name = aClass.getName(); if(!myClassName.equals(name)) { return true; } boolean accessible = myPlace == null || checkAccessibility(aClass); if(myCandidates == null) { myCandidates = new SmartList<ClassCandidateInfo>(); } else { String fqName = aClass.getQualifiedName(); if(fqName != null) { for(int i = myCandidates.size() - 1; i >= 0; i--) { ClassCandidateInfo info = myCandidates.get(i); Domination domination = dominates(aClass, accessible && isAccessible(aClass), fqName, info); if(domination == Domination.DOMINATED_BY) { return true; } else if(domination == Domination.DOMINATES) { myCandidates.remove(i); } } } } myHasAccessibleCandidate |= accessible; myHasInaccessibleCandidate |= !accessible; myCandidates.add(new ClassCandidateInfo(aClass, state.get(PsiSubstitutor.KEY), !accessible, myCurrentFileContext)); myResult = null; if(!accessible) { return true; } if(aClass.hasModifierProperty(PsiModifier.PRIVATE)) { final PsiClass containingPlaceClass = PsiTreeUtil.getParentOfType(myPlace, PsiClass.class, false); if(containingPlaceClass != null && !PsiTreeUtil.isAncestor(containingPlaceClass, aClass, false)) { return true; } } return myCurrentFileContext instanceof PsiImportStatementBase; }
@NotNull private JavaResolveResult doAdvancedResolve(@NotNull PsiFile containingFile) { final PsiElement psiElement = getElement(); if(!psiElement.isValid()) { return JavaResolveResult.EMPTY; } final String elementText = psiElement.getText(); final PsiElement context = getContext(); if(context instanceof PsiClass) { if(isStaticClassReference(elementText, false)) { final PsiClass psiClass = ((PsiClass) context).findInnerClassByName(getCanonicalText(), false); if(psiClass != null) { return new ClassCandidateInfo(psiClass, PsiSubstitutor.EMPTY, false, psiElement); } PsiElement member = doResolveMember((PsiClass) context, myText); return member == null ? JavaResolveResult.EMPTY : new CandidateInfo(member, PsiSubstitutor.EMPTY, false, false, psiElement); } else if(!myInStaticImport && myJavaClassReferenceSet.isAllowDollarInNames()) { return JavaResolveResult.EMPTY; } } final int endOffset = getRangeInElement().getEndOffset(); LOG.assertTrue(endOffset <= elementText.length(), elementText); final int startOffset = myJavaClassReferenceSet.getReference(0).getRangeInElement().getStartOffset(); final String qName = elementText.substring(startOffset, endOffset); if(!qName.contains(".")) { final String defaultPackage = JavaClassReferenceProvider.DEFAULT_PACKAGE.getValue(getOptions()); if(StringUtil.isNotEmpty(defaultPackage)) { final JavaResolveResult resolveResult = advancedResolveInner(psiElement, defaultPackage + "." + qName, containingFile); if(resolveResult != JavaResolveResult.EMPTY) { return resolveResult; } } } return advancedResolveInner(psiElement, qName, containingFile); }
private JavaResolveResult advancedResolveInner(@NotNull PsiElement psiElement, @NotNull String qName, @NotNull PsiFile containingFile) { final PsiManager manager = containingFile.getManager(); final GlobalSearchScope scope = getScope(containingFile); if(myIndex == myJavaClassReferenceSet.getReferences().length - 1) { final PsiClass aClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(qName, scope); if(aClass != null) { return new ClassCandidateInfo(aClass, PsiSubstitutor.EMPTY, false, psiElement); } else { if(!JavaClassReferenceProvider.ADVANCED_RESOLVE.getBooleanValue(getOptions())) { return JavaResolveResult.EMPTY; } } } PsiElement resolveResult = JavaPsiFacade.getInstance(manager.getProject()).findPackage(qName); if(resolveResult == null) { resolveResult = JavaPsiFacade.getInstance(manager.getProject()).findClass(qName, scope); } if(myInStaticImport && resolveResult == null) { resolveResult = resolveMember(qName, manager, getElement().getResolveScope()); } if(resolveResult == null) { if(containingFile instanceof PsiJavaFile) { if(containingFile instanceof ServerPageFile) { containingFile = containingFile.getViewProvider().getPsi(JavaLanguage.INSTANCE); if(containingFile == null) { return JavaResolveResult.EMPTY; } } final ClassResolverProcessor processor = new ClassResolverProcessor(getCanonicalText(), psiElement, containingFile); PsiClass contextClass = myJavaClassReferenceSet.getProvider().getContextClass(psiElement); if(contextClass != null) { PsiScopesUtil.treeWalkUp(processor, contextClass, null); } else { containingFile.processDeclarations(processor, ResolveState.initial(), null, psiElement); } if(processor.getResult().length == 1) { final JavaResolveResult javaResolveResult = processor.getResult()[0]; if(javaResolveResult != JavaResolveResult.EMPTY && getOptions() != null) { final Boolean value = JavaClassReferenceProvider.RESOLVE_QUALIFIED_CLASS_NAME.getValue(getOptions()); final PsiClass psiClass = (PsiClass) javaResolveResult.getElement(); if(value != null && value.booleanValue() && psiClass != null) { final String qualifiedName = psiClass.getQualifiedName(); if(!qName.equals(qualifiedName)) { return JavaResolveResult.EMPTY; } } } return javaResolveResult; } } } return resolveResult != null ? new CandidateInfo(resolveResult, PsiSubstitutor.EMPTY, false, false, psiElement) : JavaResolveResult.EMPTY; }