Skip to content

Commit e6340ad

Browse files
committed
Add documentation for the IDE tests
1 parent 068fcca commit e6340ad

16 files changed

+268
-55
lines changed

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ package dotty.tools.languageserver.util
22

33
import dotty.tools.languageserver.util.embedded._
44

5+
/**
6+
* Helper object to create virtual source files and extract markers from the source files, using the
7+
* `code` interpolator.
8+
*
9+
* The markers can then be used to perform tests at different positions within the source
10+
* file.
11+
*/
512
object Code {
613

714
// Default positions
@@ -15,6 +22,19 @@ object Code {
1522
val m8 = new CodeMarker("m8")
1623

1724
implicit class CodeHelper(val sc: StringContext) extends AnyVal {
25+
26+
/**
27+
* An interpolator that lets set marker inside a virtual source file.
28+
*
29+
* For instance:
30+
* ```
31+
* code"""object ${m1}Foo${m2} { def bar = ${m3}Hello{$m4}.quux }"""
32+
* ```
33+
*
34+
* This will define a source file where the markers `m1` and `m2` enclose the identifier `Foo`,
35+
* and `m3` and `m4` enclose the identifier `Hello`. These positions can then be used to ask to
36+
* perform actions such as finding all references, etc.
37+
*/
1838
def code(args: Embedded*): SourceWithPositions = {
1939
val pi = sc.parts.iterator
2040
val ai = args.iterator
@@ -54,10 +74,18 @@ object Code {
5474
}
5575
}
5676

77+
/** A new `CodeTester` working with `sources` in the workspace. */
5778
def withSources(sources: SourceWithPositions*): CodeTester = new CodeTester(sources.toList, Nil)
5879

80+
/**
81+
* A virtual source file where several markers have been set.
82+
*
83+
* @param text The code contained within the virtual source file.
84+
* @param positions The positions of the markers that have been set.
85+
*/
5986
case class SourceWithPositions(text: String, positions: List[(CodeMarker, Int, Int)]) {
60-
def withSource: CodeTester = new CodeTester(this :: Nil, Nil)
87+
/** A new `CodeTester` with only this source in the workspace. */
88+
def withSource: CodeTester = new CodeTester(this :: Nil, Nil)
6189
}
6290

6391
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ import org.eclipse.lsp4j._
77

88
import PositionContext._
99

10+
/**
11+
* A range of positions between two markers.
12+
*
13+
* @param start The start marker.
14+
* @param end The end marker.
15+
*/
1016
case class CodeRange(start: CodeMarker, end: CodeMarker) {
1117
private var checked = false
1218
def check(): PosCtx[Unit] = {

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

Lines changed: 95 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import dotty.tools.languageserver.util.embedded.CodeMarker
66
import dotty.tools.languageserver.util.server.{TestFile, TestServer}
77
import org.eclipse.lsp4j.SymbolInformation
88

9+
/**
10+
* Simulates an LSP client for test in a workspace defined by `sources`.
11+
*
12+
* @param sources The list of sources in the workspace
13+
* @param actions Unused
14+
*/
915
class CodeTester(sources: List[SourceWithPositions], actions: List[Action]) {
1016

1117
private val testServer = new TestServer(TestFile.testDir)
@@ -15,27 +21,106 @@ class CodeTester(sources: List[SourceWithPositions], actions: List[Action]) {
1521
}
1622
private val positions: PositionContext = getPositions(files)
1723

24+
/**
25+
* Perform a hover over `range`, verifies that result matches `expected`.
26+
*
27+
* @param range The range over which to hover.
28+
* @param expected The expected result.
29+
* @return This `CodeTester` after performing the action.
30+
*
31+
* @see dotty.tools.languageserver.util.actions.CodeHover
32+
*/
1833
def hover(range: CodeRange, expected: String): CodeTester =
1934
doAction(new CodeHover(range, expected))
2035

21-
def definition(range: CodeRange, refOpt: Seq[CodeRange]): CodeTester =
22-
doAction(new CodeDefinition(range, refOpt))
36+
/**
37+
* Perform a jump to definition over `range`, verifies that the results are `expected`.
38+
*
39+
* @param range The range of positions from which run `jump to definition`.
40+
* @param expected The expected positions to jump to.
41+
* @return This `CodeTester` after performing the action.
42+
*
43+
* @see dotty.tools.languageserver.util.actions.CodeDefinition
44+
*/
45+
def definition(range: CodeRange, expected: Seq[CodeRange]): CodeTester =
46+
doAction(new CodeDefinition(range, expected))
2347

24-
def highlight(range: CodeRange, highs: (CodeRange, String)*): CodeTester =
25-
doAction(new CodeDocumentHighlight(range, highs))
48+
/**
49+
* Perform a highlight over `range`, verifies that the ranges and kinds of symbols match
50+
* `expected`.
51+
*
52+
* @param range The range of positions to highlight.
53+
* @param expected The expected ranges and the kind of symbols that should be highlighted.
54+
* @return This `CodeTester` after performing the action.
55+
*
56+
* @see dotty.tools.languageserver.util.actions.CodeDefinition
57+
*/
58+
def highlight(range: CodeRange, expected: (CodeRange, String)*): CodeTester =
59+
doAction(new CodeDocumentHighlight(range, expected))
2660

27-
def references(range: CodeRange, refs: List[CodeRange], withDecl: Boolean = false): CodeTester =
28-
doAction(new CodeReferences(range, refs, withDecl))
61+
/**
62+
* Finds all the references to the symbol in `range`, verifies that the results match `expected`.
63+
*
64+
* @param range The range of positions from which search for references.
65+
* @param expected The expected positions of the references
66+
* @param withDecl When set, include the declaration of the symbol under `range` in the results.
67+
* @return This `CodeTester` after performing the action.
68+
*
69+
* @see dotty.tools.languageserver.util.actions.CodeReferences
70+
*/
71+
def references(range: CodeRange, expected: List[CodeRange], withDecl: Boolean = false): CodeTester =
72+
doAction(new CodeReferences(range, expected, withDecl))
2973

30-
def completion(marker: CodeMarker, completions: List[(String, String, String)]): CodeTester =
31-
doAction(new CodeCompletion(marker, completions))
74+
/**
75+
* Requests completion at the position defined by `marker`, verifies that the results match
76+
* `expected`.
77+
*
78+
* @param marker The position from which to ask for completions.
79+
* @param expected The expected completion results.
80+
* @return This `CodeTester` after performing the action.
81+
*
82+
* @see dotty.tools.languageserver.util.actions.CodeCompletion
83+
*/
84+
def completion(marker: CodeMarker, expected: List[(String, String, String)]): CodeTester =
85+
doAction(new CodeCompletion(marker, expected))
3286

87+
/**
88+
* Performs a workspace-wide renaming of the symbol under `marker`, verifies that the positions to
89+
* update match `expected`.
90+
*
91+
* @param marker The position from which to ask for renaming.
92+
* @param newName The new name to give to the symbol.
93+
* @param expected The expected list of positions to change.
94+
* @return This `CodeTester` after performing the action.
95+
*
96+
* @see dotty.tools.languageserver.util.actions.CodeRename
97+
*/
3398
def rename(marker: CodeMarker, newName: String, expected: List[CodeRange]): CodeTester =
3499
doAction(new CodeRename(marker, newName, expected)) // TODO apply changes to the sources and positions
35100

36-
def documentSymbol(marker: CodeMarker, symbols: SymInfo*): CodeTester =
37-
doAction(new CodeDocumentSymbol(marker, symbols))
101+
/**
102+
* Queries for all the symbols referenced in the source file in `marker`, verifies that they match
103+
* `expected`.
104+
*
105+
* @param marker The marker defining the source file from which to query.
106+
* @param expected The expected symbols to be found.
107+
* @return This `CodeTester` after performing the action.
108+
*
109+
* @see dotty.tools.languageserver.util.actions.CodeDocumentSymbol
110+
*/
111+
def documentSymbol(marker: CodeMarker, expected: SymInfo*): CodeTester =
112+
doAction(new CodeDocumentSymbol(marker, expected))
38113

114+
/**
115+
* Queries the whole workspace for symbols matching `query`, verifies that the results match
116+
* `expected`.
117+
*
118+
* @param query The query used to find symbols.
119+
* @param expected The expected symbols to be found.
120+
* @return This `CodeTester` after performing the action.
121+
*
122+
* @see dotty.tools.languageserver.util.actions.CodeSymbol
123+
*/
39124
def symbol(query: String, symbols: SymInfo*): CodeTester =
40125
doAction(new CodeSymbol(query, symbols))
41126

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,20 @@ import dotty.tools.languageserver.util.server.TestServer
66

77
import PositionContext._
88

9+
/**
10+
* Base trait for representing an action performed against a language server (such as hover, go to
11+
* definition, etc.)
12+
*/
913
trait Action {
1014
type Exec[T] = implicit (TestServer, PositionContext) => T
15+
16+
/** Execute the action. */
1117
def execute(): Exec[Unit]
18+
19+
/** Return a textual representation of this action. */
1220
def show: PosCtx[String]
21+
22+
/** The server that this action targets. */
1323
def server: Exec[DottyLanguageServer] = implicitly[TestServer].server
1424

1525
// FIXME

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package dotty.tools.languageserver.util.actions
22

33
import dotty.tools.languageserver.util.embedded.CodeMarker
44

5+
/** An action that defines a `marker` where the action will be performed. */
56
trait ActionOnMarker extends Action {
67

8+
/** The marker that defines where the action will be performed. */
79
def marker: CodeMarker
810

911
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ package dotty.tools.languageserver.util.actions
33
import dotty.tools.languageserver.util.{CodeRange, PositionContext}
44
import dotty.tools.languageserver.util.embedded.CodeMarker
55

6+
/** An action that executes on a range. */
67
trait ActionOnRange extends Action {
78

9+
/** The range on which the action is performed. */
810
def range: CodeRange
11+
12+
/** The action to perform for every point of the range. */
913
def onMarker(marker: CodeMarker): Exec[Unit]
1014

11-
def execute(): Exec[Unit] = {
15+
override def execute(): Exec[Unit] = {
1216
val posCtx = implicitly[PositionContext]
1317
range.check()
1418
val file = range.file

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,21 @@ import dotty.tools.languageserver.util.server.TestFile
66

77
import scala.collection.JavaConverters._
88

9-
class CodeCompletion(val marker: CodeMarker, completions: List[(String, String, String)]) extends ActionOnMarker {
9+
/**
10+
* An action requesting for code completion at `marker`, expecting `completions`.
11+
* This action corresponds to the `textDocument/completion` method of the Language Server Protocol.
12+
*
13+
* @param marker The marker indicating the position where completion should be requested.
14+
* @param completions The expected results from the language server.
15+
*/
16+
class CodeCompletion(override val marker: CodeMarker,
17+
completions: List[(String, String, String)]) extends ActionOnMarker {
1018

1119
override def execute(): Exec[Unit] = {
12-
val res = server.completion(marker.toTextDocumentPositionParams).get()
13-
assert(res.isRight, res)
14-
val cList = res.getRight
15-
assert(!cList.isIncomplete, res)
20+
val result = server.completion(marker.toTextDocumentPositionParams).get()
21+
assert(result.isRight, result)
22+
val cList = result.getRight
23+
assert(!cList.isIncomplete, result)
1624
completions.foreach { completion =>
1725
assert(
1826
cList.getItems.asScala.exists(item =>

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,14 @@ package dotty.tools.languageserver.util.actions
33
import dotty.tools.languageserver.util._
44
import dotty.tools.languageserver.util.embedded.CodeMarker
55

6-
class CodeDefinition(val range: CodeRange, expected: Seq[CodeRange]) extends ActionOnRange {
6+
/**
7+
* An action requesting for the definition of the symbol inside `range`.
8+
* This action corresponds to the `textDocument/definition` method of the Language Server Protocol.
9+
*
10+
* @param range The range of positions for which to request the definition.
11+
* @param expected The expected results.
12+
*/
13+
class CodeDefinition(override val range: CodeRange, expected: Seq[CodeRange]) extends ActionOnRange {
714

815
override def onMarker(marker: CodeMarker): Exec[Unit] = {
916
val results = server.definition(fix(marker.toTextDocumentPositionParams)).get()

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

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,31 @@ import org.eclipse.lsp4j._
66

77
import scala.collection.JavaConverters._
88

9-
class CodeDocumentHighlight(val range: CodeRange, highs: Seq[(CodeRange, String)]) extends ActionOnRange {
9+
/**
10+
* An action requesting for the ranges that should be highlighted, when a position within `range`
11+
* is selected.
12+
* This action corresponds to the `textDocument/documentHighlight` method of the Language Server
13+
* Protocol.
14+
*
15+
* @param range The range to of positions to test.
16+
* @param expected The expected results.
17+
*/
18+
class CodeDocumentHighlight(override val range: CodeRange,
19+
expected: Seq[(CodeRange, String)]) extends ActionOnRange {
1020

1121
override def onMarker(marker: CodeMarker): Exec[Unit] = {
12-
val (refs, kinds) = highs.unzip
13-
val res = server.documentHighlight(fix(marker.toTextDocumentPositionParams)).get()
14-
assert(res.size() == refs.size, res)
15-
assert(refs.size == kinds.length, res)
16-
res.asScala.zip(refs).zip(kinds).foreach { case ((dhl, ref), kind) =>
17-
assert(dhl.getKind == DocumentHighlightKind.valueOf(kind), res)
18-
assert(dhl.getRange == ref.toRange, res)
22+
val (references, kinds) = expected.unzip
23+
val results = server.documentHighlight(fix(marker.toTextDocumentPositionParams)).get()
24+
assert(results.size() == references.size, results)
25+
assert(references.size == kinds.length, results)
26+
results.asScala.zip(references).zip(kinds).foreach { case ((dhl, ref), kind) =>
27+
assert(dhl.getKind == DocumentHighlightKind.valueOf(kind), results)
28+
assert(dhl.getRange == ref.toRange, results)
1929
}
2030
}
2131

2232
override def show: PositionContext.PosCtx[String] = {
23-
val (refs, kinds) = highs.unzip
24-
s"CodeDocumentHighlight(${range.show}, ${refs.map(_.show)}, $kinds)"
33+
val (references, kinds) = expected.unzip
34+
s"CodeDocumentHighlight(${range.show}, ${references.map(_.show)}, $kinds)"
2535
}
2636
}

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,24 @@ import dotty.tools.languageserver.util.{PositionContext, SymInfo}
55

66
import scala.collection.JavaConverters._
77

8-
class CodeDocumentSymbol(val marker: CodeMarker, symbols: Seq[SymInfo]) extends ActionOnMarker {
8+
/**
9+
* An action requesting for the symbols found in the document matching `marker`.
10+
* This action corresponds to the `textDocument/documentSymbol` method of the Language Server
11+
* Protocol.
12+
*
13+
* @param marker The marker that identifies the document for which to request the symbols.
14+
* @param expected The expected symbols to receive.
15+
*/
16+
class CodeDocumentSymbol(override val marker: CodeMarker, expected: Seq[SymInfo]) extends ActionOnMarker {
917

1018
override def execute(): Exec[Unit] = {
11-
val res = server.documentSymbol(marker.toDocumentSymbolParams).get()
12-
assert(res.size() == symbols.size, res)
13-
for ((symInfo, expected) <- res.asScala.zip(symbols)) {
14-
assert(symInfo == expected.toSymInformation, res)
19+
val results = server.documentSymbol(marker.toDocumentSymbolParams).get()
20+
assert(results.size == expected.size, results)
21+
for ((symInfo, expected) <- results.asScala.zip(expected)) {
22+
assert(symInfo == expected.toSymInformation, results)
1523
}
1624
}
1725

1826
override def show: PositionContext.PosCtx[String] =
19-
s"CodeDocumentSymbol(${marker.show}, ${symbols.map(_.show)})"
27+
s"CodeDocumentSymbol(${marker.show}, ${expected.map(_.show)})"
2028
}

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

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,27 @@ import org.eclipse.lsp4j._
77

88
import PositionContext._
99

10-
class CodeHover(val range: CodeRange, expected: String) extends ActionOnRange {
10+
/**
11+
* An action requesting for the info shown when `range` is hovered.
12+
* This action corresponds to the `textDocument/hover` method of the Language Server Protocol.
13+
*
14+
* @param range The range of positions that should be hovered.
15+
* @param expected The expected result.
16+
*/
17+
class CodeHover(override val range: CodeRange, expected: String) extends ActionOnRange {
1118

1219
override def onMarker(marker: CodeMarker): Exec[Unit] = {
13-
val res = server.hover(fix(marker.toTextDocumentPositionParams)).get()
14-
assert(res.getRange == null)
15-
if (expected == "") assert(res.getContents == null, "Expected null contents in " + res)
20+
val result = server.hover(fix(marker.toTextDocumentPositionParams)).get()
21+
assert(result.getRange == null)
22+
if (expected == "") assert(result.getContents == null, "Expected null contents in " + result)
1623
else {
17-
assert(res.getContents.size() == 1, res)
18-
val content = res.getContents.get(0)
24+
assert(result.getContents.size() == 1, result)
25+
val content = result.getContents.get(0)
1926
assert(content.isLeft, "Expected left but was " + content)
2027
assert(content.getLeft == expected, s"Expected $expected but was ${content.getLeft}")
2128
}
2229
}
2330

2431
override def show: PositionContext.PosCtx[String] =
25-
s"CodeHover(${range.show}, $expected"
32+
s"CodeHover(${range.show}, $expected)"
2633
}

0 commit comments

Comments
 (0)