Skip to content

Commit a43e3f5

Browse files
committed
Add printing of definition names and kinds
1 parent fbf90e5 commit a43e3f5

File tree

5 files changed

+123
-15
lines changed

5 files changed

+123
-15
lines changed

repl/src/dotty/tools/repl/Repl.scala

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@ import scala.annotation.tailrec
66
import dotc.reporting.MessageRendering
77
import dotc.reporting.diagnostic.MessageContainer
88
import dotc.ast.untpd
9+
import dotc.ast.tpd
910
import dotc.core.Contexts.Context
11+
import dotc.core.Flags._
12+
import dotc.core.Denotations.Denotation
13+
import dotc.core.NameKinds.SimpleNameKind
14+
import dotc.core.Types.{ ExprType, ConstantType }
1015
import dotc.config.CompilerCommand
1116
import dotc.{ Compiler, Driver }
17+
import dotc.printing.SyntaxHighlighting
1218

1319
import AmmoniteReader._
1420
import results._
@@ -61,12 +67,64 @@ class Repl(settings: Array[String]) extends Driver {
6167
displayErrors(errors)
6268
state
6369
},
64-
(unit, newState) => {
70+
(unit, newState, ctx) => {
71+
displayDefinitions(unit.tpdTree)(ctx)
6572
newState
6673
}
6774
)
6875
}
6976

