Skip to content

Commit

Permalink
fix: correct package assumption when there is a star import (INRIA#3338)
Browse files Browse the repository at this point in the history
  • Loading branch information
slarse authored May 5, 2020
1 parent c05f4c8 commit 6dd8258
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 2 deletions.
19 changes: 17 additions & 2 deletions src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
import spoon.reflect.reference.CtWildcardReference;
import spoon.support.reflect.CtExtendedModifier;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -1059,14 +1060,28 @@ void setPackageOrDeclaringType(CtTypeReference<?> ref, CtReference declaring) {
javaLangPackageReference.setSimpleName("java.lang");
ref.setPackage(javaLangPackageReference);
} catch (NoClassDefFoundError | ClassNotFoundException e) {
// in that case we consider the package should be the same as the current one. Fix #1293
ref.setPackage(jdtTreeBuilder.getContextBuilder().compilationUnitSpoon.getDeclaredPackage().getReference());
assert jdtTreeBuilder.getFactory().getEnvironment().getNoClasspath();
ContextBuilder ctx = jdtTreeBuilder.getContextBuilder();
if (containsStarImport(ctx.compilationunitdeclaration.imports)) {
// If there is an unresolved star import in noclasspath,
// we can't tell which package the type belongs to (#3337)
CtPackageReference pkgRef = jdtTreeBuilder.getFactory().Core().createPackageReference();
pkgRef.setImplicit(true);
ref.setPackage(pkgRef);
} else {
// otherwise the type must belong to the CU's package (#1293)
ref.setPackage(ctx.compilationUnitSpoon.getDeclaredPackage().getReference());
}
}
} else {
throw new AssertionError("unexpected declaring type: " + declaring.getClass() + " of " + declaring);
}
}

private static boolean containsStarImport(ImportReference[] imports) {
return imports != null && Arrays.stream(imports).anyMatch(imp -> imp.toString().endsWith("*"));
}

/**
* In noclasspath, lambda doesn't have always a binding for their variables accesses in their block/expression.
* Here, we make the job of JDT and bind their variables accesses to their parameters.
Expand Down
18 changes: 18 additions & 0 deletions src/test/java/spoon/test/pkg/PackageTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
import spoon.SpoonModelBuilder;
import spoon.compiler.Environment;
import spoon.compiler.SpoonResourceHelper;
import spoon.reflect.CtModel;
import spoon.reflect.code.CtComment;
import spoon.reflect.code.CtTypeAccess;
import spoon.reflect.declaration.CtAnnotation;
import spoon.reflect.declaration.CtAnnotationType;
import spoon.reflect.declaration.CtClass;
Expand Down Expand Up @@ -291,6 +293,22 @@ public void testAddAnnotationToPackage() throws Exception {
}
}

@Test
public void testNoPackageAssumptionWithStarImportNoClasspath() {
// contract: The package of a type not on the classpath should not guessed if there is an unresolved star import
final Launcher launcher = new Launcher();
launcher.getEnvironment().setNoClasspath(true);
launcher.addInputResource("./src/test/resources/noclasspath/TypeAccessStarImport.java");
CtModel model = launcher.buildModel();

List<CtTypeAccess<?>> typeAccesses = model.getElements(e -> e.getAccessedType().getSimpleName().equals("SomeClass"));
assertEquals("There should only be a single type access in the test source code", 1, typeAccesses.size());
CtPackageReference pkgRef = typeAccesses.get(0).getAccessedType().getPackage();

assertTrue(pkgRef.getSimpleName().isEmpty());
assertTrue(pkgRef.isImplicit());
}

@Test
public void testGetFQNSimple() {
// contract: CtPackageReference simple name is also the fully qualified name of its referenced package
Expand Down
10 changes: 10 additions & 0 deletions src/test/resources/noclasspath/TypeAccessStarImport.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// see https://github.com/inria/spoon/issues/3337

package bug;

import some.pkg.*;

public class TypeAccessStarImport {
// SomeClass could belong to either the bug package or some.pkg, should not guess which one!
int value = SomeClass.generateValue();
}

0 comments on commit 6dd8258

Please sign in to comment.