Skip to content

Commit

Permalink
adds extension/tasks which returns all nimble tasks for the current…
Browse files Browse the repository at this point in the history
… project
  • Loading branch information
jmgomez committed Oct 10, 2024
1 parent 5ccf289 commit e647b79
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 31 deletions.
1 change: 1 addition & 0 deletions nimlangserver.nim
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ proc registerRoutes(srv: RpcSocketServer, ls: LanguageServer) =
srv.register("extension/status", wrapRpc(partial(status, ls)))
srv.register("extension/capabilities", wrapRpc(partial(extensionCapabilities, ls)))
srv.register("extension/suggest", wrapRpc(partial(extensionSuggest, ls)))
srv.register("extension/tasks", wrapRpc(partial(tasks, ls)))

#Notifications
srv.register("$/cancelRequest", wrapRpc(partial(cancelRequest, ls)))
Expand Down
4 changes: 4 additions & 0 deletions protocol/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1030,3 +1030,7 @@ type

SuggestResult* = object
actionPerformed*: SuggestAction

NimbleTask* = object
name*: string
description*: string
25 changes: 25 additions & 0 deletions routes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,31 @@ proc exit*(
result = newJNull()
await p.onExit()

proc tasks*(
ls: LanguageServer, conf: JsonNode
): Future[seq[NimbleTask]] {.async, gcsafe.} =
let rootPath: string = ls.initializeParams.getRootPath

debug "Received tasks ", rootPath = rootPath
delEnv "NIMBLE_DIR"
let process = await startProcess(
"nimble",
arguments = @["tasks"],
options = {UsePath},
workingDir = rootPath,
stdoutHandle = AsyncProcess.Pipe,
stderrHandle = AsyncProcess.Pipe,
)
#can you see this?
let res =
await process.waitForExit(InfiniteDuration) #TODO handle error (i.e. no nimble file)
let output = await process.stdoutStream.readLine()
echo output.splitLines.toSeq
var name, desc: string
for line in output.splitLines:
if scanf(line, "$+ $*", name, desc):
result.add NimbleTask(name: name.strip(), description: desc.strip())

#Notifications
proc initialized*(ls: LanguageServer, _: JsonNode): Future[void] {.async.} =
debug "Client initialized."
Expand Down
7 changes: 7 additions & 0 deletions tests/projects/tasks/src/tasks.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This is just an example to get you started. A typical hybrid package
# uses this file as the main entry point of the application.

import tasks/submodule

when isMainModule:
echo(getWelcomeMessage())
6 changes: 6 additions & 0 deletions tests/projects/tasks/src/tasks/submodule.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# This is just an example to get you started. Users of your hybrid library will
# import this file by writing ``import taskspkg/submodule``. Feel free to rename or
# remove this file altogether. You may create additional modules alongside
# this file as required.

proc getWelcomeMessage*(): string = "Hello, World!"
20 changes: 20 additions & 0 deletions tests/projects/tasks/tasks.nimble
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Package

version = "0.1.0"
author = "jmgomez"
description = "A new awesome nimble package"
license = "MIT"
srcDir = "src"
installExt = @["nim"]
bin = @["tasks"]


# Dependencies

requires "nim >= 2.1.99"

task helloWorld, "hello world":
echo "helo world"

task anotherTask, "Another task":
echo "another task"
1 change: 1 addition & 0 deletions tests/projects/tasks/tests/config.nims
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
switch("path", "$projectDir/../src")
12 changes: 12 additions & 0 deletions tests/projects/tasks/tests/test1.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This is just an example to get you started. You may wish to put all of your
# tests into a single file, or separate them into multiple `test1`, `test2`
# etc. files (better names are recommended, just make sure the name starts with
# the letter 't').
#
# To run these tests, simply execute `nimble test`.

import unittest

import tasks/submodule
test "correct welcome":
check getWelcomeMessage() == "Hello, World!"
82 changes: 51 additions & 31 deletions tests/textensions.nim
Original file line number Diff line number Diff line change
@@ -1,60 +1,80 @@
import ../[
nimlangserver, ls, lstransports, utils
]
import ../[nimlangserver, ls, lstransports, utils]
import ../protocol/[enums, types]
import std/[options, unittest, json, os, jsonutils, sequtils, strutils, sugar, strformat]
import
std/[options, unittest, json, os, jsonutils, sequtils, strutils, sugar, strformat]
import json_rpc/[rpcclient]
import chronicles
import lspsocketclient
import chronos/asyncproc


suite "Nimlangserver":
let cmdParams = CommandLineParams(transport: some socket, port: getNextFreePort())
let ls = main(cmdParams) #we could accesss to the ls here to test against its state
let client = newLspSocketClient()
waitFor client.connect("localhost", cmdParams.port)
client.registerNotification(
"window/showMessage",
"window/workDoneProgress/create",
"workspace/configuration",
"extension/statusUpdate",
"textDocument/publishDiagnostics",
"$/progress"
)

"window/showMessage", "window/workDoneProgress/create", "workspace/configuration",
"extension/statusUpdate", "textDocument/publishDiagnostics", "$/progress",
)

