Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Symbolsolver import order #2521

Merged
merged 3 commits into from Feb 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -169,40 +169,26 @@ public SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
if (dotPos > -1) {
prefix = name.substring(0, dotPos);
}
// look into type imports
// look into single type imports
for (ImportDeclaration importDecl : wrappedNode.getImports()) {
if (!importDecl.isAsterisk()) {
String qName = importDecl.getNameAsString();
boolean defaultPackage = !importDecl.getName().getQualifier().isPresent();
boolean found = !defaultPackage && importDecl.getName().getIdentifier().equals(name);
if (!found) {
if (prefix != null) {
found = qName.endsWith("." + prefix);
if (found) {
qName = qName + name.substring(dotPos);
}
if (!found && prefix != null) {
found = qName.endsWith("." + prefix);
if (found) {
qName = qName + name.substring(dotPos);
}
}
if (found) {
SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
if (ref != null && ref.isSolved()) {
return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class);
} else {
return SymbolReference.unsolved(ResolvedTypeDeclaration.class);
}
}
}
}
// look into type imports on demand
for (ImportDeclaration importDecl : wrappedNode.getImports()) {
if (importDecl.isAsterisk()) {
String qName = importDecl.getNameAsString() + "." + name;
SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
if (ref != null && ref.isSolved()) {
return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class);
}
}
}
}

// Look in current package
Expand All @@ -221,6 +207,19 @@ public SymbolReference<ResolvedTypeDeclaration> solveType(String name) {
}
}

// look into asterisk imports on demand
if (wrappedNode.getImports() != null) {
for (ImportDeclaration importDecl : wrappedNode.getImports()) {
if (importDecl.isAsterisk()) {
String qName = importDecl.getNameAsString() + "." + name;
SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType(qName);
if (ref != null && ref.isSolved()) {
return SymbolReference.adapt(ref, ResolvedTypeDeclaration.class);
}
}
}
}

