1
- /*
2
- * Copyright 2001-2016 Artima, Inc.
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- */
16
1
package org .scalactic .source
17
2
18
- import org .scalactic .Resources
19
3
4
+ // import scala.reflect.macros.blackbox.Context
20
5
import scala .reflect .macros .Context
6
+ import org .scalactic .Resources
21
7
22
8
/**
23
9
* Helper class for Position macro. (Will be removed from the public API if possible in a subsequent 3.0.0-RCx release.)
24
10
*/
25
- object PositionMacro {
11
+ object PositionMacro {
12
+ private object sourceCompatHack {
13
+ object internal { object decorators {} }
14
+ }
15
+ import sourceCompatHack ._
16
+
17
+ private class PositionMacroImpl (val universe : scala.reflect.api.Universe ) {
18
+
19
+ private val PositionModule = universe.rootMirror.staticModule(" org.scalactic.source.Position" )
20
+ private val PositionClass = universe.rootMirror.staticClass(" org.scalactic.source.Position" )
21
+ private val Position_apply = PositionModule .typeSignature.declaration(universe.newTermName(" apply" ))
22
+
23
+ private [scalactic] lazy val showScalacticFillFilePathnames : Boolean = {
24
+ val value = System .getenv(" SCALACTIC_FILL_FILE_PATHNAMES" )
25
+ value != null && value == " yes"
26
+ }
27
+
28
+ def apply (context : Context ): context.Tree = {
29
+ import context .universe ._
30
+
31
+ // On 2.10, this imports the empty object defined above
32
+ // On 2.11+, this imports `Tree.setType` extension method
33
+ import internal .decorators ._
26
34
27
- private [scalactic] lazy val showScalacticFillFilePathnames : Boolean = {
28
- val value = System .getenv(" SCALACTIC_FILL_FILE_PATHNAMES" )
29
- value != null && value == " yes"
35
+ // Our types don't capture the fact that context.universe eq this.universe, so we have to cast.
36
+ implicit def castSymbol (s : universe.Symbol ): context.universe.Symbol = s.asInstanceOf [context.universe.Symbol ]
37
+ implicit def castType (t : universe.Type ): context.universe.Type = t.asInstanceOf [context.universe.Type ]
38
+
39
+ import treeBuild .{mkAttributedIdent , mkAttributedSelect }
40
+
41
+ // Because this macro is called so frequently, we use assign types to the trees as we build them, rather
42
+ // than returning an untyped tree and letting the typechecker fill in the types.
43
+ // (`setType` and `mkAttributedXxx` assign Tree.tpe.)
44
+ def strLit (s : String ) = {
45
+ Literal (Constant (s)).setType(definitions.StringClass .toTypeConstructor)
46
+ }
47
+ def intLit (i : Int ) = {
48
+ Literal (Constant (i)).setType(definitions.IntTpe )
49
+ }
50
+ val args = List (
51
+ strLit(context.enclosingPosition.source.file.name),
52
+ if (showScalacticFillFilePathnames) strLit(context.enclosingPosition.source.path) else strLit(Resources .pleaseDefineScalacticFillFilePathnameEnvVar),
53
+ // strLit(""),
54
+ intLit(context.enclosingPosition.line)
55
+ )
56
+
57
+ Apply (mkAttributedSelect(mkAttributedIdent(PositionModule ), Position_apply ), args).setType(PositionClass .toTypeConstructor)
58
+ }
30
59
}
31
60
61
+ // Cache to avoid needing to lookup of PositionModule/PositionClass/Position_apply each macro expansion.
62
+ private var cache = new java.lang.ref.WeakReference [PositionMacroImpl ](null )
63
+
32
64
/**
33
65
* Helper method for Position macro.
34
66
*/
35
- def genPosition (context : Context ) = {
36
- import context .universe ._
37
-
38
- context.Expr (
39
- Apply (
40
- Select (
41
- Select (
42
- Select (
43
- Select (
44
- Select (
45
- Ident (newTermName(" _root_" )),
46
- newTermName(" org" )
47
- ),
48
- newTermName(" scalactic" )
49
- ),
50
- newTermName(" source" )
51
- ),
52
- newTermName(" Position" )
53
- ),
54
- newTermName(" apply" )
55
- ),
56
- List (
57
- Literal (Constant (context.enclosingPosition.source.file.name)),
58
- Literal (if (showScalacticFillFilePathnames) Constant (context.enclosingPosition.source.path) else Constant (Resources .pleaseDefineScalacticFillFilePathnameEnvVar)),
59
- Literal (Constant (context.enclosingPosition.line))
60
- )
61
- )
62
- )
67
+ def genPosition (context : Context ): context.Expr [Position ] = {
68
+ var impl = cache.get()
69
+ if (impl == null || impl.universe != context.universe) {
70
+ impl = new PositionMacroImpl (context.universe)
71
+ cache = new java.lang.ref.WeakReference [PositionMacroImpl ](impl)
72
+ }
73
+ context.Expr [Position ](impl.apply(context))
63
74
}
64
-
65
- }
75
+ }
0 commit comments