Skip to content

Commit d9e7574

Browse files
authored
Merge pull request #5230 from dotty-staging/worksheet-stuff
Worksheet improvements
2 parents b5d9ef3 + 59ceea9 commit d9e7574

16 files changed

+446
-377
lines changed

language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,9 @@ class DottyLanguageServer extends LanguageServer
153153
rootUri = params.getRootUri
154154
assert(rootUri != null)
155155

156-
val c = new ServerCapabilities
156+
class DottyServerCapabilities(val worksheetRunProvider: Boolean = true) extends lsp4j.ServerCapabilities
157+
158+
val c = new DottyServerCapabilities
157159
c.setTextDocumentSync(TextDocumentSyncKind.Full)
158160
c.setDocumentHighlightProvider(true)
159161
c.setDocumentSymbolProvider(true)

language-server/src/dotty/tools/languageserver/worksheet/Worksheet.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ import java.util.concurrent.CancellationException
1515
object Worksheet {
1616

1717
/**
18-
* Evaluate `tree` as a worksheet using the REPL.
18+
* Run `tree` as a worksheet using the REPL.
1919
*
2020
* @param tree The top level object wrapping the worksheet.
2121
* @param sendMessage A mean of communicating the results of evaluation back.
2222
* @param cancelChecker A token to check whether execution should be cancelled.
2323
*/
24-
def evaluate(tree: SourceTree,
25-
sendMessage: (Int, String) => Unit,
26-
cancelChecker: CancelChecker)(
24+
def run(tree: SourceTree,
25+
sendMessage: (Int, String) => Unit,
26+
cancelChecker: CancelChecker)(
2727
implicit ctx: Context): Unit = synchronized {
2828

2929
Evaluator.get(cancelChecker) match {

language-server/src/dotty/tools/languageserver/worksheet/WorksheetClient.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import org.eclipse.lsp4j.services.LanguageClient
44
import org.eclipse.lsp4j.jsonrpc.services.JsonNotification
55

66
/**
7-
* A `LanguageClient` that supports the `worksheet/publishOutput` notification.
8-
*
9-
* @see dotty.tools.languageserver.worksheet.WorksheetExecOutput
7+
* A `LanguageClient` that supports worksheet-specific notifications.
108
*/
119
trait WorksheetClient extends LanguageClient {
10+
/**
11+
* A notification that tells the client that a line of a worksheet produced
12+
* the specified output.
13+
*/
1214
@JsonNotification("worksheet/publishOutput")
13-
def publishOutput(output: WorksheetExecOutput): Unit
15+
def publishOutput(output: WorksheetRunOutput): Unit
1416
}
1517

language-server/src/dotty/tools/languageserver/worksheet/WorksheetMessages.scala

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,21 @@ package dotty.tools.languageserver.worksheet
22

33
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier
44

5-
/** The parameter for the `worksheet/exec` request. */
6-
case class WorksheetExecParams(textDocument: VersionedTextDocumentIdentifier) {
7-
// Used for deserialization
8-
// see https://github.com/lampepfl/dotty/pull/5102#discussion_r222055355
5+
// All case classes in this file should have zero-parameters secondary
6+
// constructors to allow Gson to reflectively create instances on
7+
// deserialization without relying on sun.misc.Unsafe.
8+
9+
/** The parameter for the `worksheet/run` request. */
10+
case class WorksheetRunParams(textDocument: VersionedTextDocumentIdentifier) {
911
def this() = this(null)
1012
}
1113

12-
/** The response to a `worksheet/exec` request. */
13-
case class WorksheetExecResponse(success: Boolean) {
14-
// Used for deserialization
15-
// see https://github.com/lampepfl/dotty/pull/5102#discussion_r222055355
14+
/** The response to a `worksheet/run` request. */
15+
case class WorksheetRunResult(success: Boolean) {
1616
def this() = this(false)
1717
}
1818

19-
/**
20-
* A notification that tells the client that a line of a worksheet
21-
* produced the specified output.
22-
*/
23-
case class WorksheetExecOutput(textDocument: VersionedTextDocumentIdentifier, line: Int, content: String) {
24-
// Used for deserialization
25-
// see https://github.com/lampepfl/dotty/pull/5102#discussion_r222055355
19+
/** The parameters to the `worksheet/publishOutput` notification. */
20+
case class WorksheetRunOutput(textDocument: VersionedTextDocumentIdentifier, line: Int, content: String) {
2621
def this() = this(null, 0, null)
2722
}

language-server/src/dotty/tools/languageserver/worksheet/WorksheetService.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,18 @@ trait WorksheetService { thisServer: DottyLanguageServer =>
1616
val worksheets: ConcurrentHashMap[URI, CompletableFuture[_]] = new ConcurrentHashMap()
1717

1818
@JsonRequest
19-
def exec(params: WorksheetExecParams): CompletableFuture[WorksheetExecResponse] = thisServer.synchronized {
19+
def run(params: WorksheetRunParams): CompletableFuture[WorksheetRunResult] = thisServer.synchronized {
2020
val uri = new URI(params.textDocument.getUri)
2121
val future =
2222
computeAsync { cancelChecker =>
2323
try {
2424
val driver = driverFor(uri)
25-
val sendMessage = (line: Int, msg: String) => client.publishOutput(WorksheetExecOutput(params.textDocument, line, msg))
26-
evaluateWorksheet(driver, uri, sendMessage, cancelChecker)(driver.currentCtx)
27-
WorksheetExecResponse(success = true)
25+
val sendMessage = (line: Int, msg: String) => client.publishOutput(WorksheetRunOutput(params.textDocument, line, msg))
26+
runWorksheet(driver, uri, sendMessage, cancelChecker)(driver.currentCtx)
27+
WorksheetRunResult(success = true)
2828
} catch {
2929
case _: Throwable =>
30-
WorksheetExecResponse(success = false)
30+
WorksheetRunResult(success = false)
3131
} finally {
3232
worksheets.remove(uri)
3333
}
@@ -37,21 +37,21 @@ trait WorksheetService { thisServer: DottyLanguageServer =>
3737
}
3838

3939
/**
40-
* Evaluate the worksheet at `uri`.
40+
* Run the worksheet at `uri`.
4141
*
4242
* @param driver The driver for the project that contains the worksheet.
4343
* @param uri The URI of the worksheet.
4444
* @param sendMessage A mean of communicating the results of evaluation back.
4545
* @param cancelChecker Token to check whether evaluation was cancelled
4646
*/
47-
private def evaluateWorksheet(driver: InteractiveDriver,
47+
private def runWorksheet(driver: InteractiveDriver,
4848
uri: URI,
4949
sendMessage: (Int, String) => Unit,
5050
cancelChecker: CancelChecker)(
5151
implicit ctx: Context): Unit = {
5252
val trees = driver.openedTrees(uri)
5353
trees.headOption.foreach { tree =>
54-
Worksheet.evaluate(tree, sendMessage, cancelChecker)
54+
Worksheet.run(tree, sendMessage, cancelChecker)
5555
}
5656
}
5757
}

language-server/test/dotty/tools/languageserver/WorksheetTest.scala

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,34 @@ import java.lang.System.{lineSeparator => nl}
1212

1313
class WorksheetTest {
1414

15-
@Test def evaluateExpression: Unit = {
15+
@Test def runExpression: Unit = {
1616
ws"${m1}2 + 2".withSource
17-
.evaluate(m1, "1:val res0: Int = 4")
17+
.run(m1, "1:val res0: Int = 4")
1818
}
1919

20-
@Test def evaluateSimpleVal: Unit = {
20+
@Test def runSimpleVal: Unit = {
2121
ws"${m1}val foo = 123".withSource
22-
.evaluate(m1, "1:val foo: Int = 123")
22+
.run(m1, "1:val foo: Int = 123")
2323
}
2424

2525
@Test def usePreviousDefinition: Unit = {
2626
ws"""${m1}val foo = 123
2727
val bar = foo + 1""".withSource
28-
.evaluate(m1, "1:val foo: Int = 123",
28+
.run(m1, "1:val foo: Int = 123",
2929
"2:val bar: Int = 124")
3030
}
3131

3232
@Test def defineObject: Unit = {
3333
ws"""${m1}def foo(x: Int) = x + 1
3434
foo(1)""".withSource
35-
.evaluate(m1, "1:def foo(x: Int): Int",
35+
.run(m1, "1:def foo(x: Int): Int",
3636
"2:val res0: Int = 2")
3737
}
3838

3939
@Test def defineCaseClass: Unit = {
4040
ws"""${m1} case class Foo(x: Int)
4141
Foo(1)""".withSource
42-
.evaluate(m1, "1:// defined case class Foo",
42+
.run(m1, "1:// defined case class Foo",
4343
"2:val res0: Foo = Foo(1)")
4444
}
4545

@@ -48,15 +48,15 @@ class WorksheetTest {
4848
override def toString: String = "Foo"
4949
}
5050
new Foo(1)""".withSource
51-
.evaluate(m1, "3:// defined class Foo",
51+
.run(m1, "3:// defined class Foo",
5252
"4:val res0: Foo = Foo")
5353
}
5454

5555
@Test def defineAnonymousClass0: Unit = {
5656
ws"""${m1}new {
5757
override def toString: String = "Foo"
5858
}""".withSource
59-
.evaluate(m1, "3:val res0: Object = Foo")
59+
.run(m1, "3:val res0: Object = Foo")
6060
}
6161

6262
@Test def defineAnonymousClass1: Unit = {
@@ -65,33 +65,33 @@ class WorksheetTest {
6565
new Foo with Bar {
6666
override def toString: String = "Foo"
6767
}""".withSource
68-
.evaluate(m1, "1:// defined class Foo",
68+
.run(m1, "1:// defined class Foo",
6969
"2:// defined trait Bar",
7070
"5:val res0: Foo & Bar = Foo")
7171
}
7272

7373
@Test def produceMultilineOutput: Unit = {
7474
ws"""${m1}1 to 3 foreach println""".withSource
75-
.evaluate(m1, s"1:1${nl}2${nl}3")
75+
.run(m1, s"1:1${nl}2${nl}3")
7676
}
7777

7878
@Test def patternMatching0: Unit = {
7979
ws"""${m1}1 + 2 match {
8080
case x if x % 2 == 0 => "even"
8181
case _ => "odd"
8282
}""".withSource
83-
.evaluate(m1, "4:val res0: String = odd")
83+
.run(m1, "4:val res0: String = odd")
8484
}
8585

8686
@Test def patternMatching1: Unit = {
8787
ws"""${m1}val (foo, bar) = (1, 2)""".withSource
88-
.evaluate(m1, s"1:val foo: Int = 1${nl}val bar: Int = 2")
88+
.run(m1, s"1:val foo: Int = 1${nl}val bar: Int = 2")
8989
}
9090

9191
@Test def evaluationException: Unit = {
9292
ws"""${m1}val foo = 1 / 0
9393
val bar = 2""".withSource
94-
.evaluateNonStrict(m1, "1:java.lang.ArithmeticException: / by zero",
94+
.runNonStrict(m1, "1:java.lang.ArithmeticException: / by zero",
9595
"2:val bar: Int = 2")
9696
}
9797

@@ -200,19 +200,19 @@ class WorksheetTest {
200200
val bar = 2
201201
while (true) {}
202202
val baz = 3""".withSource
203-
.cancelEvaluation(m1, afterMs = 5000)
203+
.cancelRun(m1, afterMs = 5000)
204204
}
205205

206206
@Test def systemExit(): Unit = {
207207
ws"""${m1}println("Hello, world!")
208208
System.exit(0)
209209
println("Goodbye!")""".withSource
210-
.evaluate(m1, "1:Hello, world!")
210+
.run(m1, "1:Hello, world!")
211211
}
212212

213213
@Test def outputOnStdErr(): Unit = {
214214
ws"""${m1}System.err.println("Oh no")""".withSource
215-
.evaluate(m1, "1:Oh no")
215+
.run(m1, "1:Oh no")
216216
}
217217

218218
}

language-server/test/dotty/tools/languageserver/util/CodeTester.scala

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -118,39 +118,39 @@ class CodeTester(sources: List[SourceWithPositions], actions: List[Action]) {
118118
doAction(new CodeSymbol(query, symbols))
119119

120120
/**
121-
* Triggers evaluation of the worksheet specified by `marker`, verifies that the results of
122-
* evaluation match `expected.
121+
* Triggers running the worksheet specified by `marker`, verifies that the results of
122+
* the run matches `expected`.
123123
*
124124
* @param marker A marker a identifies the worksheet to evaluate.
125125
* @param expected The expected output.
126126
*
127-
* @see dotty.tools.languageserver.util.actions.WorksheetEvaluate
127+
* @see dotty.tools.languageserver.util.actions.WorksheetRun
128128
*/
129-
def evaluate(marker: CodeMarker, expected: String*): this.type =
130-
doAction(new WorksheetEvaluate(marker, expected, strict = true))
129+
def run(marker: CodeMarker, expected: String*): this.type =
130+
doAction(new WorksheetRun(marker, expected, strict = true))
131131

132132
/**
133-
* Triggers evaluation of the worksheet specified by `marker`, verifies that each line of output
133+
* Triggers running the worksheet specified by `marker`, verifies that each line of output
134134
* starts with `expected`.
135135
*
136136
* @param marker A marker a identifies the worksheet to evaluate.
137137
* @param expected The expected starts of output.
138138
*
139-
* @see dotty.tools.languageserver.util.actions.WorksheetEvaluate
139+
* @see dotty.tools.languageserver.util.actions.WorksheetRun
140140
*/
141-
def evaluateNonStrict(marker: CodeMarker, expected: String*): this.type =
142-
doAction(new WorksheetEvaluate(marker, expected, strict = false))
141+
def runNonStrict(marker: CodeMarker, expected: String*): this.type =
142+
doAction(new WorksheetRun(marker, expected, strict = false))
143143

144144
/**
145-
* Triggers evaluation of the worksheet specified by `marker`, then verifies that execution can be
145+
* Triggers running the worksheet specified by `marker`, then verifies that execution can be
146146
* cancelled after `afterMs` milliseconds.
147147
*
148148
* @param marker A marker that identifier the worksheet to evaluate.
149149
* @param afterMs The delay in milliseconds before cancelling execution.
150150
*
151151
* @see dotty.tools.languageserver.util.actions.WorksheetCancel
152152
*/
153-
def cancelEvaluation(marker: CodeMarker, afterMs: Long): this.type =
153+
def cancelRun(marker: CodeMarker, afterMs: Long): this.type =
154154
doAction(new WorksheetCancel(marker, afterMs))
155155

156156
private def doAction(action: Action): this.type = {

language-server/test/dotty/tools/languageserver/util/actions/WorksheetAction.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package dotty.tools.languageserver.util.actions
22

3-
import dotty.tools.languageserver.worksheet.{WorksheetExecOutput, WorksheetExecParams, WorksheetExecResponse}
3+
import dotty.tools.languageserver.worksheet.{WorksheetRunOutput, WorksheetRunParams, WorksheetRunResult}
44
import dotty.tools.languageserver.util.embedded.CodeMarker
55

66
import java.net.URI
@@ -10,13 +10,13 @@ import org.eclipse.lsp4j.VersionedTextDocumentIdentifier
1010

1111
abstract class WorksheetAction extends Action {
1212

13-
/** Triggers the evaluation of the worksheet. */
14-
def triggerEvaluation(marker: CodeMarker): Exec[CompletableFuture[WorksheetExecResponse]] = {
15-
server.exec(WorksheetExecParams(marker.toVersionedTextDocumentIdentifier))
13+
/** Triggers running the worksheet. */
14+
def triggerRun(marker: CodeMarker): Exec[CompletableFuture[WorksheetRunResult]] = {
15+
server.run(WorksheetRunParams(marker.toVersionedTextDocumentIdentifier))
1616
}
1717

1818
/** The output of the worksheet that contains `marker`. */
19-
def worksheetOutput(marker: CodeMarker): Exec[List[WorksheetExecOutput]] = {
19+
def worksheetOutput(marker: CodeMarker): Exec[List[WorksheetRunOutput]] = {
2020
val textDocument = marker.toVersionedTextDocumentIdentifier
2121
client.worksheetOutput.get.filter(_.textDocument.getUri == textDocument.getUri)
2222
}

language-server/test/dotty/tools/languageserver/util/actions/WorksheetCancel.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import java.util.concurrent.TimeUnit
1010
class WorksheetCancel(marker: CodeMarker, afterMs: Long) extends WorksheetAction {
1111

1212
override def execute(): Exec[Unit] = {
13-
val futureResult = triggerEvaluation(marker)
13+
val futureResult = triggerRun(marker)
1414
Thread.sleep(afterMs)
1515
val cancelled = futureResult.cancel(true)
1616

language-server/test/dotty/tools/languageserver/util/actions/WorksheetEvaluate.scala renamed to language-server/test/dotty/tools/languageserver/util/actions/WorksheetRun.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import java.util.concurrent.TimeUnit
77

88
import org.junit.Assert.{assertEquals, assertTrue, fail}
99

10-
class WorksheetEvaluate(marker: CodeMarker, expected: Seq[String], strict: Boolean) extends WorksheetAction {
10+
class WorksheetRun(marker: CodeMarker, expected: Seq[String], strict: Boolean) extends WorksheetAction {
1111

1212
override def execute(): Exec[Unit] = {
13-
val result = triggerEvaluation(marker).get(30, TimeUnit.SECONDS)
13+
val result = triggerRun(marker).get(30, TimeUnit.SECONDS)
1414
assertTrue(result.success)
1515

1616
val logs = worksheetOutput(marker).map(out => s"${out.line}:${out.content}")
@@ -26,5 +26,5 @@ class WorksheetEvaluate(marker: CodeMarker, expected: Seq[String], strict: Boole
2626
}
2727

2828
override def show: PositionContext.PosCtx[String] =
29-
s"WorksheetEvaluate(${marker.file}, ${expected})"
29+
s"WorksheetRun(${marker.file}, ${expected})"
3030
}

language-server/test/dotty/tools/languageserver/util/server/TestClient.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package dotty.tools.languageserver.util.server
22

3-
import dotty.tools.languageserver.worksheet.{WorksheetExecOutput, WorksheetClient}
3+
import dotty.tools.languageserver.worksheet.{WorksheetRunOutput, WorksheetClient}
44

55
import java.util.concurrent.CompletableFuture
66

@@ -22,7 +22,7 @@ class TestClient extends WorksheetClient {
2222
val log = new Log[MessageParams]
2323
val diagnostics = new Log[PublishDiagnosticsParams]
2424
val telemetry = new Log[Any]
25-
val worksheetOutput = new Log[WorksheetExecOutput]
25+
val worksheetOutput = new Log[WorksheetRunOutput]
2626

2727
override def logMessage(message: MessageParams) = {
2828
log += message
@@ -45,7 +45,7 @@ class TestClient extends WorksheetClient {
4545
diagnostics += diagnosticsParams
4646
}
4747

48-
override def publishOutput(output: WorksheetExecOutput) = {
48+
override def publishOutput(output: WorksheetRunOutput) = {
4949
worksheetOutput += output
5050
}
5151

0 commit comments

Comments
 (0)