direct inheritor search with javac indices: do not forget of classes declared in method body (when internal is A$1Name)

This commit is contained in:
Dmitry Batkovich
2016-10-12 19:19:42 +03:00
parent 7ffc9297a5
commit cfbaa260fe
3 changed files with 36 additions and 9 deletions
@@ -159,17 +159,26 @@ public class JavaBaseCompilerSearchAdapter implements ClassResolvingCompilerSear
while (true) {
int lastIndex = internalName.lastIndexOf('$', curLast);
if (lastIndex > -1 && lastIndex < internalName.length() - 1) {
final boolean anonymousSign = Character.isDigit(internalName.charAt(lastIndex + 1));
if (anonymousSign) {
final int followingIndex = lastIndex + 1;
final boolean digit = Character.isDigit(internalName.charAt(followingIndex));
if (digit) {
if (curLast == internalName.length() - 1) {
if (matcherBySuperNameAdded) {
final int nextNonDigit = getNextNonDigitIndex(internalName, followingIndex);
if (nextNonDigit == -1) {
if (matcherBySuperNameAdded) {
break;
}
matcherBySuperNameAdded = true;
//anonymous
matchers.add(new InternalClassMatcher.BySuperName(baseClass.getName()));
break;
} else {
//declared inside method
matchers.add(new InternalClassMatcher.ByName(internalName.substring(nextNonDigit)));
}
matcherBySuperNameAdded = true;
matchers.add(new InternalClassMatcher.BySuperName(baseClass.getName()));
break;
}
else {
//declared in anonymous
matchers.add(new InternalClassMatcher.ByName(StringUtil.getShortName(internalName, '$')));
break;
}
@@ -185,6 +194,15 @@ public class JavaBaseCompilerSearchAdapter implements ClassResolvingCompilerSear
return matchers;
}
private static int getNextNonDigitIndex(String name, int digitIndex) {
for (int i = digitIndex + 1; i < name.length(); i++) {
if (!Character.isDigit(name.charAt(i))) {
return i;
}
}
return -1;
}
private interface InternalClassMatcher {
boolean matches(PsiClassStub stub);
@@ -0,0 +1,9 @@
class Test {
void m() {
class FooInsideMethodImpl extends Foo {}
}
}
@@ -80,17 +80,17 @@ public class CompilerReferencesTest extends AbstractCompilerAwareTest {
}
public void testHierarchy() {
myFixture.configureByFiles(getName() + "/Foo.java", getName() + "/FooImpl.java", getName() + "/Bar.java", getName() + "/Baz.java");
myFixture.configureByFiles(getName() + "/Foo.java", getName() + "/FooImpl.java", getName() + "/Bar.java", getName() + "/Baz.java", getName() + "/Test.java");
rebuildProject();
CompilerReferenceService.CompilerDirectInheritorInfo<PsiClass> directInheritorInfo = getHierarchyUnderForElementCaret();
Collection<PsiClass> inheritors = directInheritorInfo.getDirectInheritors().collect(Collectors.toList());
assertSize(4, inheritors);
assertSize(6, inheritors);
for (PsiClass inheritor : inheritors) {
if (inheritor instanceof PsiAnonymousClass) {
assertOneOf(inheritor.getTextOffset(), 58, 42, 94);
} else {
assertOneOf(inheritor.getQualifiedName(), "FooImpl", "FooImpl2");
assertOneOf(inheritor.getName(), "FooImpl", "FooImpl2", "FooInsideMethodImpl");
}
}