@@ -18,13 +18,16 @@ package tests.core
1818
1919import scala .concurrent .duration .*
2020
21+ import langoustine .testkit .*
22+
2123import cats .effect .IO
2224import jsonrpclib .fs2 .catsMonadic
2325import jsonrpclib .{fs2 as _ , * }
2426import langoustine .lsp .*
2527import langoustine .lsp .all .*
2628import langoustine .lsp .structures .InitializeParams .ClientInfo
2729import langoustine .lsp .structures .InitializeResult .ServerInfo
30+ import cats .syntax .all .*
2831
2932object LSPTests extends weaver.SimpleIOSuite :
3033
@@ -138,6 +141,56 @@ object LSPTests extends weaver.SimpleIOSuite:
138141
139142 }
140143
144+ serverTest(" cancellation" ) { log =>
145+ import requests .*
146+
147+ val NumParallelCalls = 5
148+
149+ IO .ref(Set .empty[CallId .StringId ])
150+ .parProduct(cats.effect.std.CountDownLatch [IO ](NumParallelCalls ))
151+ .flatMap: (cancelled, latch) =>
152+ val server = basicServer.handleRequest(textDocument.documentSymbol) {
153+ in =>
154+ log.info(s " in handler for ${in.params.textDocument.uri}" ) *>
155+ IO .never
156+ .onCancel(
157+ log.info(
158+ s " Cancelled ${in.params.textDocument.uri}"
159+ ) *>
160+ cancelled.update(
161+ _ + CallId .StringId (in.params.textDocument.uri.value)
162+ ) *>
163+ latch.release
164+ )
165+ .as(None )
166+ }
167+
168+ Probe
169+ .create(server, log)
170+ .use: probe =>
171+ val requests = List .tabulate(NumParallelCalls ): i =>
172+ val callID = CallId .StringId (s " document $i" )
173+ probe
174+ .requestAndForget(
175+ callID,
176+ textDocument.documentSymbol,
177+ DocumentSymbolParams (
178+ TextDocumentIdentifier (
179+ uri = DocumentUri (callID.string)
180+ )
181+ )
182+ )
183+ .as(callID)
184+
185+ for
186+ callIds <- requests.parSequence
187+ _ <- callIds.parTraverse(probe.cancel)
188+ _ <- latch.await.timeout(5 .seconds)
189+ allCancelled <- cancelled.get
190+ yield expect.same(callIds.toSet, allCancelled)
191+ end for
192+ }
193+
141194 serverTest(" documentSymbol" ) { log =>
142195 val symbols : Option [Vector [DocumentSymbol ]] =
143196 Option (
@@ -190,51 +243,3 @@ end LSPTests
190243
191244def basicServer =
192245 LSPBuilder .create[IO ]
193-
194- // test("textDocument/documentSymbol") {
195- // import requests.*
196-
197- // val symbols: Option[Vector[DocumentSymbol]] =
198- // Opt(
199- // Vector(
200- // DocumentSymbol(
201- // name = "root",
202- // kind = SymbolKind.Array,
203- // range = Range(Position(0, 0), Position(0, 5)),
204- // selectionRange = Range(Position(0, 0), Position(0, 5)),
205- // children = Opt(
206- // Vector(
207- // DocumentSymbol(
208- // name = "child",
209- // kind = SymbolKind.String,
210- // range = Range(Position(1, 0), Position(1, 5)),
211- // selectionRange = Range(Position(1, 0), Position(1, 5))
212- // )
213- // )
214- // )
215- // )
216- // )
217- // )
218-
219- // val server = basicServer[Try].handleRequest(textDocument.documentSymbol) {
220- // in =>
221- // Try {
222- // symbols
223- // }
224- // }
225-
226- // val (response, _) = request(
227- // server,
228- // CallId.StringId("resp1"),
229- // textDocument.documentSymbol,
230- // DocumentSymbolParams(
231- // TextDocumentIdentifier(DocumentUri("/home/bla.txt"))
232- // )
233- // ).get
234-
235- // expect.same(
236- // response,
237- // symbols
238- // )
239- // }
240- // end LSPTests
0 commit comments