diff options
author | Martin Odersky <odersky@gmail.com> | 2014-02-11 22:00:24 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-02-11 23:21:45 +0100 |
commit | 98daf15f17a119d76c7b9289c82a7730ac8ece58 (patch) | |
tree | 71b06e97aaa4955ed1491626b5712e3eef01fb77 /src/dotty/tools/dotc/util/Attachment.scala | |
parent | ce55c3b08da29acafaa3c43796ead9cf854f1d34 (diff) | |
download | dotty-98daf15f17a119d76c7b9289c82a7730ac8ece58.tar.gz dotty-98daf15f17a119d76c7b9289c82a7730ac8ece58.tar.bz2 dotty-98daf15f17a119d76c7b9289c82a7730ac8ece58.zip |
Wrapped up definition of attachments.
Diffstat (limited to 'src/dotty/tools/dotc/util/Attachment.scala')
-rw-r--r-- | src/dotty/tools/dotc/util/Attachment.scala | 101 |
1 files changed, 62 insertions, 39 deletions
diff --git a/src/dotty/tools/dotc/util/Attachment.scala b/src/dotty/tools/dotc/util/Attachment.scala index 7cc94754d..061438bb4 100644 --- a/src/dotty/tools/dotc/util/Attachment.scala +++ b/src/dotty/tools/dotc/util/Attachment.scala @@ -5,71 +5,94 @@ package dotty.tools.dotc.util */ object Attachment { + /** The class of keys for attachments yielding values of type V */ class Key[+V] - val NullKey = new Key[Null] - - abstract class AttachmentLink[+V] extends DotClass { - private[Attachment] def key: Key[V] - private[Attachment] def value: V + /** An implementation trait for attachements. + * Clients should inherit from Container instead. + */ + trait LinkSource { private[Attachment] var next: Link[_] - def getAttachment[V](key: Key[V]): Option[V] = - if (this.key eq key) Some(value.asInstanceOf[V]) - else if (next == null) None - else next.getAttachment(key) - - def attachment[V](key: Key[V]): V = - if (this.key eq key) value.asInstanceOf[V] - else if (next == null) throw new NoSuchElementException - else next.attachment(key) + /** Optionally get attachment corresponding to `key` */ + final def getAttachment[V](key: Key[V]): Option[V] = { + val nx = next + if (nx == null) None + else if (nx.key eq key) Some(nx.value.asInstanceOf[V]) + else nx.getAttachment[V](key) + } - def attachmentOrElse[V](key: Key[V], default: V): V = - if (this.key eq key) value.asInstanceOf[V] - else if (next == null) default - else next.attachmentOrElse(key, default) + /** The attachment corresponding to `key`. + * @throws NoSuchElementException if no attachment with key exists + */ + final def attachment[V](key: Key[V]): V = { + val nx = next + if (nx == null) throw new NoSuchElementException + else if (nx.key eq key) nx.value.asInstanceOf[V] + else nx.attachment(key) + } - def pushAttachment[V](key: Key[V], value: V): Unit = { - assert(!getAttachment(key).isDefined) - next = new Link(key, value, next) + /** The attachment corresponding to `key`, or `default` + * if no attachment with `key` exists. + */ + final def attachmentOrElse[V](key: Key[V], default: V): V = { + val nx = next + if (nx == null) default + else if (nx.key eq key) nx.value.asInstanceOf[V] + else nx.attachmentOrElse(key, default) } - def putAttachment[V](key: Key[V], value: V): Option[V] = { - if (next == null) { + /** Add attachment with given `key` and `value`. + * @return Optionally, the old attachment with given `key` if one existed before. + * The new attachment is added at the position of the old one, or at the end + * if no attachment with same `key` existed. + */ + final def putAttachment[V](key: Key[V], value: V): Option[V] = { + val nx = next + if (nx == null) { next = new Link(key, value, null) None } - else if (next.key eq key) { - val nx = next + else if (nx.key eq key) { next = new Link(key, value, nx.next) Some(nx.value.asInstanceOf[V]) } - else next.putAttachment(key, value) + else nx.putAttachment(key, value) } - def removeAttachment[V](key: Key[V]): Option[V] = { - if (next == null) + /** Remove attachment with given `key`, if it exists. + * @return Optionally, the removed attachment with given `key` if one existed before. + */ + final def removeAttachment[V](key: Key[V]): Option[V] = { + val nx = next + if (nx == null) None - else if (next.key eq key) { - val nx = next + else if (nx.key eq key) { next = nx.next Some(nx.value.asInstanceOf[V]) } - else next.removeAttachment(key) + else nx.removeAttachment(key) } - def allAttachments: List[Any] = - if (next == null) Nil else next.allAttachments + /** The list of all values attached to this container. */ + final def allAttachments: List[Any] = { + val nx = next + if (nx == null) Nil else nx.value :: nx.allAttachments + } } + /** A private, concrete implementation class linking attachments. + */ private[Attachment] class Link[+V](val key: Key[V], val value: V, var next: Link[_]) - extends AttachmentLink[V] { - override def allAttachments: List[Any] = value :: super.allAttachments - } + extends LinkSource - class Container extends AttachmentLink[Null] { - private[Attachment] def key = NullKey - private[Attachment] def value: Null = unsupported("value") + /** A trait for objects that can contain attachments */ + trait Container extends LinkSource { private[Attachment] var next: Link[_] = null + + final def pushAttachment[V](key: Key[V], value: V): Unit = { + assert(!getAttachment(key).isDefined) + next = new Link(key, value, next) + } } }
\ No newline at end of file |