Skip to content

Commit

Permalink
Merge pull request #2927 from jlerbsc/master
Browse files Browse the repository at this point in the history
Fix issue 2909 improving search for the most relevant declaration of the specified class
  • Loading branch information
jlerbsc committed Nov 16, 2020
2 parents 2deaa1a + e487f61 commit 818946f
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.github.javaparser.JavaParser;
import com.github.javaparser.JavaToken;
Expand Down Expand Up @@ -506,12 +507,14 @@ public Optional<ClassOrInterfaceDeclaration> getClassByName(String className) {
}

/**
* Try to get a locally class declaration by its name (top level or inner class)
* Try to get all local class declarations ending by its name (top level or inner class)
*
* @param className the class name (case-sensitive)
*/
public Optional<ClassOrInterfaceDeclaration> getLocaleDeclarationFromClassname(String className) {
return findAll(ClassOrInterfaceDeclaration.class).stream().filter(cid->cid.getNameAsString().equals(className)).findFirst();
public List<ClassOrInterfaceDeclaration> getLocalDeclarationFromClassname(String className) {
return findAll(ClassOrInterfaceDeclaration.class).stream()
.filter(cid->cid.getFullyQualifiedName().get().endsWith(className))
.collect(Collectors.toList());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,10 @@ public ResolvedType visit(ThisExpr node, Boolean solveLambdas) {
// Attempt to resolve locally in Compilation unit
Optional<CompilationUnit> cu = node.findAncestor(CompilationUnit.class);
if (cu.isPresent()) {
// Try to resolve in the compilation unit by its name
Optional<ClassOrInterfaceDeclaration> classByName = cu.get().getLocaleDeclarationFromClassname(className);
if (classByName.isPresent()) {
return new ReferenceTypeImpl(facade.getTypeDeclaration(classByName.get()), typeSolver);
// Try to resolve the class name from the compilation unit (the last statement is considered to be the most relevant)
List<ClassOrInterfaceDeclaration> localDeclarations = cu.get().getLocalDeclarationFromClassname(className);
if (!localDeclarations.isEmpty()) {
return new ReferenceTypeImpl(facade.getTypeDeclaration(localDeclarations.get(localDeclarations.size()-1)), typeSolver);
}
}
return new ReferenceTypeImpl(facade.getTypeDeclaration(facade.findContainingTypeDeclOrObjectCreationExpr(node, className)), typeSolver);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,47 @@ void testResolvingLocallyFromPartialReferenceToInnerClass() {
assertEquals("Program.OuterClass",expr.calculateResolvedType().describe());
});
}

@Test
void test() {
ParserConfiguration config = new ParserConfiguration();
config.setSymbolResolver(new JavaSymbolSolver(new ReflectionTypeSolver(false)));
StaticJavaParser.setConfiguration(config);

String s = "package test;\n" +
"\n" +
"public class Program {\n" +
"\n" +
" public class OuterClass {\n" +
" }\n" +
"\n" +
" public class FarOuterClass {\n" +
"\n" +
" public class OuterClass {\n" +
" int field = 0;\n" +
"\n" +
" public class InnerClass {\n" +
" InnerClass() {\n" +
" // Different cases to refer to enclosing type\n" +
" OuterClass outer1 = OuterClass.this; // case1\n" +
" OuterClass.this.field = 1; // case1\n" +
" OuterClass outer2 = FarOuterClass.OuterClass.this; // case2\n" +
" FarOuterClass.OuterClass.this.field = 1; // case2\n" +
" OuterClass outer3 = Program.FarOuterClass.OuterClass.this; // case3\n" +
" Program.FarOuterClass.OuterClass.this.field = 1; // case3\n" +
" OuterClass outer4 = test.Program.FarOuterClass.OuterClass.this; // case4\n" +
" test.Program.FarOuterClass.OuterClass.this.field = 1; // case4\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}";

CompilationUnit cu = StaticJavaParser.parse(s);
List<ThisExpr> exprs = cu.findAll(ThisExpr.class);
exprs.forEach(expr-> {
assertEquals("test.Program.FarOuterClass.OuterClass",expr.calculateResolvedType().describe());
System.out.println(String.format("%s is resolved to %s", expr.toString(), expr.calculateResolvedType().describe()));
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
public class OuterClass {
}

0 comments on commit 818946f

Please sign in to comment.