summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-05-29 21:30:29 +0000
committerPaul Phillips <paulp@improving.org>2011-05-29 21:30:29 +0000
commita8926ae0b28d606e240f409adca69f1d91f45990 (patch)
treed33af8c263ca170a4440d3f4005f69f0916b5b14
parent4c7d23b470b71e730024d1f7797f742dc97207fa (diff)
downloadscala-a8926ae0b28d606e240f409adca69f1d91f45990.tar.gz
scala-a8926ae0b28d606e240f409adca69f1d91f45990.tar.bz2
scala-a8926ae0b28d606e240f409adca69f1d91f45990.zip
Now :t types declarations as well as expression...
Now :t types declarations as well as expressions, and cleans up the output the same way the repl does so stray unsolved type constraints don't befuddle anyone. Closes #4391, no review.
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoop.scala10
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala55
-rw-r--r--test/files/run/bug4556.check17
-rw-r--r--test/files/run/bug4556.scala9
-rw-r--r--test/files/run/repl-colon-type.check57
-rw-r--r--test/files/run/repl-colon-type.scala23
6 files changed, 122 insertions, 49 deletions
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
index d83076f0be..dc2a653c83 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
@@ -419,13 +419,11 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter)
try newJavap()
catch { case _: Exception => null }
- // TODO: unsolved types shouldn't make it out of this alive.
- //
- // scala> :t Some(Set(1)) getOrElse Set("abc")
- // scala.collection.immutable.Set[_ >: ? <: ?]
+ // Still todo: modules.
private def typeCommand(line: String): Result = {
- intp.typeOfExpression(line, false) match {
- case Some(tp) => tp.toString
+ if (line.trim == "") ":type <expression>"
+ else intp.typeOfExpression(line, false) match {
+ case Some(tp) => intp.afterTyper(tp.toString)
case _ => "" // the error message was already printed
}
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
index 3f91f3c0d6..2594df90d1 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
@@ -510,6 +510,19 @@ class IMain(val settings: Settings, protected val out: PrintWriter) extends Impo
Right(buildRequest(line, trees))
}
+ def typeCleanser(sym: Symbol, memberName: Name): Type = {
+ // the types are all =>T; remove the =>
+ val tp1 = afterTyper(sym.info.nonPrivateDecl(memberName).tpe match {
+ case NullaryMethodType(tp) => tp
+ case tp => tp
+ })
+ // normalize non-public types so we don't see protected aliases like Self
+ afterTyper(tp1 match {
+ case TypeRef(_, sym, _) if !sym.isPublic => tp1.normalize
+ case tp => tp
+ })
+ }
+
/**
* Interpret one line of input. All feedback, including parse errors
* and evaluation results, are printed via the supplied compiler's
@@ -817,25 +830,13 @@ class IMain(val settings: Settings, protected val out: PrintWriter) extends Impo
def lookupTypeOf(name: Name) = typeOf.getOrElse(name, typeOf(global.encode(name.toString)))
def simpleNameOfType(name: TypeName) = (compilerTypeOf get name) map (_.typeSymbol.simpleName)
- private def typeMap[T](f: Type => T): Map[Name, T] = {
- def toType(name: Name): T = {
- // the types are all =>T; remove the =>
- val tp1 = lineAfterTyper(resultSymbol.info.nonPrivateDecl(name).tpe match {
- case NullaryMethodType(tp) => tp
- case tp => tp
- })
- // normalize non-public types so we don't see protected aliases like Self
- lineAfterTyper(tp1 match {
- case TypeRef(_, sym, _) if !sym.isPublic => f(tp1.normalize)
- case tp => f(tp)
- })
- }
- termNames ++ typeNames map (x => x -> toType(x)) toMap
- }
+ private def typeMap[T](f: Type => T): Map[Name, T] =
+ termNames ++ typeNames map (x => x -> f(typeCleanser(resultSymbol, x))) toMap
+
/** Types of variables defined by this request. */
lazy val compilerTypeOf = typeMap[Type](x => x)
/** String representations of same. */
- lazy val typeOf = typeMap[String](_.toString)
+ lazy val typeOf = typeMap[String](tp => afterTyper(tp.toString))
// lazy val definedTypes: Map[Name, Type] = {
// typeNames map (x => x -> afterTyper(resultSymbol.info.nonPrivateDecl(x).tpe)) toMap
@@ -973,6 +974,26 @@ class IMain(val settings: Settings, protected val out: PrintWriter) extends Impo
}
}
+ // Since people will be giving us ":t def foo = 5" even though that is not an
+ // expression, we have a means of typing declarations too.
+ private def typeOfDeclaration(code: String): Option[Type] = {
+ repldbg("typeOfDeclaration(" + code + ")")
+ val obname = freshInternalVarName()
+
+ interpret("object " + obname + " {\n" + code + "\n}\n", true) match {
+ case IR.Success =>
+ val sym = symbolOfTerm(obname)
+ if (sym == NoSymbol) None else {
+ // TODO: bitmap$n is not marked synthetic.
+ val decls = sym.tpe.decls.toList filterNot (x => x.isConstructor || x.isPrivate || (x.name.toString contains "$"))
+ repldbg("decls: " + decls)
+ decls.lastOption map (decl => typeCleanser(sym, decl.name))
+ }
+ case _ =>
+ None
+ }
+ }
+
// XXX literals.
// 1) Identifiers defined in the repl.
// 2) A path loadable via getModule.
@@ -1011,7 +1032,7 @@ class IMain(val settings: Settings, protected val out: PrintWriter) extends Impo
// while letting errors through, so it is first trying it silently: if there
// is an error, and errors are desired, then it re-evaluates non-silently
// to induce the error message.
- beSilentDuring(evaluate()) orElse {
+ beSilentDuring(evaluate()) orElse beSilentDuring(typeOfDeclaration(expr)) orElse {
if (!silent)
evaluate()
diff --git a/test/files/run/bug4556.check b/test/files/run/bug4556.check
deleted file mode 100644
index 69d0b4fda1..0000000000
--- a/test/files/run/bug4556.check
+++ /dev/null
@@ -1,17 +0,0 @@
-Type in expressions to have them evaluated.
-Type :help for more information.
-
-scala>
-
-scala> :type [List(1, 2, 3)]
-<console>:2: error: illegal start of simple expression
- [List(1, 2, 3)]
- ^
-
-
-scala> :type List(1, 2, 3)
-List[Int]
-
-scala>
-
-scala>
diff --git a/test/files/run/bug4556.scala b/test/files/run/bug4556.scala
deleted file mode 100644
index 8f682ce7df..0000000000
--- a/test/files/run/bug4556.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-import scala.tools.partest.ReplTest
-
-object Test extends ReplTest {
- def code = """
- |:type [List(1, 2, 3)]
- |:type List(1, 2, 3)
- """.stripMargin
-}
-
diff --git a/test/files/run/repl-colon-type.check b/test/files/run/repl-colon-type.check
new file mode 100644
index 0000000000..66c2fcc77f
--- /dev/null
+++ b/test/files/run/repl-colon-type.check
@@ -0,0 +1,57 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> :type List[1, 2, 3]
+<console>:2: error: identifier expected but integer literal found.
+ List[1, 2, 3]
+ ^
+
+
+scala> :type List(1, 2, 3)
+List[Int]
+
+scala> :type def foo[T](x: T) = List(x)
+[T](x: T)List[T]
+
+scala> :type val bar = List(Set(1))
+List[scala.collection.immutable.Set[Int]]
+
+scala> :type lazy val bar = Set(Set(1))
+scala.collection.immutable.Set[scala.collection.immutable.Set[Int]]
+
+scala> :type def f[T >: Null, U <: String](x: T, y: U) = Set(x, y)
+[T >: Null, U <: String](x: T, y: U)scala.collection.immutable.Set[Any]
+
+scala> :type def x = 1 ; def bar[T >: Null <: AnyRef](xyz: T) = 5
+[T >: Null <: AnyRef](xyz: T)Int
+
+scala>
+
+scala> :type 5
+Int
+
+scala> :type val f = 5
+Int
+
+scala> :type lazy val f = 5
+Int
+
+scala> :type protected lazy val f = 5
+Int
+
+scala> :type def f = 5
+Int
+
+scala> :type def f() = 5
+()Int
+
+scala>
+
+scala> :type def g[T](xs: Set[_ <: T]) = Some(xs.head)
+[T](xs: Set[_ <: T])Some[T]
+
+scala>
+
+scala>
diff --git a/test/files/run/repl-colon-type.scala b/test/files/run/repl-colon-type.scala
new file mode 100644
index 0000000000..39ab580d2a
--- /dev/null
+++ b/test/files/run/repl-colon-type.scala
@@ -0,0 +1,23 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ def code = """
+ |:type List[1, 2, 3]
+ |:type List(1, 2, 3)
+ |:type def foo[T](x: T) = List(x)
+ |:type val bar = List(Set(1))
+ |:type lazy val bar = Set(Set(1))
+ |:type def f[T >: Null, U <: String](x: T, y: U) = Set(x, y)
+ |:type def x = 1 ; def bar[T >: Null <: AnyRef](xyz: T) = 5
+ |
+ |:type 5
+ |:type val f = 5
+ |:type lazy val f = 5
+ |:type protected lazy val f = 5
+ |:type def f = 5
+ |:type def f() = 5
+ |
+ |:type def g[T](xs: Set[_ <: T]) = Some(xs.head)
+ """.stripMargin
+}
+