77+
def displayDefinitions(tree: tpd.Tree)(implicit ctx: Context): Unit = {
78+
def display(tree: tpd.Tree) = if (tree.symbol.info.exists) {
79+
val info = tree.symbol.info
80+
val defn = ctx.definitions
81+
val defs =
82+
info.bounds.hi.finalResultType
83+
.membersBasedOnFlags(Method, Synthetic | Private)
84+
.filterNot { denot =>
85+
denot.symbol.owner == defn.AnyClass ||
86+
denot.symbol.owner == defn.ObjectClass ||
87+
denot.symbol.isConstructor
88+
}
89+
90+
val vals =
91+
info.fields
92+
.filterNot(_.symbol.is(ParamAccessor | Private | Synthetic | Module))
93+
.filter(_.symbol.name.is(SimpleNameKind))
94+
95+
(
96+
defs.map(Rendering.renderMethod) ++
97+
vals.map(Rendering.renderVal)
98+
).foreach(println)
99+
}
100+
101+
def displayTypeDef(tree: tpd.TypeDef) = {
102+
val sym = tree.symbol
103+
val name = tree.name.show.dropRight(if (sym.is(Module)) 1 else 0)
104+
105+
val kind =
106+
if (sym.is(CaseClass)) "case class"
107+
else if (sym.is(Trait)) "trait"
108+
else if (sym.is(Module)) "object"
109+
else "class"
110+
111+
112+
println(SyntaxHighlighting(s"defined $kind $name"))
113+
}
114+
115+
116+
tree match {
117+
case tpd.PackageDef(_, xs) =>
118+
val allTypeDefs = xs.collect { case td: tpd.TypeDef => td }
119+
val (objs, tds) = allTypeDefs.partition(_.name.show.startsWith("ReplSession"))
120+
objs
121+
.foreach(display)
122+
tds
123+
.filterNot(t => t.symbol.is(Synthetic) || !t.name.is(SimpleNameKind))
124+
.foreach(displayTypeDef)
125+
}
126+
}
127+
70128
def interpretCommand(cmd: Command, state: State): Unit = cmd match {
71129
case UnknownCommand(cmd) => {
72130
println(s"""Unknown command: "$cmd", run ":help" for a list of commands""")

repl/src/dotty/tools/repl/ReplCompiler.scala

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,26 +110,26 @@ class ReplCompiler(ictx: Context) extends Compiler {
110110
unit.result
111111
}
112112

113-
def runCompilation(unit: CompilationUnit, state: State): Result[State] = {
113+
def runCompilation(unit: CompilationUnit, state: State): Result[(State, Context)] = {
114114
implicit val ctx = ictx
115115
val reporter = new StoreReporter(null) with UniqueMessagePositions with HideNonSensicalMessages
116116
val run = newRun(ctx.fresh.setReporter(reporter))
117117
run.compileUnits(unit :: Nil)
118118

119119
val errs = reporter.removeBufferedMessages
120-
if (errs.isEmpty) state.copy(
121-
objectIndex = state.objectIndex + 1,
122-
valIndex = state.valIndex
123-
).result
120+
if (errs.isEmpty) {
121+
val newState = State(state.objectIndex + 1, state.valIndex, state.history)
122+
(newState, run.runContext).result
123+
}
124124
else errs.errors
125125
}
126126

127-
def compile(parsed: Parsed, state: State): Result[(CompilationUnit, State)] = {
127+
def compile(parsed: Parsed, state: State): Result[(CompilationUnit, State, Context)] = {
128128
implicit val ctx = ictx
129129
for {
130-
defs <- definitions(parsed.trees, state)
131-
unit <- createUnit(defs.trees, state.objectIndex, parsed.sourceCode)
132-
state <- runCompilation(unit, defs.state)
133-
} yield (unit, state)
130+
defs <- definitions(parsed.trees, state)
131+
unit <- createUnit(defs.trees, state.objectIndex, parsed.sourceCode)
132+
(state, ctx) <- runCompilation(unit, defs.state)
133+
} yield (unit, state, ctx)
134134
}
135135
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package dotty.tools
2+
package repl
3+
4+
import dotc.core.Types._
5+
import dotc.core.Contexts.Context
6+
import dotc.core.Denotations.Denotation
7+
import dotc.core.Flags
8+
9+
object Rendering {
10+
11+
def renderMethod(d: Denotation)(implicit ctx: Context): String = {
12+
def params(tpe: Type): String = tpe match {
13+
case ConstantType(c) => ": " + c.value
14+
case tpe: ParamRef => ": " + tpe.paramName + ".type"
15+
case tpe: TypeRef => ": " + tpe.show
16+
case mt: MethodType =>
17+
val ps = mt.paramNames.zip(mt.paramInfos).map { (name, tpe) =>
18+
val tp = tpe match {
19+
case ConstantType(c) => c.value.toString
20+
case tpe => tpe.show
21+
}
22+
s"${name.show}: $tp"
23+
}
24+
val plist =
25+
if (mt.resultType.isInstanceOf[ExprType]) ""
26+
else "(" + ps.mkString(", ") + ")"
27+
28+
plist + params(mt.resultType)
29+
}
30+
31+
s"def ${d.symbol.name.show}${params(d.info)}"
32+
}
33+
34+
def renderVal(d: Denotation)(implicit ctx: Context): String = {
35+
val prefix = if (d.symbol.is(Flags.Mutable)) "var" else "val"
36+
val tpe = d.info match {
37+
case ConstantType(c) => c.value.toString
38+
case tpe => tpe.show
39+
}
40+
s"$prefix ${d.symbol.name.show}: $tpe"
41+
}
42+
43+
}

repl/src/dotty/tools/repl/results.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ object results {
77
type Errors = Seq[MessageContainer]
88

99
/** A result of a computation is either a list of errors or the result `A` */
10-
class Result[A] private[results] (result: Errors | A) {
10+
class Result[A] private[results] (result: Errors | A) { self =>
1111
def flatMap[B](f: A => Result[B]): Result[B] =
1212
result match {
1313
case errs: Errors => new Result(errs)
@@ -25,6 +25,13 @@ object results {
2525
case errs: Errors => onErrors(errs)
2626
case a: A @unchecked => onResult(a)
2727
}
28+
29+
class WithFilter(p: A => Boolean) {
30+
def flatMap[B](f: A => Result[B]) = self.flatMap(f)
31+
def map[B](f: A => B) = self.map(f)
32+
}
33+
34+
def withFilter(p: A => Boolean) = new WithFilter(p)
2835
}
2936

3037
implicit class ResultConversionA[A](val a: A) extends AnyVal {

repl/test/dotty/tools/repl/CompilerTests.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ class ReplCompilerTests extends ReplTest {
2727

2828
compiler
2929
.compile(parsed, State(0, 0, Nil))
30-
.flatMap { (unit, state) =>
31-
val parsed @ Parsed(_,_) = ParseResult("def foo(i: Int): i.type = i")
30+
.flatMap { (unit, state, ctx) =>
31+
val parsed @ Parsed(_,_) = ParseResult("def foo(i: Int): i.type = i")(ctx)
3232
compiler.compile(parsed, state)
3333
}
3434
.fold(
3535
onErrors(_),
36-
(unit, state) => {
36+
(unit, state, ctx) => {
3737
assert(state.objectIndex == 2,
3838
s"Wrong object offset: expected 2 got ${state.objectIndex}")
3939
}

0 commit comments

Comments
 (0)