Skip to content

Commit b5c32dd

Browse files
authored
Merge pull request #410 from sjrd/missing-annotations
Fix #402: Recover from annotations that are missing on the classpath.
2 parents e3f97f7 + e17c561 commit b5c32dd

File tree

3 files changed

+45
-3
lines changed

3 files changed

+45
-3
lines changed

tasty-query/shared/src/main/scala/tastyquery/Annotations.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import tastyquery.Types.*
1313
object Annotations:
1414
final class Annotation(val tree: TermTree):
1515
private var mySymbol: ClassSymbol | Null = null
16+
private var mySafeSymbol: Option[ClassSymbol] | Null = null
1617
private var myArguments: List[TermTree] | Null = null
1718

1819
/** The annotation class symbol. */
@@ -22,9 +23,27 @@ object Annotations:
2223
else
2324
val computed = computeAnnotSymbol(tree)
2425
mySymbol = computed
26+
mySafeSymbol = Some(computed)
2527
computed
2628
end symbol
2729

30+
/** Tests whether the annotation has the given class symbol.
31+
*
32+
* If the class of this annotation cannot be successfully resolved, returns `false`.
33+
*/
34+
private[tastyquery] def safeHasSymbol(cls: ClassSymbol)(using Context): Boolean =
35+
val safeSymbol =
36+
val local = mySafeSymbol
37+
if local != null then local
38+
else
39+
val local = computeSafeAnnotSymbol(tree)
40+
local.foreach(mySymbol = _)
41+
mySafeSymbol = local
42+
local
43+
44+
safeSymbol.contains(cls)
45+
end safeHasSymbol
46+
2847
/** The symbol of the constructor used in the annotation.
2948
*
3049
* This operation is not supported for annotations read from Java or Scala 2.
@@ -138,6 +157,14 @@ object Annotations:
138157
}
139158
end computeAnnotSymbol
140159

160+
private def computeSafeAnnotSymbol(tree: TermTree)(using Context): Option[ClassSymbol] =
161+
// This is not a very efficient way to deal with this, but I don't really see a good solution
162+
try Some(computeAnnotSymbol(tree))
163+
catch
164+
case _: MemberNotFoundException =>
165+
None
166+
end computeSafeAnnotSymbol
167+
141168
private def findNewAnnotTypeTree(tree: TermTree): TypeTree =
142169
def invalid(): Nothing =
143170
throw InvalidProgramStructureException(s"Cannot find annotation class in $tree")

tasty-query/shared/src/main/scala/tastyquery/Symbols.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,13 +199,13 @@ object Symbols {
199199
final def asPackage: PackageSymbol = this.asInstanceOf[PackageSymbol]
200200

201201
final def hasAnnotation(annotClass: ClassSymbol)(using Context): Boolean =
202-
annotations.exists(_.symbol == annotClass)
202+
annotations.exists(_.safeHasSymbol(annotClass))
203203

204204
final def getAnnotations(annotClass: ClassSymbol)(using Context): List[Annotation] =
205-
annotations.filter(_.symbol == annotClass)
205+
annotations.filter(_.safeHasSymbol(annotClass))
206206

207207
final def getAnnotation(annotClass: ClassSymbol)(using Context): Option[Annotation] =
208-
annotations.find(_.symbol == annotClass)
208+
annotations.find(_.safeHasSymbol(annotClass))
209209

210210
override def toString: String = {
211211
val ownerPrefix = owner match
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package simple_trees
2+
3+
import javax.annotation.processing.SupportedAnnotationTypes
4+
5+
class MissingAnnotations:
6+
@SupportedAnnotationTypes(Array("foo.bar"))
7+
def foo(): String = "hello"
8+
end MissingAnnotations
9+
10+
object MissingAnnotationsTest:
11+
def test(): Unit =
12+
// This used to fail to resolve under JDK 11+, because the annotation is not available in java.base
13+
new MissingAnnotations().foo()
14+
end test
15+
end MissingAnnotationsTest

0 commit comments

Comments
 (0)