Skip to content

Commit 057d3ae

Browse files
committed
Make the entire API thread-safe.
On the condition that the `ClasspathEntry`s used to create the `Context` are thread-safe.
1 parent 227c2ef commit 057d3ae

File tree

11 files changed

+214
-126
lines changed

11 files changed

+214
-126
lines changed

tasty-query/js/src/main/scala/tastyquery/nodejs/ClasspathLoaders.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ object ClasspathLoaders:
3131
* to create a [[Contexts.Context]]. The latter gives semantic access to all
3232
* the definitions on the classpath.
3333
*
34+
* The entries of the resulting [[Classpaths.Classpath]] can be considered
35+
* thread-safe, since the JavaScript environment is always single-threaded.
36+
*
3437
* @note the resulting [[Classpaths.ClasspathEntry ClasspathEntry]] entries of
3538
* the returned [[Classpaths.Classpath]] correspond to the elements of `classpath`.
3639
*/

tasty-query/jvm/src/main/scala/tastyquery/jdk/ClasspathLoaders.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ object ClasspathLoaders {
4040
* to create a [[Contexts.Context]]. The latter gives semantic access to all
4141
* the definitions on the classpath.
4242
*
43+
* The entries of the resulting [[Classpaths.Classpath]] are all guaranteed
44+
* to be thread-safe.
45+
*
4346
* @note the resulting [[Classpaths.ClasspathEntry ClasspathEntry]] entries of
4447
* the returned [[Classpaths.Classpath]] correspond to the elements of `classpath`.
4548
*/

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@ import tastyquery.Utils.*
1313

1414
object Annotations:
1515
final class Annotation(val tree: TermTree):
16-
private var mySymbol: Memo[ClassSymbol] = uninitializedMemo
17-
private var mySafeSymbol: Memo[Option[ClassSymbol]] = uninitializedMemo
18-
private var myArguments: Memo[List[TermTree]] = uninitializedMemo
16+
private val mySymbol: Memo[ClassSymbol] = uninitializedMemo
17+
private val mySafeSymbol: Memo[Option[ClassSymbol]] = uninitializedMemo
18+
private val myArguments: Memo[List[TermTree]] = uninitializedMemo
1919

2020
/** The annotation class symbol. */
2121
def symbol(using Context): ClassSymbol =
22-
memoized2(mySymbol, mySymbol = _) {
22+
memoized2(mySymbol) {
2323
computeAnnotSymbol(tree)
2424
} { computed =>
25-
initializeMemo[Option[ClassSymbol]](mySafeSymbol = _, Some(computed))
25+
initializeMemo(mySafeSymbol, Some(computed))
2626
}
2727
end symbol
2828

@@ -31,10 +31,10 @@ object Annotations:
3131
* If the class of this annotation cannot be successfully resolved, returns `false`.
3232
*/
3333
private[tastyquery] def safeHasSymbol(cls: ClassSymbol)(using Context): Boolean =
34-
val safeSymbol = memoized2(mySafeSymbol, mySafeSymbol = _) {
34+
val safeSymbol = memoized2(mySafeSymbol) {
3535
computeSafeAnnotSymbol(tree)
3636
} { computed =>
37-
computed.foreach(sym => initializeMemo[ClassSymbol](mySymbol = _, sym))
37+
computed.foreach(sym => initializeMemo(mySymbol, sym))
3838
}
3939

4040
safeSymbol.contains(cls)
@@ -56,7 +56,7 @@ object Annotations:
5656
* `NamedArg`s are not visible with this method. They are replaced by
5757
* their right-hand-side.
5858
*/
59-
def arguments: List[TermTree] = memoized(myArguments, myArguments = _) {
59+
def arguments: List[TermTree] = memoized(myArguments) {
6060
computeAnnotArguments(tree)
6161
}
6262

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ object Classpaths:
2323
* All the methods of `ClasspathEntry` and its components may throw
2424
* `java.io.IOException`s to indicate I/O errors.
2525
*
26+
* A `ClasspathEntry` is encouraged to be thread-safe, along with all its
27+
* components, but it is not a strong requirement. Implementations that are
28+
* thread-safe should be documented as such. [[Contexts.Context]]s created
29+
* only from thread-safe `ClasspathEntry`s are thread-safe themselves.
30+
*
2631
* Implementations of this class are encouraged to define a `toString()`
2732
* method that helps identifying the entry for debugging purposes.
2833
*/
@@ -99,16 +104,21 @@ object Classpaths:
99104
def readClassFileBytes(): IArray[Byte]
100105
end ClassData
101106

102-
/** In-memory representation of classpath entries. */
107+
/** In-memory representation of classpath entries.
108+
*
109+
* In-memory classpath entries are thread-safe.
110+
*/
103111
object InMemory:
104112
import Classpaths as generic
105113

114+
/** A thread-safe, immutable classpath entry. */
106115
final class ClasspathEntry(debugString: String, val packages: List[PackageData]) extends generic.ClasspathEntry:
107116
override def toString(): String = debugString
108117

109118
def listAllPackages(): List[generic.PackageData] = packages
110119
end ClasspathEntry
111120

121+
/** A thread-safe, immutable package information within a classpath entry. */
112122
final class PackageData(debugString: String, val dotSeparatedName: String, val classes: List[ClassData])
113123
extends generic.PackageData:
114124
private lazy val byBinaryName = classes.map(c => c.binaryName -> c).toMap
@@ -120,6 +130,7 @@ object Classpaths:
120130
def getClassDataByBinaryName(binaryName: String): Option[generic.ClassData] = byBinaryName.get(binaryName)
121131
end PackageData
122132

133+
/** A thread-safe, immutable class information within a classpath entry. */
123134
final class ClassData(
124135
debugString: String,
125136
val binaryName: String,

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ object Contexts {
2727

2828
/** Factory methods for [[Context]]. */
2929
object Context:
30-
/** Creates a new [[Context]] for the given [[Classpaths.Classpath]]. */
30+
/** Creates a new [[Context]] for the given [[Classpaths.Classpath]].
31+
*
32+
* If all the [[Classpaths.ClasspathEntry ClasspathEntries]] in the classpath
33+
* are thread-safe, then the resulting [[Context]] is thread-safe.
34+
*/
3135
def initialize(classpath: Classpath): Context =
3236
val classloader = Loader(classpath)
3337
val ctx = new Context(classloader)

0 commit comments

Comments
 (0)