summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2013-04-15 23:16:34 -0700
committerAdriaan Moors <adriaan.moors@typesafe.com>2013-04-15 23:16:34 -0700
commit86651c1205de9d901a9f0a0214888ac7c4724b81 (patch)
tree50bfed24410467a1926ebd0cedd35d79bd6750f8
parente337bfca56572b88dbc75a0e5d20f862be5f4ce0 (diff)
parent4e2459e3de5a1265d5bf071fc1029c6c022336c3 (diff)
downloadscala-86651c1205de9d901a9f0a0214888ac7c4724b81.tar.gz
scala-86651c1205de9d901a9f0a0214888ac7c4724b81.tar.bz2
scala-86651c1205de9d901a9f0a0214888ac7c4724b81.zip
Merge pull request #2380 from paulp/pr/reifier-ast-test
Reifier -> AST Node test.
-rw-r--r--src/compiler/scala/reflect/reify/phases/Reshape.scala2
-rw-r--r--src/reflect/scala/reflect/internal/util/Position.scala48
-rw-r--r--test/files/run/reify-each-node-type.check35
-rw-r--r--test/files/run/reify-each-node-type.scala108
4 files changed, 180 insertions, 13 deletions
diff --git a/src/compiler/scala/reflect/reify/phases/Reshape.scala b/src/compiler/scala/reflect/reify/phases/Reshape.scala
index bc2dbeed3e..5f53f558b4 100644
--- a/src/compiler/scala/reflect/reify/phases/Reshape.scala
+++ b/src/compiler/scala/reflect/reify/phases/Reshape.scala
@@ -167,7 +167,7 @@ trait Reshape {
// if this assumption fails, please, don't be quick to add postprocessing here (like I did before)
// but rather try to fix this in Typer, so that it produces quality originals (like it's done for typedAnnotated)
if (reifyDebug) println("TypeTree, essential: %s (%s)".format(tt.tpe, tt.tpe.kind))
- if (reifyDebug) println("verdict: rolled back to original %s".format(tt.original))
+ if (reifyDebug) println("verdict: rolled back to original %s".format(tt.original.toString.replaceAll("\\s+", " ")))
transform(tt.original)
} else {
// type is deemed to be non-essential
diff --git a/src/reflect/scala/reflect/internal/util/Position.scala b/src/reflect/scala/reflect/internal/util/Position.scala
index bb8c9e9b26..fe6c7db989 100644
--- a/src/reflect/scala/reflect/internal/util/Position.scala
+++ b/src/reflect/scala/reflect/internal/util/Position.scala
@@ -20,18 +20,12 @@ object Position {
else if (posIn.isDefined) posIn.inUltimateSource(posIn.source)
else posIn
)
- def file = pos.source.file
- def prefix = if (shortenFile) file.name else file.path
+ val prefix = if (shortenFile) pos.sourceName else pos.sourcePath
pos match {
case FakePos(fmsg) => fmsg+" "+msg
case NoPosition => msg
- case _ =>
- List(
- "%s:%s: %s".format(prefix, pos.line, msg),
- pos.lineContent.stripLineEnd,
- " " * (pos.column - 1) + "^"
- ) mkString "\n"
+ case _ => "%s:%s: %s\n%s\n%s".format(prefix, pos.line, msg, pos.lineContent, pos.lineCarat)
}
}
}
@@ -206,12 +200,39 @@ abstract class Position extends scala.reflect.api.Position { self =>
def column: Int = throw new UnsupportedOperationException("Position.column")
+ /** A line with a ^ padded with the right number of spaces.
+ */
+ def lineCarat: String = " " * (column - 1) + "^"
+
+ /** The line of code and the corresponding carat pointing line, trimmed
+ * to the maximum specified width, with the trimmed versions oriented
+ * around the point to give maximum context.
+ */
+ def lineWithCarat(maxWidth: Int): (String, String) = {
+ val radius = maxWidth / 2
+ var start = math.max(column - radius, 0)
+ var result = lineContent drop start take maxWidth
+
+ if (result.length < maxWidth) {
+ result = lineContent takeRight maxWidth
+ start = lineContent.length - result.length
+ }
+
+ (result, lineCarat drop start take maxWidth)
+ }
+
/** Convert this to a position around `point` that spans a single source line */
def toSingleLine: Position = this
- def lineContent: String =
- if (isDefined) source.lineToString(line - 1)
- else "NO_LINE"
+ /** The source code corresponding to the range, if this is a range position.
+ * Otherwise the empty string.
+ */
+ def sourceCode = ""
+ def sourceName = "<none>"
+ def sourcePath = "<none>"
+ def lineContent = "<none>"
+ def lengthInChars = 0
+ def lengthInLines = 0
/** Map this position to a position in an original source
* file. If the SourceFile is a normal SourceFile, simply
@@ -240,7 +261,10 @@ class OffsetPosition(override val source: SourceFile, override val point: Int) e
override def withPoint(off: Int) = new OffsetPosition(source, off)
override def withSource(source: SourceFile, shift: Int) = new OffsetPosition(source, point + shift)
- override def line: Int = source.offsetToLine(point) + 1
+ override def line = source.offsetToLine(point) + 1
+ override def sourceName = source.file.name
+ override def sourcePath = source.file.path
+ override def lineContent = source.lineToString(line - 1)
override def column: Int = {
var idx = source.lineToOffset(source.offsetToLine(point))
diff --git a/test/files/run/reify-each-node-type.check b/test/files/run/reify-each-node-type.check
new file mode 100644
index 0000000000..af6fd13a7b
--- /dev/null
+++ b/test/files/run/reify-each-node-type.check
@@ -0,0 +1,35 @@
+ 1 s Ident
+ 2 r.List Select
+ 3 r.List.apply() Apply
+ 4 r.List.apply(1) Literal
+ 5 r.List.apply[Int]() TypeApply
+ 6 (1: Int) Typed
+ 7 (null: r.List[Int]) AppliedTypeTree
+ 8 { (); () } Block
+ 9 { val x: Int = 0; () } ValDef
+10 { val x = 0; () } TypeTree
+11 if (true) () else () If
+12 { def f: Unit = (); () } DefDef
+13 { def m = NN.super.q; () } Super
+14 { abstract trait A extends AnyRef; () } ClassDef Template
+15 { def f(x: Any): Unit = (); () } EmptyTree
+16 (null: r.D with r.E) CompoundTypeTree
+17 { type T = Int; () } TypeDef
+18 { type CC[T >: Nothing <: r.D] = r.C[T]; () } TypeBoundsTree
+19 try { 0 } finally Predef.println("") Try
+20 ((x: Int) => x) Function
+21 { var v = 1; v = 2 } Assign
+22 { class A extends AnyRef { def <init>() = { super.<init>(); This
+23 new r.List[Int]() New
+24 0: @unchecked Annotated
+25 (null: r.Outer#Inner) SelectFromTypeTree
+26 (null: Nil.type) SingletonTypeTree
+27 (null: T forSome { type T >: Nothing <: Any }) ExistentialTypeTree
+28 { import r.{A, B=>C}; () } Import
+29 { def f: Int = return 0; () } Return
+30 { object x extends AnyRef { def <init>() = { super.<init>(); ModuleDef
+31 throw new Exception() Throw
+32 0 match { case _ => 0 } Match CaseDef
+33 0 match { case (1| 2) => 0 } Alternative
+34 NN.q match { case (x @ r.List) => 0 } Bind
+35 NN.q match { case r.UnSeq(1, (_)*) => 0 } Star
diff --git a/test/files/run/reify-each-node-type.scala b/test/files/run/reify-each-node-type.scala
new file mode 100644
index 0000000000..a827da766d
--- /dev/null
+++ b/test/files/run/reify-each-node-type.scala
@@ -0,0 +1,108 @@
+import scala.reflect.runtime.universe._
+
+object r {
+ class A
+ class B
+ class List[+A]
+ object List { def apply[A](xs: A*): List[A] = new List[A] }
+ object Nil extends List[Nothing]
+
+ trait OuterP[A] {
+ trait Inner
+ trait InnerP[B]
+ }
+ trait Outer {
+ trait Inner
+ trait InnerP[B]
+ }
+ object Un { def unapply(x: Any) = Some(5) }
+ object UnSeq { def unapplySeq(x: Any) = Some(Seq(5)) }
+ class C[T]
+ class D
+ trait E
+
+ trait SN {
+ def q: Any = null
+ }
+}
+
+object s {
+ import r._
+
+ trait NN extends SN {
+ def act[T](expr: Expr[T]): Unit
+
+ act(reify { s /* Ident */ })
+ act(reify { r.List /* Select */ })
+ act(reify { List() /* Apply */ })
+ act(reify { List(1) /* Literal */ })
+ act(reify { List[Int]() /* TypeApply */ })
+ act(reify { 1: Int /* Typed */ })
+ act(reify { null: List[Int] /* AppliedTypeTree */ })
+ act(reify { () ; () /* Block */ })
+ act(reify { val x: Int = 0 /* ValDef */ })
+ act(reify { val x = 0 /* TypeTree */ })
+ act(reify { if (true) () /* If */ })
+ act(reify { def f { } /* DefDef */ })
+ act(reify { def m = super.q /* Super */ })
+ act(reify { trait A /* ClassDef Template */ })
+ act(reify { def f(x: Any) { } /* EmptyTree */ })
+ act(reify { null: D with E /* CompoundTypeTree */ })
+ act(reify { type T = Int /* TypeDef */ })
+ act(reify { type CC[T <: D] = C[T] /* TypeBoundsTree */ })
+ act(reify { try 0 finally println("") /* Try */ })
+ act(reify { (x: Int) => x /* Function */ })
+ act(reify { var v = 1 ; v = 2 /* Assign */ })
+ act(reify { class A() { def this(x: A) = this() } /* This */ })
+ act(reify { new List[Int] /* New */ })
+ act(reify { 0: @unchecked /* Annotated */ })
+ act(reify { null: Outer#Inner /* SelectFromTypeTree */ })
+ act(reify { null: Nil.type /* SingletonTypeTree */ })
+ act(reify { null: (T forSome { type T }) /* ExistentialTypeTree */ })
+ act(reify { import r.{ A, B => C }; /* Import */ })
+ act(reify { def f: Int = return 0 /* Return */ })
+ act(reify { object x /* ModuleDef */ })
+ act(reify { throw new java.lang.Exception /* Throw */ })
+ act(reify { 0 match { case _ => 0 } /* Match CaseDef */ })
+ act(reify { 0 match { case 1 | 2 => 0 } /* Alternative */ })
+ act(reify { q match { case x @ List => 0 } /* Bind */ })
+ act(reify { q match { case UnSeq(1, _*) => 0 } /* Star */ })
+
+ // ``unexpected: bound type that doesn't have a tpe: Ident(newTypeName("Int"))''
+ // act(reify { r.List[T forSome { type T <: Int }]() }) // Was crashing , no longer
+ //
+ // error: exception during macro expansion:
+ // scala.MatchError: collection.this.Seq.unapplySeq[A] (of class scala.reflect.internal.Trees$TypeApply)
+ // at scala.reflect.reify.phases.Reshape$$anon$1.extractExtractor$1(Reshape.scala:73)
+ // at scala.reflect.reify.phases.Reshape$$anon$1.transform(Reshape.scala:82)
+ // at scala.reflect.reify.phases.Reshape$$anon$1.transform(Reshape.scala:24)
+ // at scala.reflect.internal.Trees$class.itransform(Trees.scala:1290)
+ //
+ // act(reify { r.List[Any]() match { case Seq(1, _*) => 1 } } )
+
+ // act(reify { List[OuterP[Int]#InnerP[Byte]]() })
+ //
+ // SI-7243
+ //
+ // test/files/run/reify-each-node-type.scala:85: error: Cannot materialize r.List.apply[r.OuterP[Int]#InnerP[Byte]]() as { ... } because:
+ // scala.reflect.macros.TypecheckException: value TypeTreeWithDeferredRefCheck is not a member of type parameter U
+ // act(reify { List[OuterP[Int]#InnerP[Byte]]() })
+ // ^
+ // one error found
+ }
+}
+
+object Test {
+ var idx = 0
+ val seen = scala.collection.mutable.Set[String]()
+
+ object N extends s.NN {
+ def act[T](expr: Expr[T]): Unit = {
+ idx += 1
+ val ts = expr.tree filter (_ => true) map (_.getClass.getName split "[.$]" last) filterNot seen distinct;
+ println("%2d %60s %s".format(idx, expr.tree.toString.replaceAll("""\s+""", " ").take(60), ts mkString " "))
+ seen ++= ts
+ }
+ }
+ def main(args: Array[String]): Unit = N
+}