-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Conversation
812ba2a
to
11f96fa
Compare
Rebased and fixed syntax highlighting. There's an issue with creating a worksheet and letting vscode configure the IDE: When creating a worksheet in an empty, unconfigured project, vscode will ask the user whether it should configure the IDE. After selecting yes, sbt will set the Everything works fine when the language server is configured by creating a |
I can have a look at what configureIDE is doing |
Should be fixed. Also I've noticed that every line with an expression in the worksheet gets a warning |
|
||
val (text, positionMapper) = | ||
if (worksheetMode) (wrapWorksheet(document.getText), worksheetPositionMapper _) | ||
else (document.getText, identity[SourcePosition] _) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather make this parameter an Option[Position => Position] so we can pass None here.
vscode-dotty/package-lock.json
Outdated
@@ -92,7 +92,7 @@ | |||
"integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", | |||
"dev": true, | |||
"requires": { | |||
"array-uniq": "^1.0.1" | |||
"array-uniq": "1.0.3" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think your npm is doing something weird because mine is reverting these changes. Try upgrading to the latest npm (6.4.1)
} | ||
|
||
try task.get(0, TimeUnit.SECONDS) | ||
catch { case _: Throwable => state } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NonFatal
Thread.sleep(checkCancelledDelayMs) | ||
} catch { | ||
case _: CancellationException => | ||
task.cancel(true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will throw a CancellationException as well.
} | ||
} | ||
|
||
try task.get(0, TimeUnit.SECONDS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe make this configurable, the default can be infinite. Otherwise bound it to the configured timeout.
|
||
class WorksheetTest { | ||
|
||
@Test def evaluateExpression: Unit = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add a bunch of test from Scastie: https://github.com/scalacenter/scastie/blob/master/sbt-runner/src/test/scala/com.olegych.scastie.sbt/SbtActorTest.scala
- multiple
while(true) { }
- exceptions
1 / 0
- utf-8 encoding
- System.err
- initialization issues
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like we're still missing test cases with while(true)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have it in worksheetCancel
:
https://github.com/lampepfl/dotty/pull/5102/files#diff-99d60ad8fb95377d0449fe3f60e1e87bR196
64affd8
to
921d329
Compare
@@ -382,7 +382,7 @@ class DottyLanguageServer extends LanguageServer | |||
else { | |||
val refs = Interactive.namedTrees(uriTrees, Include.references | Include.overriding, sym) | |||
(for { | |||
ref <- refs | |||
ref <- refs if !ref.tree.symbol.isConstructor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
primary constructors are synthetic, but secondary constructors like def this() = this(1)
are not
namedTrees(trees, includeReferences, _.show.toString.contains(nameSubstring)) | ||
(implicit ctx: Context): List[SourceTree] = { | ||
val predicate: NameTree => Boolean = | ||
if (includeReferences) _.show.contains(nameSubstring) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the code was broken before, but I don't understand why now we still have to print the whole tree in some situations. This does not match the documentation comment above, and I don't see why we would ever want to do this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed includeReferences
from this function as it was never set. I have another fix that collects the names from the tree and check whether there exists one that contains the substring if you prefer to keep it.
921d329
to
4155daf
Compare
@@ -31,59 +37,59 @@ object Worksheet { | |||
sendMessage: String => Unit, | |||
cancelChecker: CancelChecker)( | |||
implicit ctx: Context): Unit = { | |||
|
|||
val replMain = dotty.tools.repl.WorksheetMain.getClass.getName.init | |||
val classpath = sys.props("java.class.path") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the classpath used for the worksheet be the same classpath that the language server uses for the InteractiveDriver for the current directory ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is the JVM classpath that runs the REPL, the REPL receives ctx.settings.classpath.value
as classpath.
149d2cd
to
ea33432
Compare
override def didSave(params: DidSaveTextDocumentParams): Unit = | ||
/*thisServer.synchronized*/ {} | ||
|
||
override def didSave(params: DidSaveTextDocumentParams): Unit = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put thisServer.synchronized around since this isn't thread-safe.
private object Evaluator { | ||
|
||
private val javaExec: Option[String] = { | ||
val isWindows = sys.props("os.name").toLowerCase().indexOf("win") >= 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://www.scala-lang.org/api/2.12.7/scala/util/Properties$.html has isWin and javaHome
* | ||
* @param stream The stream of messages coming out of the REPL. | ||
*/ | ||
private class ReplReader(stream: InputStream) extends Thread { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a lot of classes in one file, maybe make a worksheet/ subdirectory instead?
e79158a
to
6b68c3d
Compare
vscode-dotty/src/worksheet.ts
Outdated
@@ -0,0 +1,346 @@ | |||
'use strict' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't actually necessary with recent versions of typescript (it's automatically inserted in the generated js)
vscode-dotty/src/worksheet.ts
Outdated
import { LanguageClient } from 'vscode-languageclient' | ||
|
||
/** All decorations that have been added so far */ | ||
let worksheetDecorationTypes: Map<vscode.TextDocument, vscode.TextEditorDecorationType[]> = new Map<vscode.TextDocument, vscode.TextEditorDecorationType[]>() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would make a class with fields instead of using global variables in this file.
import java.net.URI | ||
|
||
/** The parameter for the `worksheet/exec` request. */ | ||
case class WorksheetExecParams(uri: URI) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add empty secondary constructors that just pass null/0 to every param like def this() = this(null)
here, otherwise when Gson deserializes from json, it will need to create the class instance using sun.misc.Unsafe which seems to work but could be problematic on Java 9+
`Interactive.scala` offered an API to find all references to names given substrings of the names. This feature was unused. This worked by pretty printing the tree and looking whether it contained the substring. This is broken, because the substring may match parts that are not references (what if we look for `if`?) It's gone now.
Because the process running the worksheets is shared between worksheets (when possible), we need to synchronize worksheet evaluation.
It is used to represent the worksheets managed by vscode, instead of having several global variables.
Instead of relying on `textDocument/didSave` and `window/logMessage` like we did in the past.
They are used when deserializing from JSON.
We now hide the warning the pure expression in statement position when the pure expression is an immediate children of the worksheet wrapper.
237739e
to
9a19df7
Compare
Thanks, I fixed it. It would be cool to have tests for VSCode at some point................. |
This is a work in progress to support worksheets in Dotty IDE. The worksheets are backed by the REPL.
Still missing:
Some details:
window/logMessage
. They are encoded as:[URI][line in source that produced the output]:[output]
.