[java] Improve symboltable for inner classes

This commit is contained in:
Andreas Dangel
2021-12-16 20:30:44 +01:00
parent 8df5768bc9
commit 2f95d99b35
4 changed files with 110 additions and 14 deletions

View File

@ -226,17 +226,15 @@ public class ClassScope extends AbstractJavaScope {
result.add(finder.getDecl());
}
// search inner classes
// search references to inner classes
Map<ClassNameDeclaration, List<NameOccurrence>> classDeclarations = getClassDeclarations();
if (result.isEmpty() && !classDeclarations.isEmpty()) {
Applier.apply(finder, classDeclarations.keySet().iterator());
if (finder.getDecl() != null) {
result.add(finder.getDecl());
}
for (ClassNameDeclaration innerClass : getClassDeclarations().keySet()) {
ASTMethodDeclarator md = innerClass.getNode().getFirstDescendantOfType(ASTMethodDeclarator.class);
if (md != null) {
images.add(md.getImage());
finder = new ImageFinderFunction(images);
}
Applier.apply(finder, innerClass.getScope().getDeclarations(VariableNameDeclaration.class).keySet().iterator());
Applier.apply(finder, innerClass.getScope().getDeclarations(MethodNameDeclaration.class).keySet().iterator());
if (finder.getDecl() != null) {
result.add(finder.getDecl());
}

View File

@ -650,6 +650,24 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class Foo {
private String bar;
}
]]></code>
</test-code>
<test-code>
<description>False positive when referenced from within inner class</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
private static final String OUTER_CONSTANT = "";
private static final class Empty {
private static final class Inner {
public boolean isEmpty(String s) {
return OUTER_CONSTANT.equals(s);
}
}
}
}
]]></code>
</test-code>

View File

@ -1734,14 +1734,13 @@ public class Outer {
<code><![CDATA[
public class OuterClass {
public void foo() {
InnerClass.doSomething();
}
public void foo() {
InnerClass.doSomething();
}
static class InnerClass {
private static void doSomething() {
}
}
static class InnerClass {
private static void doSomething() {}
}
}
]]></code>
</test-code>

View File

@ -278,4 +278,85 @@ public class Foo {
}
]]></code>
</test-code>
<test-code>
<description>False negatives for inner class references</description>
<expected-problems>4</expected-problems>
<expected-linenumbers>3,5,7,21</expected-linenumbers>
<code><![CDATA[
// from https://github.com/checkstyle/checkstyle/blob/checkstyle-9.1/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/antlr4/InputAntlr4AstRegressionUncommon.java#L185
class OtherClass {
Object x;
class SuperClassA{
protected SuperClassA bs;
protected SuperClassA s; // this is actually a false negative
Object s2;
private void method() {
x = new Object();
}
}
class SuperClassA2{}
/*
* Note: inherited fields of a nested class shadow outer scope variables
* Note: only if they are accessible!
*/
public class FieldAccessSuper extends SuperClassA {
private SuperClassA s;
public void foo() {
// simple super field access
// Primary[Prefix[Name[s]]]
s = new SuperClassA();
// access inherited field through primary
// Primary[ Prefix[Primary[(this)]], Suffix[s], Suffix[s2] ]
(this).s.s2 = new SuperClassA2();
this.s.s2 = new SuperClassA2();
// access inherited field, second 's' has inherited field 's2'
// Primary[Prefix[Name[s.s.s2]]]
s.s.s2 = new SuperClassA2();
// field access through super
// Primary[Prefix["super"], Suffix["field"]]
super.s = new SuperClassA();
// fully qualified case
// Primary[Prefix[Name[net...FieldAccessSuper]], Suffix[this], Suffix[s]]
FieldAccessSuper.this.s
= new SuperClassA();
}
public class Nested extends SuperClassA {
SuperClassA a;
class SubscriptionAdapter{}
final /* synthetic */ SubscriptionAdapter this$0 = null;
final /* synthetic */ Object val$argHolder = null;
public void foo() {
// access enclosing super field
// Primary[Prefix[Name[s]]]
s = new SuperClassA();
// access Nested inherited field
// Primary[Prefix[Name[bs]]]
bs = new SuperClassA();
// access super field with fully qualified stuff
// Primary[Prefix["FieldAccessSuper"], Suffix[Nested],
// Suffix["super"], Suffix["bs"]]
FieldAccessSuper.Nested.super.bs = new SuperClassA();
// refers to the enclosing class's immediate super class's field
// Primary[Prefix["FieldAccessSuper"], Suffix["super"], Suffix["s"]]
FieldAccessSuper.super.s = new SuperClassA();
}
}
}
}
]]></code>
</test-code>
</test-data>