method chain completion: use proper qualifier, not method declaration class

This commit is contained in:
Dmitry Batkovich
2017-04-20 12:23:55 +03:00
parent 1cd85cfa2a
commit 9f13e80bc1
5 changed files with 38 additions and 27 deletions
@@ -222,30 +222,34 @@ class CompilerReferenceReader {
}
@Nullable("return null if the class hierarchy contains ambiguous qualified names")
private LightRef.NamedLightRef[] getWholeHierarchy(LightRef.LightClassHierarchyElementDef hierarchyElement, boolean checkBaseClassAmbiguity)
throws StorageException {
Set<LightRef.NamedLightRef> result = new THashSet<>();
Queue<LightRef.NamedLightRef> q = new Queue<>(10);
q.addLast(hierarchyElement);
while (!q.isEmpty()) {
LightRef.NamedLightRef curClass = q.pullFirst();
if (result.add(curClass)) {
if (checkBaseClassAmbiguity || curClass != hierarchyElement) {
if (hasMultipleDefinitions(curClass)) {
return null;
}
}
myIndex.get(CompilerIndices.BACK_HIERARCHY).getData(curClass).forEach((id, children) -> {
for (LightRef child : children) {
if (child instanceof LightRef.LightClassHierarchyElementDef && !(child instanceof LightRef.LightAnonymousClassDef)) {
q.addLast((LightRef.LightClassHierarchyElementDef) child);
LightRef.NamedLightRef[] getWholeHierarchy(LightRef.LightClassHierarchyElementDef hierarchyElement, boolean checkBaseClassAmbiguity) {
try {
Set<LightRef.NamedLightRef> result = new THashSet<>();
Queue<LightRef.NamedLightRef> q = new Queue<>(10);
q.addLast(hierarchyElement);
while (!q.isEmpty()) {
LightRef.NamedLightRef curClass = q.pullFirst();
if (result.add(curClass)) {
if (checkBaseClassAmbiguity || curClass != hierarchyElement) {
if (hasMultipleDefinitions(curClass)) {
return null;
}
}
return true;
});
myIndex.get(CompilerIndices.BACK_HIERARCHY).getData(curClass).forEach((id, children) -> {
for (LightRef child : children) {
if (child instanceof LightRef.LightClassHierarchyElementDef && !(child instanceof LightRef.LightAnonymousClassDef)) {
q.addLast((LightRef.LightClassHierarchyElementDef)child);
}
}
return true;
});
}
}
return result.toArray(new LightRef.NamedLightRef[result.size()]);
}
catch (StorageException e) {
throw new RuntimeException(e);
}
return result.toArray(new LightRef.NamedLightRef[result.size()]);
}
private enum DefCount { NONE, ONE, MANY}
@@ -32,7 +32,8 @@ public abstract class CompilerReferenceServiceEx extends CompilerReferenceServic
}
@NotNull
public abstract SortedSet<OccurrencesAware<MethodIncompleteSignature>> findMethodReferenceOccurrences(@NotNull String rawReturnType)
public abstract SortedSet<OccurrencesAware<MethodIncompleteSignature>> findMethodReferenceOccurrences(@NotNull String rawReturnType,
boolean allowIterators)
throws ReferenceIndexUnavailableException;
public abstract boolean mayHappen(@NotNull LightRef qualifier, @NotNull LightRef base, int probabilityThreshold)
@@ -221,17 +221,23 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceServiceEx imp
@NotNull
@Override
public SortedSet<OccurrencesAware<MethodIncompleteSignature>> findMethodReferenceOccurrences(@NotNull String rawReturnType) {
public SortedSet<OccurrencesAware<MethodIncompleteSignature>> findMethodReferenceOccurrences(@NotNull String rawReturnType,
boolean allowIterators) {
try {
myReadDataLock.lock();
if (myReader == null) throw new ReferenceIndexUnavailableException();
try {
final int type = myReader.getNameEnumerator().tryEnumerate(rawReturnType);
if (type == 0) return Collections.emptySortedSet();
return Stream.of(new SignatureData(type, true), new SignatureData(type, false))
return Stream.of(new SignatureData(type, (byte)0, true), new SignatureData(type, (byte)0, false))
.flatMap(sd -> myReader.getMembersFor(sd)
.stream()
.filter(r -> r instanceof LightRef.JavaLightMethodRef)
.map(r -> (LightRef.JavaLightMethodRef) r)
.flatMap(r -> {
LightRef.NamedLightRef[] hierarchy = myReader.getWholeHierarchy(r.getOwner(), false);
return hierarchy == null ? Stream.empty() : Arrays.stream(hierarchy).map(c -> r.override(c.getName()));
})
.map(r -> new OccurrencesAware<>(
new MethodIncompleteSignature((LightRef.JavaLightMethodRef)r, sd, this),
myReader.getOccurrenceCount(r))))
@@ -56,7 +56,7 @@ public class ChainsSearcher {
private static SearchInitializer createInitializer(TargetType target,
CompilerReferenceServiceEx compilerReferenceServiceEx,
ChainCompletionContext context) {
SortedSet<OccurrencesAware<MethodIncompleteSignature>> methods = compilerReferenceServiceEx.findMethodReferenceOccurrences(target.getClassQName());
SortedSet<OccurrencesAware<MethodIncompleteSignature>> methods = compilerReferenceServiceEx.findMethodReferenceOccurrences(target.getClassQName(), false);
return new SearchInitializer(methods, context);
}
@@ -96,7 +96,7 @@ public class ChainsSearcher {
continue;
}
String currentReturnType = headSignature.getOwner();
SortedSet<OccurrencesAware<MethodIncompleteSignature>> nextMethods = indexReader.findMethodReferenceOccurrences(currentReturnType);
SortedSet<OccurrencesAware<MethodIncompleteSignature>> nextMethods = indexReader.findMethodReferenceOccurrences(currentReturnType, false);
MaxSizeTreeSet<OccurrencesAware<MethodIncompleteSignature>> currentSignatures =
new MaxSizeTreeSet<>(maxResultSize);
for (OccurrencesAware<MethodIncompleteSignature> indexValue : nextMethods) {
@@ -9,7 +9,7 @@ interface PsiClass {}
public class TestCompletion {
public void method() {
PsiMember psiMember = null;
PsiClass c = psiMember.getContainingClass()
PsiMethod psiMethod = null;
PsiClass c = psiMethod.getContainingClass()
}
}