test "calling extension/suggest with restart in the project uri should restart nimsuggest":
let initParams = InitializeParams %* {
let initParams =
InitializeParams %* {
"processId": %getCurrentProcessId(),
"rootUri": fixtureUri("projects/hw/"),
"capabilities": {
"window": {
"workDoneProgress": true
},
"workspace": {"configuration": true}
}
}
"capabilities":
{"window": {"workDoneProgress": true}, "workspace": {"configuration": true}},
}
let initializeResult = waitFor client.initialize(initParams)

check initializeResult.capabilities.textDocumentSync.isSome

let helloWorldUri = fixtureUri("projects/hw/hw.nim")
let helloWorldFile = "projects/hw/hw.nim"
let helloWorldFile = "projects/hw/hw.nim"
let hwAbsFile = uriToPath(helloWorldFile.fixtureUri())
client.notify("textDocument/didOpen", %createDidOpenParams(helloWorldFile))

let progressParam = %ProgressParams(token: fmt "Creating nimsuggest for {hwAbsFile}")
check waitFor client.waitForNotification("$/progress", (json: JsonNode) => progressParam["token"] == json["token"])
check waitFor client.waitForNotification("$/progress", (json: JsonNode) => json["value"]["kind"].getStr == "begin")
check waitFor client.waitForNotification("$/progress", (json: JsonNode) => json["value"]["kind"].getStr == "end")
let progressParam =
%ProgressParams(token: fmt "Creating nimsuggest for {hwAbsFile}")
check waitFor client.waitForNotification(
"$/progress", (json: JsonNode) => progressParam["token"] == json["token"]
)
check waitFor client.waitForNotification(
"$/progress", (json: JsonNode) => json["value"]["kind"].getStr == "begin"
)
check waitFor client.waitForNotification(
"$/progress", (json: JsonNode) => json["value"]["kind"].getStr == "end"
)

client.notify(
"textDocument/didOpen", %createDidOpenParams("projects/hw/useRoot.nim")
)

client.notify("textDocument/didOpen",
%createDidOpenParams("projects/hw/useRoot.nim"))

let prevSuggestPid = ls.projectFiles[hwAbsFile].process.pid
let suggestParams = SuggestParams(action: saRestart, projectFile: hwAbsFile)
let suggestRes = client.call("extension/suggest", %suggestParams).waitFor
let suggestPid = ls.projectFiles[hwAbsFile].process.pid

check prevSuggestPid != suggestPid


test "calling extension/tasks should return all existing tasks":
let initParams =
InitializeParams %* {
"processId": %getCurrentProcessId(),
"rootUri": fixtureUri("projects/tasks/"),
"capabilities":
{"window": {"workDoneProgress": true}, "workspace": {"configuration": true}},
}
let initializeResult = waitFor client.initialize(initParams)

let tasksFile = "projects/tasks/src/tasks.nim"
let taskAbsFile = uriToPath(tasksFile.fixtureUri())
client.notify("textDocument/didOpen", %createDidOpenParams(tasksFile))

let tasks = client.call("extension/tasks", jsonutils.toJson(())).waitFor().jsonTo(
seq[NimbleTask]
)

check tasks.len == 2
check tasks[0].name == "helloWorld"
check tasks[0].description == "hello world"

0 comments on commit e647b79

Please sign in to comment.