From 3a8d04df7cb0319896ae98b08986a7006b208fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Lars=C3=A9n?= Date: Mon, 11 May 2020 15:01:17 +0200 Subject: [PATCH] fix: Ensure unqualified member access remains unqualified (#3364) --- .../compiler/jdt/JDTTreeBuilderHelper.java | 7 ++++++- .../test/reference/TypeReferenceTest.java | 20 +++++++++++++++++++ .../UnqualifiedExternalTypeMemberAccess.java | 9 +++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/test/resources/noclasspath/UnqualifiedExternalTypeMemberAccess.java diff --git a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilderHelper.java b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilderHelper.java index 2c7033e5f44..274f3c4b327 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilderHelper.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilderHelper.java @@ -639,7 +639,12 @@ CtTypeAccess createTypeAccessNoClasspath(SingleNameReference singleNameRe } else { typeReference.setSimpleName(CharOperation.charToString(singleNameReference.binding.readableName())); } - jdtTreeBuilder.getReferencesBuilder().setPackageOrDeclaringType(typeReference, jdtTreeBuilder.getReferencesBuilder().getDeclaringReferenceFromImports(singleNameReference.token)); + CtReference packageOrDeclaringType = jdtTreeBuilder.getReferencesBuilder().getDeclaringReferenceFromImports(singleNameReference.token); + if (packageOrDeclaringType != null) { + // must be implicit as a SingleNameReference is not qualified, see #3363 + packageOrDeclaringType.setImplicit(true); + } + jdtTreeBuilder.getReferencesBuilder().setPackageOrDeclaringType(typeReference, packageOrDeclaringType); return jdtTreeBuilder.getFactory().Code().createTypeAccess(typeReference); } diff --git a/src/test/java/spoon/test/reference/TypeReferenceTest.java b/src/test/java/spoon/test/reference/TypeReferenceTest.java index 3202821f1b3..4598f44f89d 100644 --- a/src/test/java/spoon/test/reference/TypeReferenceTest.java +++ b/src/test/java/spoon/test/reference/TypeReferenceTest.java @@ -731,4 +731,24 @@ private static CtTypeReference getDeepestComponentType(CtArrayTypeReference) ref; } + + @Test + public void testUnqualifiedExternalTypeMemberAccess() { + // contract: if a type member is accessed without qualification, but it is not part of the current + // compilation unit, any qualification attached to it through import resolution must remain implicit + // See #3363 for details + final Launcher launcher = new Launcher(); + launcher.addInputResource("./src/test/resources/noclasspath/UnqualifiedExternalTypeMemberAccess.java"); + launcher.getEnvironment().setNoClasspath(true); + CtModel model = launcher.buildModel(); + List> typeReferences = model.getElements(e -> e.getSimpleName().equals("SOMETHING")); + + assertEquals("There should only be one reference to SOMETHING, check the resource!", 1, typeReferences.size()); + + CtTypeReference typeRef = typeReferences.get(0); + CtTypeReference declType = typeRef.getDeclaringType(); + + assertEquals("Constants", declType.getSimpleName()); + assertTrue(declType.isImplicit()); + } } diff --git a/src/test/resources/noclasspath/UnqualifiedExternalTypeMemberAccess.java b/src/test/resources/noclasspath/UnqualifiedExternalTypeMemberAccess.java new file mode 100644 index 00000000000..483615cb2b7 --- /dev/null +++ b/src/test/resources/noclasspath/UnqualifiedExternalTypeMemberAccess.java @@ -0,0 +1,9 @@ +package pkg; + +import static pkg.constants.Constants.SOMETHING; + +public class UnqualifiedExternalTypeMemberAccess { + public static void main(String[] args) { + System.out.println(SOMETHING); + } +} \ No newline at end of file