mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
during resolve and search for inheritors prefer classes from my own jar
This commit is contained in:
@@ -21,7 +21,6 @@ import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.augment.PsiAugmentProvider;
|
||||
import com.intellij.psi.filters.OrFilter;
|
||||
import com.intellij.psi.impl.compiled.ClsElementImpl;
|
||||
import com.intellij.psi.impl.source.PsiImmediateClassType;
|
||||
@@ -39,10 +38,7 @@ import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.ui.IconDeferrer;
|
||||
import com.intellij.ui.RowIcon;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ReflectionCache;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -864,6 +860,7 @@ public class PsiClassImplUtil {
|
||||
}
|
||||
|
||||
public static boolean isClassEquivalentTo(PsiClass aClass, PsiElement another) {
|
||||
if (aClass == another) return true;
|
||||
if (!(another instanceof PsiClass)) return false;
|
||||
String name1 = aClass.getName();
|
||||
if (name1 == null) return false;
|
||||
@@ -900,17 +897,13 @@ public class PsiClassImplUtil {
|
||||
|
||||
final PsiFile file1 = aClass.getContainingFile().getOriginalFile();
|
||||
final PsiFile file2 = another.getContainingFile().getOriginalFile();
|
||||
if (file1.equals(file2)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//see com.intellij.openapi.vcs.changes.PsiChangeTracker
|
||||
//see com.intellij.psi.impl.PsiFileFactoryImpl#createFileFromText(CharSequence,PsiFile)
|
||||
final PsiFile original1 = file1.getUserData(PsiFileFactory.ORIGINAL_FILE);
|
||||
final PsiFile original2 = file2.getUserData(PsiFileFactory.ORIGINAL_FILE);
|
||||
if (original1 == original2 && original1 != null
|
||||
|| original1 == file2 || original2 == file1) {
|
||||
return true;
|
||||
if (original1 == original2 && original1 != null || original1 == file2 || original2 == file1 || file1 == file2) {
|
||||
return compareClassSeqNumber(aClass, (PsiClass)another);
|
||||
}
|
||||
|
||||
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(aClass.getProject()).getFileIndex();
|
||||
@@ -920,6 +913,28 @@ public class PsiClassImplUtil {
|
||||
(fileIndex.isInSource(vfile2) || fileIndex.isInLibraryClasses(vfile2));
|
||||
}
|
||||
|
||||
private static boolean compareClassSeqNumber(PsiClass aClass, PsiClass another) {
|
||||
// there may be several classes in one file, they must not be equal
|
||||
int index1 = getSeqNumber(aClass);
|
||||
if (index1 == -1) return true;
|
||||
int index2 = getSeqNumber(another);
|
||||
return index1 == index2;
|
||||
}
|
||||
|
||||
private static int getSeqNumber(PsiClass aClass) {
|
||||
// sequence number of this class among its parent' child classes named the same
|
||||
PsiElement parent = aClass.getParent();
|
||||
if (parent == null) return -1;
|
||||
int seqNo = 0;
|
||||
for (PsiElement child : parent.getChildren()) {
|
||||
if (child == aClass) return seqNo;
|
||||
if (child instanceof PsiClass && Comparing.strEqual(aClass.getName(), ((PsiClass)child).getName())) {
|
||||
seqNo++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static PsiElement originalElement(PsiClass aClass) {
|
||||
final PsiElement originalElement = aClass.getOriginalElement();
|
||||
final PsiCompiledElement compiled = originalElement.getUserData(ClsElementImpl.COMPILED_ELEMENT);
|
||||
|
||||
+10
-1
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.psi.impl.PsiSubstitutorImpl;
|
||||
import com.intellij.psi.impl.search.JavaDirectInheritorsSearcher;
|
||||
import com.intellij.psi.impl.source.resolve.ResolveCache;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
@@ -167,7 +168,15 @@ public class ClsJavaCodeReferenceElementImpl extends ClsElementImpl implements P
|
||||
for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable((PsiTypeParameterListOwner)element)) {
|
||||
if (myQualifiedName.equals(parameter.getName())) return parameter;
|
||||
}
|
||||
return JavaPsiFacade.getInstance(getProject()).findClass(myQualifiedName, getResolveScope());
|
||||
return resolveClassPreferringMyJar();
|
||||
}
|
||||
|
||||
private PsiClass resolveClassPreferringMyJar() {
|
||||
PsiClass[] classes = JavaPsiFacade.getInstance(getProject()).findClasses(myQualifiedName, getResolveScope());
|
||||
for (PsiClass aClass : classes) {
|
||||
if (JavaDirectInheritorsSearcher.isFromTheSameJar(aClass, this)) return aClass;
|
||||
}
|
||||
return classes.length == 0 ? null : classes[0];
|
||||
}
|
||||
|
||||
public void processVariants(PsiScopeProcessor processor) {
|
||||
|
||||
@@ -8,6 +8,8 @@ import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiManagerImpl;
|
||||
import com.intellij.psi.impl.java.stubs.index.JavaAnonymousClassBaseRefOccurenceIndex;
|
||||
@@ -19,14 +21,17 @@ import com.intellij.psi.search.searches.AllClassesSearch;
|
||||
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, DirectClassInheritorsSearch.SearchParameters> {
|
||||
|
||||
public boolean execute(final DirectClassInheritorsSearch.SearchParameters p, final Processor<PsiClass> consumer) {
|
||||
final PsiClass aClass = p.getClassToProcess();
|
||||
final PsiManagerImpl psiManager = (PsiManagerImpl)PsiManager.getInstance(aClass.getProject());
|
||||
@@ -73,10 +78,22 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
}
|
||||
});
|
||||
|
||||
Map<String, List<PsiClass>> classes = new HashMap<String, List<PsiClass>>();
|
||||
|
||||
for (PsiReferenceList referenceList : candidates) {
|
||||
ProgressManager.checkCanceled();
|
||||
PsiClass candidate = (PsiClass)referenceList.getParent();
|
||||
if (!consumer.process(candidate)) return false;
|
||||
String fqn = candidate.getQualifiedName();
|
||||
List<PsiClass> list = classes.get(fqn);
|
||||
if (list == null) {
|
||||
list = new ArrayList<PsiClass>();
|
||||
classes.put(fqn, list);
|
||||
}
|
||||
list.add(candidate);
|
||||
}
|
||||
|
||||
for (List<PsiClass> sameNamedClasses : classes.values()) {
|
||||
if (!processSameNamedClasses(consumer, aClass, sameNamedClasses)) return false;
|
||||
}
|
||||
|
||||
if (p.includeAnonymous()) {
|
||||
@@ -116,4 +133,37 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean processSameNamedClasses(Processor<PsiClass> consumer, PsiClass aClass, List<PsiClass> sameNamedClasses) {
|
||||
// if there is a class from the same jar, prefer it
|
||||
boolean sameJarClassFound = false;
|
||||
for (PsiClass sameNamedClass : sameNamedClasses) {
|
||||
boolean fromSameJar = isFromTheSameJar(sameNamedClass, aClass);
|
||||
if (fromSameJar) {
|
||||
sameJarClassFound = true;
|
||||
if (!consumer.process(sameNamedClass)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sameJarClassFound) {
|
||||
for (PsiClass sameNamedClass : sameNamedClasses) {
|
||||
if (!consumer.process(sameNamedClass)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static VirtualFile getJarFile(PsiElement candidate) {
|
||||
VirtualFile file = candidate.getContainingFile().getVirtualFile();
|
||||
if (file != null && file.getFileSystem() instanceof JarFileSystem) {
|
||||
return JarFileSystem.getInstance().getVirtualFileForJar(file);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
public static boolean isFromTheSameJar(PsiElement candidate, PsiElement other) {
|
||||
VirtualFile c1 = getJarFile(candidate);
|
||||
VirtualFile c2 = getJarFile(other);
|
||||
return c1 != null && c1 == c2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user