Skip to content

Commit b819fd9

Browse files
committed
Trying PositionMacro implementation by Jason Zaugg.
1 parent 91400bf commit b819fd9

File tree

5 files changed

+68
-57
lines changed

5 files changed

+68
-57
lines changed

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,10 @@ Before publishing any patch release, binary compatibility with previous version
145145
$ sbt ++2.10.7 scalacticJS/package scalacticJS/mimaReportBinaryIssues
146146
$ sbt ++2.10.7 scalatestJS/package scalatestJS/mimaReportBinaryIssues
147147

148-
$ sbt ++2.12.8 scalactic/package scalactic/mimaReportBinaryIssues
149-
$ sbt ++2.12.8 scalatest/package scalatest/mimaReportBinaryIssues
150-
$ sbt ++2.12.8 scalacticJS/package scalacticJS/mimaReportBinaryIssues
151-
$ sbt ++2.12.8 scalatestJS/package scalatestJS/mimaReportBinaryIssues
148+
$ sbt ++2.12.9 scalactic/package scalactic/mimaReportBinaryIssues
149+
$ sbt ++2.12.9 scalatest/package scalatest/mimaReportBinaryIssues
150+
$ sbt ++2.12.9 scalacticJS/package scalacticJS/mimaReportBinaryIssues
151+
$ sbt ++2.12.9 scalatestJS/package scalatestJS/mimaReportBinaryIssues
152152

153153
$ sbt ++2.13.0 scalactic/package scalactic/mimaReportBinaryIssues
154154
$ sbt ++2.13.0 scalatest/package scalatest/mimaReportBinaryIssues
@@ -160,7 +160,7 @@ To publish scalactic, scalatest and scalatest-app use the following command:
160160
$ export SCALAJS_VERSION=0.6.28
161161
$ sbt ++2.10.7 clean publishSigned "project scalatestAppJS" clean publishSigned
162162
$ sbt ++2.11.12 clean publishSigned "project scalatestAppJS" clean publishSigned
163-
$ sbt ++2.12.8 "project scalatestApp" clean publishSigned "project scalatestAppJS" clean publishSigned
163+
$ sbt ++2.12.9 "project scalatestApp" clean publishSigned "project scalatestAppJS" clean publishSigned
164164
$ sbt ++2.13.0 "project scalatestApp" clean publishSigned "project scalatestAppJS" clean publishSigned
165165
$ sbt ++2.11.12 "project scalatestAppNative" clean publishSigned
166166
$ export SCALAJS_VERSION=1.0.0-M3

project/BuildCommons.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import scala.io.Source
55

66
trait BuildCommons {
77

8-
lazy val supportedScalaVersions = List("2.13.0", "2.12.8", "2.11.12", "2.10.7")
8+
lazy val supportedScalaVersions = List("2.13.0", "2.12.9", "2.11.12", "2.10.7")
99

1010
val releaseVersion = "3.1.0-M1"
1111

project/GenScalacticDotty.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ object GenScalacticDotty {
121121
copyDir("scalactic-macro/src/main/scala/org/scalactic/source", "org/scalactic/source", targetDir,
122122
List(
123123
"PositionMacro.scala", // Already reimplemented in Position.scala
124-
"TypeInfoMacro.scala" // Already reimplemented
124+
"TypeInfoMacro.scala", // Already reimplemented
125+
"Position.scala" // Already exists for scalactic-dotty
125126
)
126127
)
127128

File renamed without changes.
Lines changed: 60 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,75 @@
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-
*/
161
package org.scalactic.source
172

18-
import org.scalactic.Resources
193

4+
//import scala.reflect.macros.blackbox.Context
205
import scala.reflect.macros.Context
6+
import org.scalactic.Resources
217

228
/**
239
* Helper class for Position macro. (Will be removed from the public API if possible in a subsequent 3.0.0-RCx release.)
2410
*/
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._
2634

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+
}
3059
}
3160

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+
3264
/**
3365
* Helper method for Position macro.
3466
*/
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))
6374
}
64-
65-
}
75+
}

0 commit comments

Comments
 (0)