Skip to content

Worksheet mode in Dotty IDE #5102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Oct 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
3a7d2b7
Implement worksheets in Dotty IDE
Duhemm Sep 12, 2018
f933994
Support multiple worksheets
Duhemm Sep 12, 2018
5fae035
Show worksheet evaluation progress
Duhemm Sep 13, 2018
04e40f4
Fix position in constructor call
Duhemm Sep 13, 2018
844a105
Add tests for worksheets
Duhemm Sep 13, 2018
cb6b40f
Consider `.sc` files as belonging to Scala
Duhemm Sep 14, 2018
27d4733
Log sbt output, and close stdin so sbt doesn't block on error
smarter Sep 15, 2018
ace1d5b
configureIDE: write projects to .dotty-ide.json even if they're empty
smarter Sep 15, 2018
a917129
Support cancelling worksheet evaluation
Duhemm Sep 18, 2018
f11f184
Add `needsTerminal` param to `JLineTerminal`
Duhemm Sep 26, 2018
2bd2ffc
Fork a new JVM to execute worksheet
Duhemm Sep 26, 2018
c1ee310
Keep evaluator alive between worksheet runs
Duhemm Sep 27, 2018
d41a47d
Dotty IDE: Do not highlight constructors
Duhemm Sep 27, 2018
de48e95
Fix `namedTrees` with substring search
Duhemm Sep 27, 2018
185e765
Support go to def, rename, etc. in worksheets
Duhemm Sep 27, 2018
79860e0
Add worksheet cancellation test
Duhemm Sep 27, 2018
c3d1367
Test exception in worksheet evaluation
Duhemm Sep 27, 2018
4223ecb
Exclude only primary constructors
Duhemm Sep 28, 2018
ae10994
Respect `-color:never` with typedef in REPL
Duhemm Sep 28, 2018
719acd8
IDE: Remove unused substring reference search
Duhemm Sep 28, 2018
ced2868
Support `System.exit` in worksheet
Duhemm Sep 28, 2018
f4cbbca
Check that worksheets capture stderr
Duhemm Sep 28, 2018
0eb7fc9
Don't wait for messages after stream is closed
Duhemm Oct 1, 2018
c58b314
Fix synchronization issue with worksheets
Duhemm Oct 1, 2018
ce04cc8
Split worksheet implementation
Duhemm Oct 1, 2018
e6b3abd
Check if evaluator runs on Windows
Duhemm Oct 1, 2018
471a059
Fix worksheet tests for Windows
Duhemm Oct 1, 2018
701e8ea
vscode: Add `Worksheet` class
Duhemm Oct 1, 2018
a3bdde1
Remove worksheets when closed
Duhemm Oct 1, 2018
de5c28e
Add `worksheet/exec` and `worksheet/publishOutput`
Duhemm Oct 2, 2018
0689ef3
Add empty secondary ctors to worksheet messages
Duhemm Oct 3, 2018
9ed6971
Address review comments
Duhemm Oct 3, 2018
9666d23
Remove only lines added to fit output
Duhemm Oct 3, 2018
a3efd48
Cancel worksheet execution on `didChange`
Duhemm Oct 4, 2018
2b7e8cf
Error message for pure expr in stat position
Duhemm Oct 4, 2018
dba854d
Filter pure expression warning in worksheets
Duhemm Oct 4, 2018
a2569c2
Factor `WorksheetWrapper` name to StdNames
Duhemm Oct 9, 2018
9a19df7
Remove unnecessary cast
Duhemm Oct 9, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/core/StdNames.scala
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,7 @@ object StdNames {
val wait_ : N = "wait"
val withFilter: N = "withFilter"
val withFilterIfRefutable: N = "withFilterIfRefutable$"
val WorksheetWrapper: N = "WorksheetWrapper"
val wrap: N = "wrap"
val zero: N = "zero"
val zip: N = "zip"
Expand Down
12 changes: 6 additions & 6 deletions compiler/src/dotty/tools/dotc/interactive/Interactive.scala
Original file line number Diff line number Diff line change
Expand Up @@ -265,12 +265,12 @@ object Interactive {
namedTrees(trees, (include & Include.references) != 0, matchSymbol(_, sym, include))

/** Find named trees with a non-empty position whose name contains `nameSubstring` in `trees`.
*
* @param includeReferences If true, include references and not just definitions
*/
def namedTrees(trees: List[SourceTree], includeReferences: Boolean, nameSubstring: String)
(implicit ctx: Context): List[SourceTree] =
namedTrees(trees, includeReferences, _.show.toString.contains(nameSubstring))
def namedTrees(trees: List[SourceTree], nameSubstring: String)
(implicit ctx: Context): List[SourceTree] = {
val predicate: NameTree => Boolean = _.name.toString.contains(nameSubstring)
namedTrees(trees, includeReferences = false, predicate)
}

/** Find named trees with a non-empty position satisfying `treePredicate` in `trees`.
*
Expand Down Expand Up @@ -322,7 +322,7 @@ object Interactive {
val includeLinkedClass = (includes & Include.linkedClass) != 0
val predicate: NameTree => Boolean = tree =>
( tree.pos.isSourceDerived
&& !tree.symbol.isConstructor
&& !tree.symbol.isPrimaryConstructor
&& (includeDeclaration || !Interactive.isDefinition(tree))
&& ( Interactive.matchSymbol(tree, symbol, includes)
|| ( includeDeclaration
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1404,7 +1404,8 @@ object Parsers {
val (impl, missingBody) = template(emptyConstructor)
impl.parents match {
case parent :: Nil if missingBody =>
if (parent.isType) ensureApplied(wrapNew(parent)) else parent
if (parent.isType) ensureApplied(wrapNew(parent))
else parent.withPos(Position(start, in.lastOffset))
case _ =>
New(impl.withPos(Position(start, in.lastOffset)))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ public enum ErrorMessageID {
CaseClassCannotExtendEnumID,
ValueClassParameterMayNotBeCallByNameID,
NotAnExtractorID,
MemberWithSameNameAsStaticID
MemberWithSameNameAsStaticID,
PureExpressionInStatementPositionID
;

public int errorNumber() {
Expand Down
10 changes: 10 additions & 0 deletions compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2139,4 +2139,14 @@ object messages {
override def kind: String = "Syntax"
override def explanation: String = ""
}

case class PureExpressionInStatementPosition(stat: untpd.Tree, exprOwner: Symbol)(implicit ctx: Context)
extends Message(PureExpressionInStatementPositionID) {

val kind = "Potential Issue"
val msg = "a pure expression does nothing in statement position; you may be omitting necessary parentheses"
val explanation =
hl"""The pure expression `$stat` doesn't have any side effect and its result is not assigned elsewhere.
|It can be removed without changing the semantics of the program. This may indicate an error.""".stripMargin
}
}
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2013,7 +2013,7 @@ class Typer extends Namer
val stat1 = typed(stat)(ctx.exprContext(stat, exprOwner))
if (!ctx.isAfterTyper && isPureExpr(stat1) &&
!stat1.tpe.isRef(defn.UnitClass) && !isSelfOrSuperConstrCall(stat1))
ctx.warning(em"a pure expression does nothing in statement position", stat.pos)
ctx.warning(PureExpressionInStatementPosition(stat, exprOwner), stat.pos)
buf += stat1
traverse(rest)
case nil =>
Expand Down
7 changes: 4 additions & 3 deletions compiler/src/dotty/tools/repl/JLineTerminal.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ import org.jline.reader.impl.history.DefaultHistory
import org.jline.terminal.TerminalBuilder
import org.jline.utils.AttributedString

final class JLineTerminal extends java.io.Closeable {
final class JLineTerminal(needsTerminal: Boolean) extends java.io.Closeable {
// import java.util.logging.{Logger, Level}
// Logger.getLogger("org.jline").setLevel(Level.FINEST)

private val terminal = TerminalBuilder.builder()
.dumb(false) // fail early if not able to create a terminal
private val terminal =
TerminalBuilder.builder()
.dumb(!needsTerminal) // fail early if we need a terminal and can't create one
.build()
private val history = new DefaultHistory

Expand Down
7 changes: 6 additions & 1 deletion compiler/src/dotty/tools/repl/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,10 @@ package dotty.tools.repl
/** Main entry point to the REPL */
object Main {
def main(args: Array[String]): Unit =
new ReplDriver(args).runUntilQuit()
new ReplDriver(args).runUntilQuit(needsTerminal = true)
}

object WorksheetMain {
def main(args: Array[String]): Unit =
new ReplDriver(args).runUntilQuit(needsTerminal = false)
}
11 changes: 8 additions & 3 deletions compiler/src/dotty/tools/repl/ReplDriver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ class ReplDriver(settings: Array[String],
* observable outside of the CLI, for this reason, most helper methods are
* `protected final` to facilitate testing.
*/
final def runUntilQuit(initialState: State = initialState): State = {
val terminal = new JLineTerminal()
final def runUntilQuit(needsTerminal: Boolean, initialState: State = initialState): State = {
val terminal = new JLineTerminal(needsTerminal)

/** Blockingly read a line, getting back a parse result */
def readLine(state: State): ParseResult = {
Expand Down Expand Up @@ -285,7 +285,12 @@ class ReplDriver(settings: Array[String],
.foreach { sym =>
// FIXME syntax highlighting on comment is currently not working
// out.println(SyntaxHighlighting.highlight("// defined " + sym.showUser))
out.println(SyntaxHighlighting.CommentColor + "// defined " + sym.showUser + SyntaxHighlighting.NoColor)
val message = "// defined " + sym.showUser
if (ctx.settings.color.value != "never") {
println(SyntaxHighlighting.CommentColor + message + SyntaxHighlighting.NoColor)
} else {
println(message)
}
}


Expand Down
6 changes: 3 additions & 3 deletions compiler/test-resources/repl/errmsgs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ scala> val z: (List[String], List[Int]) = (List(1), List("a"))
|
scala> val a: Inv[String] = new Inv(new Inv(1))
1 | val a: Inv[String] = new Inv(new Inv(1))
| ^^^^^^
| found: Inv[Int]
| required: String
| ^^^^^^^^^^
| found: Inv[Int]
| required: String
|
scala> val b: Inv[String] = new Inv(1)
1 | val b: Inv[String] = new Inv(1)
Expand Down
Loading