diff options
author | cushon <cushon@google.com> | 2017-08-25 15:41:25 -0700 |
---|---|---|
committer | Liam Miller-Cushon <cushon@google.com> | 2017-08-28 15:16:12 -0700 |
commit | 7e739192557087e402693d4e0c1f342459ad04f6 (patch) | |
tree | 462e137acac7add5668e78c7b07e78cb21d9e384 | |
parent | b44b5f69708f02440bb278402d8155963391d832 (diff) | |
download | turbine-7e739192557087e402693d4e0c1f342459ad04f6.tar.gz |
Short-circuit import based name resolution for the enclosing type
This should usually be a no-op, but it avoids import completion in some
situations when resolving a type inside its own declaration. This fix
allows such compilations to succeed with unresolvable unused imports.
It's also a minor performance improvement.
MOE_MIGRATED_REVID=166535423
-rw-r--r-- | java/com/google/turbine/binder/TypeBinder.java | 5 | ||||
-rw-r--r-- | javatests/com/google/turbine/lower/LowerTest.java | 63 |
2 files changed, 66 insertions, 2 deletions
diff --git a/java/com/google/turbine/binder/TypeBinder.java b/java/com/google/turbine/binder/TypeBinder.java index 402de98..5bee45d 100644 --- a/java/com/google/turbine/binder/TypeBinder.java +++ b/java/com/google/turbine/binder/TypeBinder.java @@ -151,12 +151,12 @@ public class TypeBinder { CompoundScope enclosingScope = base.scope() .toScope(Resolve.resolveFunction(env, owner)) + .append(new SingletonScope(base.decl().name(), owner)) .append(new ClassMemberScope(base.owner(), env)); ImmutableList<AnnoInfo> annotations = bindAnnotations(enclosingScope, base.decl().annos()); - CompoundScope bindingScope = - enclosingScope.append(new SingletonScope(base.decl().name(), owner)); + CompoundScope bindingScope = enclosingScope; // type parameters can refer to each other in f-bounds, so update the scope first bindingScope = bindingScope.append(new MapScope(base.typeParameters())); @@ -206,6 +206,7 @@ public class TypeBinder { CompoundScope scope = base.scope() .toScope(Resolve.resolveFunction(env, owner)) + .append(new SingletonScope(base.decl().name(), owner)) .append(new ClassMemberScope(owner, env)); List<MethodInfo> methods = diff --git a/javatests/com/google/turbine/lower/LowerTest.java b/javatests/com/google/turbine/lower/LowerTest.java index 8fe8214..7d916fd 100644 --- a/javatests/com/google/turbine/lower/LowerTest.java +++ b/javatests/com/google/turbine/lower/LowerTest.java @@ -423,4 +423,67 @@ public class LowerTest { 0); assertThat((acc[0] & Opcodes.ACC_DEPRECATED) == Opcodes.ACC_DEPRECATED).isTrue(); } + + @Test + public void lazyImports() throws Exception { + ImmutableMap<String, String> sources = + ImmutableMap.<String, String>builder() + .put( + "b/B.java", + lines( + "package b;", // + "public class B {", + " public static class A {", + " public static final int X = 0;", + " }", + " public static class C {}", + "}")) + .put( + "anno/Anno.java", + lines( + "package anno;", // + "public @interface Anno {", + " int value() default 0;", + "}")) + .put( + "a/A.java", + lines( + "package a;", // + "import b.B;", + "import anno.Anno;", + "import static b.B.nosuch.A;", + "@Anno(A.X)", + "public class A extends B {", + " public A a;", + " public static final int X = 1;", + "}")) + .put( + "a/C.java", + lines( + "package c;", // + "import static b.B.nosuch.C;", + "class C {", + " C c;", + "}")) + .build(); + + ImmutableMap<String, String> noImports; + { + ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); + sources.forEach( + (k, v) -> builder.put(k, v.replaceAll("import static b\\.B\\.nosuch\\..*;", ""))); + noImports = builder.build(); + } + + Map<String, byte[]> expected = + IntegrationTestSupport.runJavac(noImports, ImmutableList.of(), BOOTCLASSPATH); + Map<String, byte[]> actual = + IntegrationTestSupport.runTurbine(sources, ImmutableList.of(), BOOTCLASSPATH); + assertThat(IntegrationTestSupport.dump(IntegrationTestSupport.sortMembers(actual))) + .isEqualTo(IntegrationTestSupport.dump(IntegrationTestSupport.canonicalize(expected))); + } + + static String lines(String... lines) { + return Joiner.on("\n").join(lines); + } } |