Skip to content

Commit

Permalink
Merge pull request #15094 from griggt/fix-13523
Browse files Browse the repository at this point in the history
Fix #13523: Survive missing Java inner annotation classfiles
  • Loading branch information
griggt authored May 3, 2022
2 parents 1f4daea + ccc33ea commit aff1e11
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -1127,7 +1127,16 @@ class ClassfileParser(
val outerName = entry.strippedOuter
val innerName = entry.originalName
val owner = classNameToSymbol(outerName)
val result = atPhase(typerPhase)(getMember(owner, innerName.toTypeName))
val result = owner.denot.infoOrCompleter match
case _: StubInfo if hasAnnotation(entry.jflags) =>
requiredClass(innerName.toTypeName)
// It's okay for the classfiles of Java annotations to be missing
// from the classpath. If an annotation is defined as an inner class
// we need to avoid forcing the outer class symbol here, and instead
// return a new stub symbol for the inner class. This is tested by
// `surviveMissingInnerClassAnnot` in AnnotationsTests.scala
case _ =>
atPhase(typerPhase)(getMember(owner, innerName.toTypeName))
assert(result ne NoSymbol,
i"""failure to resolve inner class:
|externalName = ${entry.externalName},
Expand Down
23 changes: 23 additions & 0 deletions compiler/test/dotty/tools/AnnotationsTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,26 @@ class AnnotationsTest:
s"A missing annotation while parsing a Java class should be silently ignored but: ${ctx.reporter.summary}")
}
}

@Test def surviveMissingInnerClassAnnot: Unit =
withJavaCompiled(
VirtualJavaSource("Outer.java",
"""|package a.b;
|public @interface Outer { public @interface Value { @interface Immutable {} } }
|""".stripMargin),
VirtualJavaSource("Baz.java",
"""|package a.b;
|@Outer.Value.Immutable abstract class Baz {}""".stripMargin)
) { javaOutputDir =>
Files.delete(javaOutputDir.resolve("a/b/Outer.class"))
Files.delete(javaOutputDir.resolve("a/b/Outer$Value.class"))
Files.delete(javaOutputDir.resolve("a/b/Outer$Value$Immutable.class"))
inCompilerContext(javaOutputDir.toString + File.pathSeparator + TestConfiguration.basicClasspath) {
val cls = requiredClass("a.b.Baz")
val annots = cls.annotations.map(_.tree)
assert(annots == Nil,
s"class Baz should have no visible annotations since Outer.Value.Immutable is not on the classpath, but found: $annots")
assert(!ctx.reporter.hasErrors && !ctx.reporter.hasWarnings,
s"A missing annotation while parsing a Java class should be silently ignored but: ${ctx.reporter.summary}")
}
}

0 comments on commit aff1e11

Please sign in to comment.