diff options
Diffstat (limited to 'src/library/scala/reflect/base/Attachments.scala')
-rw-r--r-- | src/library/scala/reflect/base/Attachments.scala | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/src/library/scala/reflect/base/Attachments.scala b/src/library/scala/reflect/base/Attachments.scala index 889ac0ac14..479ab9a857 100644 --- a/src/library/scala/reflect/base/Attachments.scala +++ b/src/library/scala/reflect/base/Attachments.scala @@ -1,35 +1,42 @@ package scala.reflect package base -/** Attachments is a generalisation of Position. - * Typically it stores a Position of a tree, but this can be extended to encompass arbitrary payloads. +/** Attachments is a generalization of Position. Typically it stores a Position of a tree, but this can be extended to + * encompass arbitrary payloads. Payloads are stored in type-indexed slots, which can be read with `get[T]` and written + * with `update[T]` and `remove[T]`. * - * Attachments have to carry positions, because we don't want to introduce even a single additional field in Tree + * Attachments always carry positions because we don't want to introduce an additional field for attachments in `Tree` * imposing an unnecessary memory tax because of something that will not be used in most cases. */ abstract class Attachments { self => + /** The position type of this attachment */ type Pos >: Null - /** Gets the underlying position */ + /** The underlying position */ def pos: Pos - /** Creates a copy of this attachment with its position updated */ + /** Creates a copy of this attachment with the position replaced by `newPos` */ def withPos(newPos: Pos): Attachments { type Pos = self.Pos } - /** Gets the underlying payload */ + /** The underlying payload with the guarantee that no two elements have the same type. */ def all: Set[Any] = Set.empty private def matchesTag[T: ClassTag](datum: Any) = classTag[T].runtimeClass == datum.getClass + /** An underlying payload of the given class type `T`. */ def get[T: ClassTag]: Option[T] = (all filter matchesTag[T]).headOption.asInstanceOf[Option[T]] - /** Creates a copy of this attachment with its payload updated */ + /** Creates a copy of this attachment with the payload slot of T added/updated with the provided value. + * + * Replaces an existing payload of the same type, if exists. + */ def update[T: ClassTag](attachment: T): Attachments { type Pos = self.Pos } = new NonemptyAttachments(this.pos, remove[T].all + attachment) + /** Creates a copy of this attachment with the payload of the given class type `T` removed. */ def remove[T: ClassTag]: Attachments { type Pos = self.Pos } = { val newAll = all filterNot matchesTag[T] if (newAll.isEmpty) pos.asInstanceOf[Attachments { type Pos = self.Pos }] |