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

fix: Fix NullPointerException when allowing duplicate classes #3709

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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ static TypeBinding searchTypeBinding(String qualifiedName, CompilationUnitDeclar
for (CompilationUnitDeclaration unitToProcess : unitsToProcess) {
if (unitToProcess.types != null) {
for (TypeDeclaration type : unitToProcess.types) {
if (qualifiedName.equals(CharOperation.toString(type.binding.compoundName))) {
if (type.binding != null
&& qualifiedName.equals(CharOperation.toString(type.binding.compoundName))) {
return type.binding;
}
if (type.memberTypes != null) {
Expand Down
30 changes: 28 additions & 2 deletions src/test/java/spoon/test/model/TypeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.junit.Test;
import spoon.Launcher;
import spoon.compiler.ModelBuildingException;
import spoon.reflect.CtModel;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtType;
Expand All @@ -19,8 +20,11 @@
import spoon.reflect.reference.CtTypeReference;
import spoon.reflect.visitor.filter.AllTypeMembersFunction;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
Expand Down Expand Up @@ -140,7 +144,7 @@ public void testGetDeclaredOrIheritedFieldByReflection() throws Exception {

assertEquals("buf", type.getDeclaredOrInheritedField("buf").getSimpleName());
assertEquals("count", type.getDeclaredOrInheritedField("count").getSimpleName());

}

@Test
Expand Down Expand Up @@ -176,7 +180,29 @@ public void testMultiClassEnable() {
spoon.buildModel();
assertNotNull(spoon.getFactory().Class().get("A"));
}


@Test
public void testMultiClassEnableWithStaticFieldAccessToNestedType() {
// test that ignoring duplicate classes works out when there in class A is a static field
// access C.someField to a nested type B.C, and A has imported B.C.
// This forces Spoon to search for the type C with JDTTreeBuilder.searchTypeBinding.
// See https://github.com/INRIA/spoon/issues/3707 for details.

Launcher launcher = new Launcher();
launcher.getEnvironment().setIgnoreDuplicateDeclarations(true);

launcher.addInputResource("src/test/resources/duplicates-in-submodules/moduleA");
launcher.addInputResource("src/test/resources/duplicates-in-submodules/moduleB");

CtModel model = launcher.buildModel();

Set<String> expectedTypeNames = new HashSet<>(
Arrays.asList("duplicates.Duplicate", "duplicates.Main", "duplicates.WithNestedEnum"));
Set<String> typeNames = model.getAllTypes().stream().map(CtType::getQualifiedName).collect(Collectors.toSet());

assertEquals(expectedTypeNames, typeNames);
}

private void checkIsSomething(String expectedType, CtType type) {
_checkIsSomething(expectedType, type);
_checkIsSomething(expectedType, type.getReference());
Expand Down
1 change: 1 addition & 0 deletions src/test/resources/duplicates-in-submodules/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Test files to replicate https://github.com/INRIA/spoon/issues/3707
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package duplicates;

public class Duplicate {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package duplicates;

import duplicates.WithNestedEnum.NestedEnum;

public class Main {
public static void main(String[] args) {
System.out.println(NestedEnum.YES.name());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package duplicates;

class WithNestedEnum {
public enum NestedEnum {
YES;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package duplicates;

public class Duplicate {}