Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 267 lines (223 sloc) 10.711 kb
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
1 /* NSC -- new Scala compiler
2 * Copyright 2007-2011 LAMP/EPFL
3 * @author Martin Odersky
4 */
5
6 package scala.reflect
1a9b0c9 Paul Phillips Renamed scala.reflect.common to scala.reflect.i...
paulp authored
7 package internal
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
8
9 import util._
dbeab9b odersky Changes to reflection.
odersky authored
10 import pickling.ByteCodecs
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
11
12 /** AnnotationInfo and its helpers */
9e1d24d odersky Refactored reflection into reflect.api and refl...
odersky authored
13 trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable =>
25ecde0 Paul Phillips Reworked AnnotationInfo patch.
paulp authored
14 import definitions.{ ThrowsClass, StaticAnnotationClass, isMetaAnnotation }
e86f07f Paul Phillips Long-standing performance mystery solved.
paulp authored
15
4e86106 Paul Phillips Moved meta annotations to annotation.meta, plus.
paulp authored
16 // Common annotation code between Symbol and Type.
17 // For methods altering the annotation list, on Symbol it mutates
18 // the Symbol's field directly. For Type, a new AnnotatedType is
19 // created which wraps the original type.
20 trait Annotatable[Self] {
21 self: Self =>
22
23 /** The annotations on this type. */
24 def annotations: List[AnnotationInfo] // Annotations on this type.
25 def setAnnotations(annots: List[AnnotationInfo]): Self // Replace annotations with argument list.
26 def withAnnotations(annots: List[AnnotationInfo]): Self // Add annotations to this type.
4cfca8a Paul Phillips AnnotationInfo inertia takes me into continuati...
paulp authored
27 def filterAnnotations(p: AnnotationInfo => Boolean): Self // Retain only annotations meeting the condition.
4e86106 Paul Phillips Moved meta annotations to annotation.meta, plus.
paulp authored
28 def withoutAnnotations: Self // Remove all annotations from this type.
29
30 /** Symbols of any @throws annotations on this symbol.
31 */
ca47241 Paul Phillips Batting back a java.rmi.* dependency.
paulp authored
32 def throwsAnnotations(): List[Symbol] = annotations collect {
4e86106 Paul Phillips Moved meta annotations to annotation.meta, plus.
paulp authored
33 case AnnotationInfo(tp, Literal(Constant(tpe: Type)) :: Nil, _) if tp.typeSymbol == ThrowsClass => tpe.typeSymbol
34 }
35
36 /** Test for, get, or remove an annotation */
37 def hasAnnotation(cls: Symbol) = annotations exists (_ matches cls)
38 def getAnnotation(cls: Symbol) = annotations find (_ matches cls)
4cfca8a Paul Phillips AnnotationInfo inertia takes me into continuati...
paulp authored
39 def removeAnnotation(cls: Symbol): Self = filterAnnotations(ann => !(ann matches cls))
40 final def withAnnotation(annot: AnnotationInfo): Self = withAnnotations(List(annot))
4e86106 Paul Phillips Moved meta annotations to annotation.meta, plus.
paulp authored
41 }
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
42
43 /** Arguments to classfile annotations (which are written to
44 * bytecode as java annotations) are either:
2621ee6 scaladoc fixes and improvements
michelou authored
45 *
46 * - constants
47 * - arrays of constants
48 * - or nested classfile annotations
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
49 */
afc7559 Paul Phillips Annotations reacquainted with reification.
paulp authored
50 abstract class ClassfileAnnotArg extends Product
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
51
2621ee6 scaladoc fixes and improvements
michelou authored
52 /** Represents a compile-time Constant (`Boolean`, `Byte`, `Short`,
53 * `Char`, `Int`, `Long`, `Float`, `Double`, `String`, `java.lang.Class` or
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
54 * an instance of a Java enumeration value).
55 */
56 case class LiteralAnnotArg(const: Constant)
57 extends ClassfileAnnotArg {
58 override def toString = const.escapedStringValue
59 }
60
9e1d24d odersky Refactored reflection into reflect.api and refl...
odersky authored
61 object LiteralAnnotArg extends LiteralAnnotArgExtractor
62
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
63 /** Represents an array of classfile annotation arguments */
64 case class ArrayAnnotArg(args: Array[ClassfileAnnotArg])
65 extends ClassfileAnnotArg {
66 override def toString = args.mkString("[", ", ", "]")
67 }
68
9e1d24d odersky Refactored reflection into reflect.api and refl...
odersky authored
69 object ArrayAnnotArg extends ArrayAnnotArgExtractor
70
2621ee6 scaladoc fixes and improvements
michelou authored
71 /** A specific annotation argument that encodes an array of bytes as an
72 * array of `Long`. The type of the argument declared in the annotation
73 * must be `String`. This specialised class is used to encode Scala
74 * signatures for reasons of efficiency, both in term of class-file size
75 * and in term of compiler performance.
76 */
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
77 case class ScalaSigBytes(bytes: Array[Byte]) extends ClassfileAnnotArg {
78 override def toString = (bytes map { byte => (byte & 0xff).toHexString }).mkString("[ ", " ", " ]")
49ebb3e odersky ByteCodecs move to reflect.internal.
odersky authored
79 lazy val encodedBytes = ByteCodecs.encode(bytes)
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
80 def isLong: Boolean = (encodedBytes.length > 65535)
81 def sigAnnot: Type =
82 if (this.isLong)
83 definitions.ScalaLongSignatureAnnotation.tpe
84 else
85 definitions.ScalaSignatureAnnotation.tpe
86 }
87
88 /** Represents a nested classfile annotation */
25ecde0 Paul Phillips Reworked AnnotationInfo patch.
paulp authored
89 case class NestedAnnotArg(annInfo: AnnotationInfo) extends ClassfileAnnotArg {
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
90 // The nested annotation should not have any Scala annotation arguments
91 assert(annInfo.args.isEmpty, annInfo.args)
92 override def toString = annInfo.toString
93 }
94
9e1d24d odersky Refactored reflection into reflect.api and refl...
odersky authored
95 object NestedAnnotArg extends NestedAnnotArgExtractor
96
25ecde0 Paul Phillips Reworked AnnotationInfo patch.
paulp authored
97 object AnnotationInfo extends AnnotationInfoExtractor {
4cfca8a Paul Phillips AnnotationInfo inertia takes me into continuati...
paulp authored
98 def marker(atp: Type): AnnotationInfo =
99 apply(atp, Nil, Nil)
100
25ecde0 Paul Phillips Reworked AnnotationInfo patch.
paulp authored
101 def lazily(lazyInfo: => AnnotationInfo) =
102 new LazyAnnotationInfo(lazyInfo)
103
104 def apply(atp: Type, args: List[Tree], assocs: List[(Name, ClassfileAnnotArg)]): AnnotationInfo =
105 new CompleteAnnotationInfo(atp, args, assocs)
106
107 def unapply(info: AnnotationInfo): Option[(Type, List[Tree], List[(Name, ClassfileAnnotArg)])] =
108 Some((info.atp, info.args, info.assocs))
109 }
110
111 class CompleteAnnotationInfo(
112 val atp: Type,
113 val args: List[Tree],
114 val assocs: List[(Name, ClassfileAnnotArg)]
115 ) extends AnnotationInfo {
116 // Classfile annot: args empty. Scala annot: assocs empty.
117 assert(args.isEmpty || assocs.isEmpty, atp)
118
814cf34 Eugene Burmako Next generation of macros
xeno-by authored
119 // necessary for reification, see Reifiers.scala for more info
6548dcf Eugene Burmako reifyAnnotations
xeno-by authored
120 private var orig: Tree = EmptyTree
121 def original = orig
122 def setOriginal(t: Tree): this.type = { orig = t; this }
123
25ecde0 Paul Phillips Reworked AnnotationInfo patch.
paulp authored
124 override def toString = (
125 atp +
126 (if (!args.isEmpty) args.mkString("(", ", ", ")") else "") +
127 (if (!assocs.isEmpty) (assocs map { case (x, y) => x+" = "+y } mkString ("(", ", ", ")")) else "")
128 )
129 }
130
131 /** Symbol annotations parsed in `Namer` (typeCompleter of
132 * definitions) have to be lazy (#1782)
133 */
134 final class LazyAnnotationInfo(lazyInfo: => AnnotationInfo) extends AnnotationInfo {
135 private var forced = false
eb5e621 odersky Fix to position in AnnotationInfo
odersky authored
136 private lazy val forcedInfo =
137 try {
6548dcf Eugene Burmako reifyAnnotations
xeno-by authored
138 val result = lazyInfo
eb5e621 odersky Fix to position in AnnotationInfo
odersky authored
139 if (result.pos == NoPosition) result setPos pos
140 result
141 } finally forced = true
25ecde0 Paul Phillips Reworked AnnotationInfo patch.
paulp authored
142
143 def atp: Type = forcedInfo.atp
144 def args: List[Tree] = forcedInfo.args
145 def assocs: List[(Name, ClassfileAnnotArg)] = forcedInfo.assocs
6548dcf Eugene Burmako reifyAnnotations
xeno-by authored
146 def original: Tree = forcedInfo.original
147 def setOriginal(t: Tree): this.type = { forcedInfo.setOriginal(t); this }
25ecde0 Paul Phillips Reworked AnnotationInfo patch.
paulp authored
148
149 // We should always be able to print things without forcing them.
150 override def toString = if (forced) forcedInfo.toString else "@<?>"
6548dcf Eugene Burmako reifyAnnotations
xeno-by authored
151
dd16261 odersky Fix to the fix of AnnotationInfos.
odersky authored
152 override def pos: Position = if (forced) forcedInfo.pos else NoPosition
25ecde0 Paul Phillips Reworked AnnotationInfo patch.
paulp authored
153 }
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
154
2621ee6 scaladoc fixes and improvements
michelou authored
155 /** Typed information about an annotation. It can be attached to either
156 * a symbol or an annotated type.
157 *
158 * Annotations are written to the classfile as Java annotations
159 * if `atp` conforms to `ClassfileAnnotation` (the classfile parser adds
160 * this interface to any Java annotation class).
161 *
162 * Annotations are pickled (written to scala symtab attribute in the
163 * classfile) if `atp` inherits form `StaticAnnotation`.
164 *
165 * `args` stores arguments to Scala annotations, represented as typed
166 * trees. Note that these trees are not transformed by any phases
167 * following the type-checker.
168 *
169 * `assocs` stores arguments to classfile annotations as name-value pairs.
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
170 */
814cf34 Eugene Burmako Next generation of macros
xeno-by authored
171 sealed abstract class AnnotationInfo {
25ecde0 Paul Phillips Reworked AnnotationInfo patch.
paulp authored
172 def atp: Type
173 def args: List[Tree]
174 def assocs: List[(Name, ClassfileAnnotArg)]
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
175
814cf34 Eugene Burmako Next generation of macros
xeno-by authored
176 // necessary for reification, see Reifiers.scala for more info
6548dcf Eugene Burmako reifyAnnotations
xeno-by authored
177 def original: Tree
178 def setOriginal(t: Tree): this.type
179
25ecde0 Paul Phillips Reworked AnnotationInfo patch.
paulp authored
180 // see annotationArgRewriter
181 lazy val isTrivial = atp.isTrivial && !hasArgWhich(_.isInstanceOf[This])
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
182
183 private var rawpos: Position = NoPosition
184 def pos = rawpos
0c0ba99 odersky More work on making reflection thread-safe.
odersky authored
185 def setPos(pos: Position): this.type = { // Syncnote: Setpos inaccessible to reflection, so no sync in rawpos necessary.
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
186 rawpos = pos
187 this
188 }
189
4e86106 Paul Phillips Moved meta annotations to annotation.meta, plus.
paulp authored
190 /** Annotations annotating annotations are confusing so I drew
191 * an example. Given the following code:
192 *
193 * class A {
194 * @(deprecated @setter) @(inline @getter)
195 * var x: Int = 0
196 * }
197 *
198 * For the setter `x_=` in A, annotations contains one AnnotationInfo =
199 * List(deprecated @setter)
200 * The single AnnotationInfo in that list, i.e. `@(deprecated @setter)`, has metaAnnotations =
201 * List(setter)
202 *
203 * Similarly, the getter `x` in A has an @inline annotation, which has
204 * metaAnnotations = List(getter).
205 */
206 def symbol = atp.typeSymbol
207
208 /** These are meta-annotations attached at the use site; they
209 * only apply to this annotation usage. For instance, in
210 * `@(deprecated @setter @field) val ...`
211 * metaAnnotations = List(setter, field).
212 */
213 def metaAnnotations: List[AnnotationInfo] = atp match {
214 case AnnotatedType(metas, _, _) => metas
215 case _ => Nil
216 }
217
218 /** The default kind of members to which this annotation is attached.
219 * For instance, for scala.deprecated defaultTargets =
220 * List(getter, setter, beanGetter, beanSetter).
221 */
222 def defaultTargets = symbol.annotations map (_.symbol) filter isMetaAnnotation
223 // Test whether the typeSymbol of atp conforms to the given class.
224 def matches(clazz: Symbol) = symbol isNonBottomSubClass clazz
225 // All subtrees of all args are considered.
226 def hasArgWhich(p: Tree => Boolean) = args exists (_ exists p)
227
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
228 /** Check whether the type or any of the arguments are erroneous */
229 def isErroneous = atp.isErroneous || args.exists(_.isErroneous)
230
25ecde0 Paul Phillips Reworked AnnotationInfo patch.
paulp authored
231 def isStatic = symbol isNonBottomSubClass StaticAnnotationClass
232
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
233 /** Check whether any of the arguments mention a symbol */
4e86106 Paul Phillips Moved meta annotations to annotation.meta, plus.
paulp authored
234 def refsSymbol(sym: Symbol) = hasArgWhich(_.symbol == sym)
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
235
236 /** Change all ident's with Symbol "from" to instead use symbol "to" */
bf6ce00 Paul Phillips Symbol creation followup.
paulp authored
237 def substIdentSyms(from: Symbol, to: Symbol) =
238 AnnotationInfo(atp, args map (_ substTreeSyms (from -> to)), assocs) setPos pos
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
239
990fa04 Paul Phillips Fixed bug in the disambiguation of f(foo='bar')...
paulp authored
240 def stringArg(index: Int) = constantAtIndex(index) map (_.stringValue)
241 def intArg(index: Int) = constantAtIndex(index) map (_.intValue)
242 def symbolArg(index: Int) = argAtIndex(index) collect {
243 case Apply(fun, Literal(str) :: Nil) if fun.symbol == definitions.Symbol_apply =>
244 newTermName(str.stringValue)
245 }
246
247 // !!! when annotation arguments are not literals, but any sort of
248 // expression, there is a fair chance they will turn up here not as
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
249 // Literal(const) but some arbitrary AST.
990fa04 Paul Phillips Fixed bug in the disambiguation of f(foo='bar')...
paulp authored
250 def constantAtIndex(index: Int): Option[Constant] =
251 argAtIndex(index) collect { case Literal(x) => x }
252
253 def argAtIndex(index: Int): Option[Tree] =
254 if (index < args.size) Some(args(index)) else None
4cfca8a Paul Phillips AnnotationInfo inertia takes me into continuati...
paulp authored
255
256 override def hashCode = atp.## + args.## + assocs.##
257 override def equals(other: Any) = other match {
258 case x: AnnotationInfo => (atp == x.atp) && (args == x.args) && (assocs == x.assocs)
259 case _ => false
260 }
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
261 }
262
0f0144c Eugene Burmako migrates stdlib and compiler to tags
xeno-by authored
263 lazy val classfileAnnotArgTag: ArrayTag[ClassfileAnnotArg] = arrayTag[ClassfileAnnotArg]
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
264
25ecde0 Paul Phillips Reworked AnnotationInfo patch.
paulp authored
265 object UnmappableAnnotation extends CompleteAnnotationInfo(NoType, Nil, Nil)
fff93cd Paul Phillips And the remainder of the scala.reflect refactor...
paulp authored
266 }
Something went wrong with that request. Please try again.