Skip to content

Commit 57ae7fd

Browse files
authored
Projectsetup (#204)
* Fixes an issue where it keep looking for the `nimble` project even though it found one already. * adds `tprojectsetup.nim` test * hook tprojectsetup
1 parent cef1af9 commit 57ae7fd

File tree

3 files changed

+187
-1
lines changed

3 files changed

+187
-1
lines changed

nimlangserver.nim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ proc getNimbleDumpInfo(ls: LanguageServer, nimbleFile: string): NimbleDumpInfo =
165165

166166
proc getProjectFileAutoGuess(ls: LanguageServer, fileUri: string): string =
167167
let file = fileUri.decodeUrl
168+
debug "Auto-guessing project file for", file = file
168169
result = file
169170
let (dir, _, _) = result.splitFile()
170171
var
@@ -193,6 +194,7 @@ proc getProjectFileAutoGuess(ls: LanguageServer, fileUri: string): string =
193194
debug "Found nimble project", projectFile = projectFile
194195
result = projectFile
195196
certainty = Nimble
197+
return
196198
if path == dir: break
197199
path = dir
198200

tests/all.nim

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
import
2-
tnimlangserver, tsuggestapi
2+
tnimlangserver, tsuggestapi,
3+
tprojectsetup

tests/tprojectsetup.nim

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
2+
#setup a new nimble project
3+
import std/[unittest, osproc, os, sequtils, sugar, strutils]
4+
import
5+
../nimlangserver,
6+
../protocol/types,
7+
../utils,
8+
faststreams/async_backend,
9+
faststreams/asynctools_adapters,
10+
json_rpc/jsonmarshal,
11+
json_rpc/streamconnection,
12+
chronicles,
13+
std/json,
14+
strformat,
15+
sugar,
16+
unittest
17+
18+
template cd*(dir: string, body: untyped) =
19+
## Sets the current dir to ``dir``, executes ``body`` and restores the
20+
## previous working dir.
21+
let lastDir = getCurrentDir()
22+
setCurrentDir(dir)
23+
block:
24+
defer: setCurrentDir(lastDir)
25+
body
26+
27+
template createNewDir*(dir: string) =
28+
removeDir dir
29+
createDir dir
30+
31+
template cdNewDir*(dir: string, body: untyped) =
32+
createNewDir dir
33+
cd dir:
34+
body
35+
36+
37+
let
38+
rootDir = getCurrentDir()
39+
nimblePath* = findExe "nimble"
40+
installDir* = rootDir / "tests" / "nimbleDir"
41+
42+
type
43+
ProcessOutput* = tuple[output: string, exitCode: int]
44+
45+
46+
proc execNimble*(args: varargs[string]): ProcessOutput =
47+
var quotedArgs = @args
48+
if not args.anyIt("--nimbleDir:" in it or "-l" == it or "--local" == it):
49+
quotedArgs.insert("--nimbleDir:" & installDir)
50+
quotedArgs.insert(nimblePath)
51+
quotedArgs = quotedArgs.map((x: string) => x.quoteShell)
52+
53+
let path {.used.} = getCurrentDir().parentDir() / "src"
54+
55+
var cmd =
56+
when not defined(windows):
57+
"PATH=" & path & ":$PATH " & quotedArgs.join(" ")
58+
else:
59+
quotedArgs.join(" ")
60+
when defined(macosx):
61+
# TODO: Yeah, this is really specific to my machine but for my own sanity...
62+
cmd = "DYLD_LIBRARY_PATH=/usr/local/opt/openssl@1.1/lib " & cmd
63+
64+
result = execCmdEx(cmd)
65+
checkpoint(cmd)
66+
checkpoint(result.output)
67+
68+
proc execNimbleYes*(args: varargs[string]): ProcessOutput =
69+
execNimble(@args & "-y")
70+
71+
#TODO extract testutils and reusue this functions in both, tnimlangserver and this file
72+
73+
var notificationOutputs = newJArray()
74+
75+
proc registerHandlers*(connection: StreamConnection,
76+
pipeInput: AsyncInputStream,
77+
storageDir: string): LanguageServer =
78+
registerHandlers(connection, pipeInput, storageDir, CommandLineParams())
79+
80+
proc testHandler[T, Q](input: tuple[fut: FutureStream[T], res: Q], arg: T):
81+
Future[Q] {.async, gcsafe.} =
82+
debug "Received call: ", arg = %arg
83+
discard input.fut.write(arg)
84+
return input.res
85+
86+
proc testHandler[T](fut: FutureStream[T], arg: T): Future[void] {.async, gcsafe.} =
87+
debug "Received notification: ", arg = %arg
88+
{.cast(gcsafe).}:
89+
notificationOutputs.add %arg
90+
discard fut.write(arg)
91+
92+
proc fixtureUri(path: string): string =
93+
result = pathToUri(getCurrentDir() / "tests" / path)
94+
95+
proc createDidOpenParams(file: string): DidOpenTextDocumentParams =
96+
return DidOpenTextDocumentParams %* {
97+
"textDocument": {
98+
"uri": pathToUri(file),
99+
"languageId": "nim",
100+
"version": 0,
101+
"text": readFile(file)
102+
}
103+
}
104+
105+
suite "nimble setup":
106+
107+
test "should pick `testproject.nim` as the main file":
108+
let testProjectDir = absolutePath "tests" / "projects" / "testproject"
109+
let entryPoint = testProjectDir / "src" / "testproject.nim"
110+
cdNewDir testProjectDir:
111+
let (output, exitCode) = execNimbleYes("init")
112+
check exitCode == 0
113+
114+
let pipeServer = createPipe();
115+
let pipeClient = createPipe();
116+
117+
let
118+
server = StreamConnection.new(pipeServer)
119+
inputPipe = asyncPipeInput(pipeClient)
120+
storageDir = ensureStorageDir()
121+
122+
discard registerHandlers(server, inputPipe, storageDir);
123+
discard server.start(inputPipe);
124+
125+
let client = StreamConnection.new(pipeClient);
126+
discard client.start(asyncPipeInput(pipeServer));
127+
128+
let suggestInit = FutureStream[ProgressParams]()
129+
client.register("window/workDoneProgress/create",
130+
partial(testHandler[ProgressParams, JsonNode],
131+
(fut: suggestInit, res: newJNull())))
132+
let workspaceConfiguration = %* [{
133+
"workingDirectoryMapping": [{
134+
"directory": testProjectDir,
135+
"file": entryPoint,
136+
"projectFile": entryPoint
137+
}],
138+
"autoCheckFile": false,
139+
"autoCheckProject": false
140+
}]
141+
142+
let configInit = FutureStream[ConfigurationParams]()
143+
client.register(
144+
"workspace/configuration",
145+
partial(testHandler[ConfigurationParams, JsonNode],
146+
(fut: configInit, res: workspaceConfiguration)))
147+
148+
let diagnostics = FutureStream[PublishDiagnosticsParams]()
149+
client.registerNotification(
150+
"textDocument/publishDiagnostics",
151+
partial(testHandler[PublishDiagnosticsParams], diagnostics))
152+
153+
let progress = FutureStream[ProgressParams]()
154+
client.registerNotification(
155+
"$/progress",
156+
partial(testHandler[ProgressParams], progress))
157+
158+
let showMessage = FutureStream[ShowMessageParams]()
159+
client.registerNotification(
160+
"window/showMessage",
161+
partial(testHandler[ShowMessageParams], showMessage))
162+
163+
let initParams = InitializeParams %* {
164+
"processId": %getCurrentProcessId(),
165+
"capabilities": {
166+
"window": {
167+
"workDoneProgress": true
168+
},
169+
"workspace": {"configuration": true}
170+
}
171+
}
172+
173+
discard waitFor client.call("initialize", %initParams)
174+
client.notify("initialized", newJObject())
175+
# #At this point we should know the main file is `testproject.nim` but for now just test the case were we open it
176+
client.notify("textDocument/didOpen", %createDidOpenParams(entryPoint))
177+
let (_, params) = suggestInit.read.waitFor
178+
# echo "aqui"
179+
let nimsuggestNot = notificationOutputs[^1]["value"]["title"].getStr
180+
check nimsuggestNot == &"Creating nimsuggest for {entryPoint}"
181+
182+
183+

0 commit comments

Comments
 (0)