// Look in the java.lang package
SymbolReference<ResolvedReferenceTypeDeclaration> ref = typeSolver.tryToSolveType("java.lang." + name);
if (ref != null && ref.isSolved()) {
Expand Down
Expand Up @@ -40,16 +40,15 @@

public class TypeResolutionWithSameNameTest extends AbstractResolutionTest {


/*
* abstract class extends_duplicate.DuplicateTypeName
* class extends_duplicate.A extends extends_duplicate.DuplicateTypeName
* class extends_duplicate.A.DuplicateTypeName extends extends_duplicate.A
*/
@Test
void testTypesWithSameNameInPackageAndNested_directExtends() throws IOException {
Path srcRootPath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/src1");
Path extendsTypePath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/src1/extends_duplicate/A.java");
Path srcRootPath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/00_package_precedes_nested_class");
Path extendsTypePath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/00_package_precedes_nested_class/extends_duplicate/A.java");

JavaParserTypeSolver javaParserTypeSolver = new JavaParserTypeSolver(srcRootPath);
StaticJavaParser
Expand All @@ -67,20 +66,19 @@ void testTypesWithSameNameInPackageAndNested_directExtends() throws IOException
// Verify qualified name matches the non-nested class in the same package.
// Note verbose assertions show both the "correct" expected value, and the erroneous value to be avoided.
String qualifiedName = resolvedExtendedType.getQualifiedName();
assertEquals("extends_duplicate.DuplicateTypeName", qualifiedName, "Error - not resolved to interface in separate file.");
assertNotEquals("extends_duplicate.A.DuplicateTypeName", qualifiedName, "Error - resolved to nested class.");
assertEquals("extends_duplicate.DuplicateTypeName", qualifiedName, "Error - not resolved to the class in the package.");
assertNotEquals("extends_duplicate.A.DuplicateTypeName", qualifiedName, "Error - mistakenly resolved to a nested class instead of the expected class.");
}


/*
* interface implements_duplicate.DuplicateTypeName
* class implements_duplicate.class A implements implements_duplicate.DuplicateTypeName
* class implements_duplicate.A.DuplicateTypeName extends implements_duplicate.A
*/
@Test
void testTypesWithSameNameInPackageAndNested_directImplements() throws IOException {
Path srcRootPath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/src2");
Path implementingTypePath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/src2/implements_duplicate/A.java");
Path srcRootPath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/01_package_precedes_nested_interface");
Path implementingTypePath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/01_package_precedes_nested_interface/implements_duplicate/A.java");

JavaParserTypeSolver javaParserTypeSolver = new JavaParserTypeSolver(srcRootPath);
StaticJavaParser
Expand All @@ -98,9 +96,80 @@ void testTypesWithSameNameInPackageAndNested_directImplements() throws IOExcepti
// Verify qualified name matches the non-nested class in the same package.
// Note verbose assertions show both the "correct" expected value, and the erroneous value to be avoided.
String qualifiedName = resolvedImplementedType.getQualifiedName();
assertEquals("implements_duplicate.DuplicateTypeName", qualifiedName, "Error - not resolved to interface in separate file.");
assertNotEquals("implements_duplicate.A.DuplicateTypeName", qualifiedName, "Error - resolved to nested class.");
assertEquals("implements_duplicate.DuplicateTypeName", qualifiedName, "Error - not resolved to interface in the package.");
assertNotEquals("implements_duplicate.A.DuplicateTypeName", qualifiedName, "Error - mistakenly resolved to a nested class instead of the expected interface.");
}

@Test
void testTypesWithSameNameStaticNonTypeAndNonStaticType() throws IOException {
Path srcRootPath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/02_ignore_static_non_type_import");
Path mainPath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/02_ignore_static_non_type_import/main/Main.java");

JavaParserTypeSolver javaParserTypeSolver = new JavaParserTypeSolver(srcRootPath);
StaticJavaParser
.getConfiguration()
.setSymbolResolver(new JavaSymbolSolver(javaParserTypeSolver));

CompilationUnit cu = StaticJavaParser.parse(mainPath);
ClassOrInterfaceDeclaration c = Navigator.demandClass(cu, "Main");

String qualifiedName = c.getFieldByName("field_a").get().resolve().getType().describe();
assertEquals("another.A", qualifiedName, "Error - not resolved to a class.");
assertNotEquals("another.MyEnum.A", qualifiedName, "Error - mistakenly resolved to an enum member instead of the expected class.");
}

@Test
void testTypesWithSameNameSingleTypeImportAndPackage() throws IOException {
Path srcRootPath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/03_single_type_import_precedes_package_member");
Path mainPath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/03_single_type_import_precedes_package_member/main/Main.java");

JavaParserTypeSolver javaParserTypeSolver = new JavaParserTypeSolver(srcRootPath);
StaticJavaParser
.getConfiguration()
.setSymbolResolver(new JavaSymbolSolver(javaParserTypeSolver));

CompilationUnit cu = StaticJavaParser.parse(mainPath);
ClassOrInterfaceDeclaration c = Navigator.demandClass(cu, "Main");

String qualifiedName = c.getFieldByName("field_a").get().resolve().getType().describe();
assertEquals("another.A", qualifiedName, "Error - not resolved to the imorted class.");
assertNotEquals("main.A", qualifiedName, "Error - mistakenly resolved to a package member insted of the explicitly imported class.");
}

@Test
void testTypesWithSameNamePackageAndAsteriskImport() throws IOException {
Path srcRootPath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/04_package_member_precedes_asterisk_import");
Path mainPath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/04_package_member_precedes_asterisk_import/main/Main.java");

JavaParserTypeSolver javaParserTypeSolver = new JavaParserTypeSolver(srcRootPath);
StaticJavaParser
.getConfiguration()
.setSymbolResolver(new JavaSymbolSolver(javaParserTypeSolver));

CompilationUnit cu = StaticJavaParser.parse(mainPath);
ClassOrInterfaceDeclaration c = Navigator.demandClass(cu, "Main");

String qualifiedName = c.getFieldByName("field_a").get().resolve().getType().describe();
assertEquals("main.A", qualifiedName, "Error - not resolved to a package member.");
assertNotEquals("another.A", qualifiedName, "Error - mistakenly resolved to an asterisk-imported class instead of the expected package member.");
}

@Test
void testTypesWithSameNameAsteriskImportAndJavaLang() throws IOException {
Path srcRootPath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/05_asterisk_import_precedes_java_lang");
Path mainPath = adaptPath("src/test/resources/TypeResolutionWithSameNameTest/05_asterisk_import_precedes_java_lang/main/Main.java");

JavaParserTypeSolver javaParserTypeSolver = new JavaParserTypeSolver(srcRootPath);
StaticJavaParser
.getConfiguration()
.setSymbolResolver(new JavaSymbolSolver(javaParserTypeSolver));

CompilationUnit cu = StaticJavaParser.parse(mainPath);
ClassOrInterfaceDeclaration c = Navigator.demandClass(cu, "Main");

String qualifiedName = c.getFieldByName("s").get().resolve().getType().describe();
assertEquals("another.String", qualifiedName, "Error - not resolved to an asterisk-imported class.");
assertNotEquals("java.lang.String", qualifiedName, "Error - mistakenly resolved to a member of java.lang instead of a member of asterisk-imported package.");
}

}
@@ -0,0 +1,4 @@
package another;

class A {
}
@@ -0,0 +1,5 @@
package another;

enum MyEnum {
A;
}
@@ -0,0 +1,8 @@
package main;

import static another.MyEnum.A;
import another.A;

class Main {
A field_a;
}
@@ -0,0 +1,4 @@
package another;

class A {
}
@@ -0,0 +1,4 @@
package main;

class A {
}
@@ -0,0 +1,7 @@
package main;

import another.A;

class Main {
A field_a;
}
@@ -0,0 +1,4 @@
package another;

class A {
}
@@ -0,0 +1,4 @@
package main;

class A {
}
@@ -0,0 +1,7 @@
package main;

import another.*;

class Main {
A field_a;
}
@@ -0,0 +1,4 @@
package another;

class String {
}
@@ -0,0 +1,7 @@
package main;

import another.*;

class Main {
String s;
}