diff --git a/nimlsp.nimble b/nimlsp.nimble index 75de9f9..1c40b6f 100644 --- a/nimlsp.nimble +++ b/nimlsp.nimble @@ -13,7 +13,6 @@ requires "nim >= 1.0.0" #requires "packedjson" requires "astpatternmatching" requires "jsonschema >= 0.2.1" - # nimble test does not work for me out of the box #task test, "Runs the test suite": #exec "nim c -r tests/test_messages.nim" diff --git a/src/config.nims b/src/config.nims index e06379f..d1860d3 100644 --- a/src/config.nims +++ b/src/config.nims @@ -1,3 +1,23 @@ import os switch "path", getCurrentCompilerExe().parentDir.parentDir +--gc:markAndSweep + +switch "hint","XDeclaredButNotUsed:off" + +--path:"$lib/packages/docutils" + +--define:useStdoutAsStdmsg +--define:nimsuggest +--define:nimcore + +# die when nimsuggest uses more than 4GB: +when defined(cpu32): + switch "define","nimMaxHeap=2000" +else: + switch "define","nimMaxHeap=4000" + +--threads:on +switch "warning","[Spacing]:off" # The JSON schema macro uses a syntax similar to TypeScript +switch "warning","[CaseTransition]:off" +switch "define","nimOldCaseObjects" diff --git a/src/nimlsp.nim b/src/nimlsp.nim index 43cb57f..5d7acd1 100644 --- a/src/nimlsp.nim +++ b/src/nimlsp.nim @@ -1,4 +1,4 @@ -import nimlsppkg / [baseprotocol, utfmapping, suggestlib] +import nimlsppkg / [baseprotocol, utfmapping, suggestlib, logger] include nimlsppkg / messages import streams import tables @@ -9,7 +9,6 @@ import uri import algorithm const - storage = getTempDir() / "nimlsp" version = block: var version = "0.0.0" let nimbleFile = staticRead(currentSourcePath().parentDir().parentDir() / "nimlsp.nimble") @@ -27,21 +26,10 @@ var nimpath = explicitSourcePath discard existsOrCreateDir(storage) -when defined(debugLogging): - var logFile = open(storage / "nimlsp.log", fmWrite) - -template debugEcho(args: varargs[string, `$`]) = - when defined(debugLogging): - stderr.write(join args) - stderr.write("\n") - logFile.write(join args) - logFile.write("\n\n") - logFile.flushFile() - -debugEcho("Version: " & version) -debugEcho("explicitSourcePath: " & explicitSourcePath) +debug("Version: " & version) +debug("explicitSourcePath: " & explicitSourcePath) for i in 1..paramCount(): - debugEcho("Argument " & $i & ": " & paramStr(i)) + debug("Argument " & $i & ": " & paramStr(i)) var ins = newFileStream(stdin) @@ -51,43 +39,41 @@ var projectFiles = initTable[string, tuple[nimsuggest: NimSuggest, openFiles: int]]() openFiles = initTable[string, tuple[projectFile: string, fingerTable: seq[seq[tuple[u16pos, offset: int]]]]]() -template whenValid(data, kind, body) = - if data.isValid(kind, allowExtra = true): - var data = kind(data) - body - else: - debugEcho("Unable to parse data as " & $kind) - -template whenValid(data, kind, body, elseblock) = - if data.isValid(kind, allowExtra = true): - var data = kind(data) - body - else: - elseblock - -template textDocumentRequest(message, kind, name, body) {.dirty.} = +template textDocumentRequest(message, kind, name, body: untyped): untyped = if message["params"].isSome: - let name = message["params"].unsafeGet - whenValid(name, kind): - let - fileuri = name["textDocument"]["uri"].getStr - filestash = storage / (hash(fileuri).toHex & ".nim" ) - debugEcho "Got request for URI: ", fileuri, " copied to " & filestash - when kind isnot DocumentSymbolParams: - let - rawLine = name["position"]["line"].getInt - rawChar = name["position"]["character"].getInt + let p = message["params"].unsafeGet + if p.isValid(kind, allowExtra = true): + var name = kind(p) body + else: + debug("Unable to parse data as " & $kind) + +proc fileuri[T](p:T):string = + p["textDocument"]["uri"].getStr -template textDocumentNotification(message, kind, name, body) {.dirty.} = +proc filePath[T](p:T):string = + p.fileuri[7..^1] + +proc filestash[T](p:T):string = + storage / (hash(p.fileuri).toHex & ".nim" ) + +proc rawLine[T](p:T):int = + p["position"]["line"].getInt + +proc rawChar[T](p:T):int = + p["position"]["character"].getInt + +proc col[T](openFiles:Table[string, tuple[projectFile: string, fingerTable: seq[seq[tuple[u16pos, offset: int]]]]];p:T):int= + openFiles[p.fileuri].fingerTable[p.rawLine].utf16to8(p.rawChar) + +template textDocumentNotification(message, kind, name, body: untyped): untyped = if message["params"].isSome: - let name = message["params"].unsafeGet - whenValid(name, kind): - if not name["textDocument"].hasKey("languageId") or name["textDocument"]["languageId"].getStr == "nim": - let - fileuri = name["textDocument"]["uri"].getStr - filestash = storage / (hash(fileuri).toHex & ".nim" ) - body + var p = message["params"].unsafeGet + if p.isValid(kind, allowExtra = true): + var name = kind(p) + body + else: + debug("Unable to parse data as " & $kind) proc pathToUri(path: string): string = # This is a modified copy of encodeUrl in the uri module. This doesn't encode @@ -164,7 +150,8 @@ if paramCount() == 1: of "--version": echo "nimlsp v", version quit 0 - else: nimpath = expandFilename(paramStr(1)) + else: + nimpath = expandFilename(paramStr(1)) if not fileExists(nimpath / "config/nim.cfg"): stderr.write "Unable to find \"config/nim.cfg\" in \"" & nimpath & "\". " & "Supply the Nim project folder by adding it as an argument.\n" @@ -172,22 +159,22 @@ if not fileExists(nimpath / "config/nim.cfg"): while true: try: - debugEcho "Trying to read frame" + debug "Trying to read frame" let frame = ins.readFrame - debugEcho "Got frame:\n" & frame - let message = frame.parseJson - whenValid(message, RequestMessage): - debugEcho "Got valid Request message of type " & message["method"].getStr + let msg = frame.parseJson + if msg.isValid(RequestMessage): + let message = RequestMessage(msg) + debug "Got valid Request message of type " & message["method"].getStr if not initialized and message["method"].getStr != "initialize": message.error(-32002, "Unable to accept requests before being initialized", newJNull()) continue case message["method"].getStr: of "shutdown": - debugEcho "Got shutdown request, answering" + debug "Got shutdown request, answering" message.respond(newJNull()) gotShutdown = true of "initialize": - debugEcho "Got initialize request, answering" + debug "Got initialize request, answering" initialized = true message.respond(create(InitializeResult, create(ServerCapabilities, textDocumentSync = some(create(TextDocumentSyncOptions, @@ -215,7 +202,7 @@ while true: workspaceSymbolProvider = none(bool), #?: bool codeActionProvider = none(bool), #?: bool codeLensProvider = none(CodeLensOptions), #?: CodeLensOptions - documentFormattingProvider = none(bool), #?: bool + documentFormattingProvider = some(false), #?: bool documentRangeFormattingProvider = none(bool), #?: bool documentOnTypeFormattingProvider = none(DocumentOnTypeFormattingOptions), #?: DocumentOnTypeFormattingOptions renameProvider = some(true), #?: bool @@ -227,14 +214,14 @@ while true: )).JsonNode) of "textDocument/completion": message.textDocumentRequest(CompletionParams, compRequest): - debugEcho "Running equivalent of: sug ", fileuri[7..^1], ";", filestash, ":", - rawLine + 1, ":", - openFiles[fileuri].fingerTable[rawLine].utf16to8(rawChar) - let suggestions = getNimsuggest(fileuri).sug(fileuri[7..^1], dirtyfile = filestash, - rawLine + 1, - openFiles[fileuri].fingerTable[rawLine].utf16to8(rawChar) + debug "Running equivalent of: sug ", compRequest.filePath, ";", compRequest.filestash, ":", + compRequest.rawLine + 1, ":", + openFiles.col(compRequest) + let suggestions = getNimsuggest(compRequest.fileuri).sug(compRequest.filePath, dirtyfile = compRequest.filestash, + compRequest.rawLine + 1, + openFiles.col(compRequest) ) - debugEcho "Found suggestions: ", + debug "Found suggestions: ", suggestions[0..(if suggestions.len > 10: 10 else: suggestions.high)], (if suggestions.len > 10: " and " & $(suggestions.len-10) & " more" else: "") var completionItems = newJarray() @@ -243,7 +230,7 @@ while true: label = suggestion.qualifiedPath[^1], kind = some(nimSymToLSPKind(suggestion).int), detail = some(nimSymDetails(suggestion)), - documentation = some(suggestion.nimDocstring), + documentation = some(suggestion.doc), deprecated = none(bool), preselect = none(bool), sortText = none(string), @@ -259,14 +246,14 @@ while true: message.respond completionItems of "textDocument/hover": message.textDocumentRequest(TextDocumentPositionParams, hoverRequest): - debugEcho "Running equivalent of: def ", fileuri[7..^1], ";", filestash, ":", - rawLine + 1, ":", - openFiles[fileuri].fingerTable[rawLine].utf16to8(rawChar) - let suggestions = getNimsuggest(fileuri).def(fileuri[7..^1], dirtyfile = filestash, - rawLine + 1, - openFiles[fileuri].fingerTable[rawLine].utf16to8(rawChar) + debug "Running equivalent of: def ", hoverRequest.filePath, ";", hoverRequest.filestash, ":", + hoverRequest.rawLine + 1, ":", + openFiles.col(hoverRequest) + let suggestions = getNimsuggest(hoverRequest.fileuri).def(hoverRequest.filePath, dirtyfile = hoverRequest.filestash, + hoverRequest.rawLine + 1, + openFiles.col(hoverRequest) ) - debugEcho "Found suggestions: ", + debug "Found suggestions: ", suggestions[0..(if suggestions.len > 10: 10 else: suggestions.high)], (if suggestions.len > 10: " and " & $(suggestions.len-10) & " more" else: "") if suggestions.len == 0: @@ -278,15 +265,15 @@ while true: let rangeopt = some(create(Range, - create(Position, rawLine, rawChar), - create(Position, rawLine, rawChar + suggestions[0].qualifiedPath[^1].len) + create(Position, hoverRequest.rawLine, hoverRequest.rawChar), + create(Position, hoverRequest.rawLine, hoverRequest.rawChar + suggestions[0].qualifiedPath[^1].len) )) markedString = create(MarkedStringOption, "nim", label) if suggestions[0].doc != "": message.respond create(Hover, @[ markedString, - create(MarkedStringOption, "", suggestions[0].nimDocstring), + create(MarkedStringOption, "", suggestions[0].doc), ], rangeopt ).JsonNode @@ -294,14 +281,14 @@ while true: message.respond create(Hover, markedString, rangeopt).JsonNode of "textDocument/references": message.textDocumentRequest(ReferenceParams, referenceRequest): - debugEcho "Running equivalent of: use ", fileuri[7..^1], ";", filestash, ":", - rawLine + 1, ":", - openFiles[fileuri].fingerTable[rawLine].utf16to8(rawChar) - let suggestions = getNimsuggest(fileuri).use(fileuri[7..^1], dirtyfile = filestash, - rawLine + 1, - openFiles[fileuri].fingerTable[rawLine].utf16to8(rawChar) + debug "Running equivalent of: use ", referenceRequest.filePath, ";", referenceRequest.filestash, ":", + referenceRequest.rawLine + 1, ":", + openFiles.col(referenceRequest) + let suggestions = getNimsuggest(referenceRequest.fileuri).use(referenceRequest.filePath, dirtyfile = referenceRequest.filestash, + referenceRequest.rawLine + 1, + openFiles.col(referenceRequest) ) - debugEcho "Found suggestions: ", + debug "Found suggestions: ", suggestions[0..(if suggestions.len > 10: 10 else: suggestions.high)], (if suggestions.len > 10: " and " & $(suggestions.len-10) & " more" else: "") var response = newJarray() @@ -320,14 +307,14 @@ while true: message.respond response of "textDocument/rename": message.textDocumentRequest(RenameParams, renameRequest): - debugEcho "Running equivalent of: use ", fileuri[7..^1], ";", filestash, ":", - rawLine + 1, ":", - openFiles[fileuri].fingerTable[rawLine].utf16to8(rawChar) - let suggestions = getNimsuggest(fileuri).use(fileuri[7..^1], dirtyfile = filestash, - rawLine + 1, - openFiles[fileuri].fingerTable[rawLine].utf16to8(rawChar) + debug "Running equivalent of: use ", renameRequest.filePath, ";", renameRequest.filestash, ":", + renameRequest.rawLine + 1, ":", + openFiles.col(renameRequest) + let suggestions = getNimsuggest(renameRequest.fileuri).use(renameRequest.filePath, dirtyfile = renameRequest.filestash, + renameRequest.rawLine + 1, + openFiles.col(renameRequest) ) - debugEcho "Found suggestions: ", + debug "Found suggestions: ", suggestions[0..(if suggestions.len > 10: 10 else: suggestions.high)], (if suggestions.len > 10: " and " & $(suggestions.len-10) & " more" else: "") if suggestions.len == 0: @@ -350,14 +337,14 @@ while true: ).JsonNode of "textDocument/definition": message.textDocumentRequest(TextDocumentPositionParams, definitionRequest): - debugEcho "Running equivalent of: def ", fileuri[7..^1], ";", filestash, ":", - rawLine + 1, ":", - openFiles[fileuri].fingerTable[rawLine].utf16to8(rawChar) - let declarations = getNimsuggest(fileuri).def(fileuri[7..^1], dirtyfile = filestash, - rawLine + 1, - openFiles[fileuri].fingerTable[rawLine].utf16to8(rawChar) + debug "Running equivalent of: def ", definitionRequest.filePath, ";", definitionRequest.filestash, ":", + definitionRequest.rawLine + 1, ":", + openFiles.col(definitionRequest) + let declarations = getNimsuggest(definitionRequest.fileuri).def(definitionRequest.filePath, dirtyfile = definitionRequest.filestash, + definitionRequest.rawLine + 1, + openFiles.col(definitionRequest) ) - debugEcho "Found suggestions: ", + debug "Found suggestions: ", declarations[0..(if declarations.len > 10: 10 else: declarations.high)], (if declarations.len > 10: " and " & $(declarations.len-10) & " more" else: "") if declarations.len == 0: @@ -375,9 +362,9 @@ while true: message.respond response of "textDocument/documentSymbol": message.textDocumentRequest(DocumentSymbolParams, symbolRequest): - debugEcho "Running equivalent of: outline ", fileuri[7..^1], ";", filestash - let syms = getNimsuggest(fileuri).outline(fileuri[7..^1], dirtyfile = filestash) - debugEcho "Found outlines: ", + debug "Running equivalent of: outline ", symbolRequest.filePath, ";", symbolRequest.filestash + let syms = getNimsuggest(symbolRequest.fileuri).outline(symbolRequest.filePath, dirtyfile = symbolRequest.filestash) + debug "Found outlines: ", syms[0..(if syms.len > 10: 10 else: syms.high)], (if syms.len > 10: " and " & $(syms.len-10) & " more" else: "") if syms.len == 0: @@ -409,85 +396,86 @@ while true: # let # fileuri = signRequest["textDocument"]["uri"].getStr # filestash = storage / (hash(fileuri).toHex & ".nim" ) - # debugEcho "Got signature request for URI: ", fileuri, " copied to " & filestash + # debug "Got signature request for URI: ", fileuri, " copied to " & filestash # let # rawLine = signRequest["position"]["line"].getInt # rawChar = signRequest["position"]["character"].getInt # suggestions = getNimsuggest(fileuri).con(fileuri[7..^1], dirtyfile = filestash, rawLine + 1, rawChar) else: - debugEcho "Unknown request" + debug "Unknown request" continue - whenValid(message, NotificationMessage): - debugEcho "Got valid Notification message of type " & message["method"].getStr + elif msg.isValid(NotificationMessage): + let message = NotificationMessage(msg) + debug "Got valid Notification message of type " & message["method"].getStr if not initialized and message["method"].getStr != "exit": continue case message["method"].getStr: of "exit": - debugEcho "Exiting" + debug "Exiting" if gotShutdown: quit 0 else: quit 1 of "initialized": - debugEcho "Properly initialized" + debug "Properly initialized" of "textDocument/didOpen": message.textDocumentNotification(DidOpenTextDocumentParams, textDoc): let - file = open(filestash, fmWrite) - projectFile = getProjectFile(fileuri[7..^1]) - debugEcho "New document opened for URI: ", fileuri, " saving to " & filestash - openFiles[fileuri] = ( + file = open(textDoc.filestash, fmWrite) + projectFile = getProjectFile(textDoc.filePath) + debug "New document opened for URI: ", textDoc.fileuri, " \nsaving to " & textDoc.filestash + openFiles[textDoc.fileuri] = ( #nimsuggest: initNimsuggest(fileuri[7..^1]), projectFile: projectFile, fingerTable: @[] ) if not projectFiles.hasKey(projectFile): - debugEcho "Initialising project with ", projectFile, ":", nimpath + debug "Initialising project with project file: ", projectFile, "\nnimpath: ", nimpath projectFiles[projectFile] = (nimsuggest: initNimsuggest(projectFile, nimpath), openFiles: 1) else: projectFiles[projectFile].openFiles += 1 for line in textDoc["textDocument"]["text"].getStr.splitLines: - openFiles[fileuri].fingerTable.add line.createUTFMapping() + openFiles[textDoc.fileuri].fingerTable.add line.createUTFMapping() file.writeLine line file.close() of "textDocument/didChange": message.textDocumentNotification(DidChangeTextDocumentParams, textDoc): - let file = open(filestash, fmWrite) - debugEcho "Got document change for URI: ", fileuri, " saving to " & filestash - openFiles[fileuri].fingerTable = @[] + let file = open(textDoc.filestash, fmWrite) + debug "Got document change for URI: ", textDoc.fileuri, " saving to " & textDoc.filestash + openFiles[textDoc.fileuri].fingerTable = @[] for line in textDoc["contentChanges"][0]["text"].getStr.splitLines: - openFiles[fileuri].fingerTable.add line.createUTFMapping() + openFiles[textDoc.fileuri].fingerTable.add line.createUTFMapping() file.writeLine line file.close() of "textDocument/didClose": message.textDocumentNotification(DidCloseTextDocumentParams, textDoc): - let projectFile = getProjectFile(fileuri[7..^1]) - debugEcho "Got document close for URI: ", fileuri, " copied to " & filestash - removeFile(filestash) + let projectFile = getProjectFile(textDoc.filePath) + debug "Got document close for URI: ", textDoc.fileuri, " copied to " & textDoc.filestash + removeFile(textDoc.filestash) projectFiles[projectFile].openFiles -= 1 if projectFiles[projectFile].openFiles == 0: - debugEcho "Trying to stop nimsuggest" - debugEcho "Stopped nimsuggest with code: " & $getNimsuggest(fileuri).stopNimsuggest() - openFiles.del(fileuri) + debug "Trying to stop nimsuggest" + debug "Stopped nimsuggest with code: " & $getNimsuggest(textDoc.fileuri).stopNimsuggest() + openFiles.del(textDoc.fileuri) of "textDocument/didSave": message.textDocumentNotification(DidSaveTextDocumentParams, textDoc): if textDoc["text"].isSome: - let file = open(filestash, fmWrite) - debugEcho "Got document save for URI: ", fileuri, " saving to ", filestash - openFiles[fileuri].fingerTable = @[] + let file = open(textDoc.filestash, fmWrite) + debug "Got document save for URI: ", textDoc.fileuri, " saving to ", textDoc.filestash + openFiles[textDoc.fileuri].fingerTable = @[] for line in textDoc["text"].unsafeGet.getStr.splitLines: - openFiles[fileuri].fingerTable.add line.createUTFMapping() + openFiles[textDoc.fileuri].fingerTable.add line.createUTFMapping() file.writeLine line file.close() - debugEcho "fileuri: ", fileuri, ", project file: ", openFiles[fileuri].projectFile, ", dirtyfile: ", filestash - let diagnostics = getNimsuggest(fileuri).chk(fileuri[7..^1], dirtyfile = filestash) - debugEcho "Got diagnostics: ", + debug "fileuri: ", textDoc.fileuri, ", project file: ", openFiles[textDoc.fileuri].projectFile, ", dirtyfile: ", textDoc.filestash + let diagnostics = getNimsuggest(textDoc.fileuri).chk(textDoc.filePath, dirtyfile = textDoc.filestash) + debug "Got diagnostics: ", diagnostics[0..(if diagnostics.len > 10: 10 else: diagnostics.high)], (if diagnostics.len > 10: " and " & $(diagnostics.len-10) & " more" else: "") if diagnostics.len == 0: notify("textDocument/publishDiagnostics", create(PublishDiagnosticsParams, - fileuri, + textDoc.fileuri, @[]).JsonNode ) else: @@ -495,11 +483,11 @@ while true: for diagnostic in diagnostics: if diagnostic.line == 0: continue - if diagnostic.filePath != fileuri[7..^1]: + if diagnostic.filePath != textDoc.filePath: continue # Try to guess the size of the identifier let - message = diagnostic.nimDocstring + message = diagnostic.doc endcolumn = diagnostic.column + message.rfind('\'') - message.find('\'') - 1 response.add create(Diagnostic, create(Range, @@ -517,14 +505,16 @@ while true: none(seq[DiagnosticRelatedInformation]) ) notify("textDocument/publishDiagnostics", create(PublishDiagnosticsParams, - fileuri, + textDoc.fileuri, response).JsonNode ) else: - debugEcho "Got unknown notification message" + debug "Got unknown notification message" continue + else: + debug "Got unknown message" & frame except IOError: break except CatchableError as e: - debugEcho "Got exception: ", e.msg + debug "Got exception: ", e.msg continue diff --git a/src/nimlsp.nim.cfg b/src/nimlsp.nim.cfg deleted file mode 100644 index 93c3b02..0000000 --- a/src/nimlsp.nim.cfg +++ /dev/null @@ -1,21 +0,0 @@ -gc:markAndSweep - -hint[XDeclaredButNotUsed]:off - -path:"$lib/packages/docutils" - -define:useStdoutAsStdmsg -define:nimsuggest -define:nimcore - -# die when nimsuggest uses more than 4GB: -@if cpu32: - define:"nimMaxHeap=2000" -@else: - define:"nimMaxHeap=4000" -@end - ---threads:on ---warning[Spacing]:off # The JSON schema macro uses a syntax similar to TypeScript ---warning[CaseTransition]:off --d:nimOldCaseObjects diff --git a/src/nimlsppkg/logger.nim b/src/nimlsppkg/logger.nim new file mode 100644 index 0000000..319d379 --- /dev/null +++ b/src/nimlsppkg/logger.nim @@ -0,0 +1,14 @@ +import os +const + storage* = getTempDir() / "nimlsp" + +when defined(debugLogging): + var logFile = open(storage / "nimlsp.log", fmWrite) + +template debug*(args: varargs[string, `$`]) = + when defined(debugLogging): + stderr.write(join args) + stderr.write("\n") + logFile.write(join args) + logFile.write("\n\n") + logFile.flushFile() \ No newline at end of file diff --git a/src/nimlsppkg/suggestlib.nim b/src/nimlsppkg/suggestlib.nim index 7185a05..2f0a3f3 100644 --- a/src/nimlsppkg/suggestlib.nim +++ b/src/nimlsppkg/suggestlib.nim @@ -1,12 +1,10 @@ import macros, os +import logger const explicitSourcePath {.strdefine.} = getCurrentCompilerExe().parentDir.parentDir macro mImport(path: static[string]): untyped = - result = newNimNode(nnkStmtList) - result.add(quote do: - import `path` - ) + result = nnkImportStmt.newTree(newLit(path)) mImport(explicitSourcePath / "nimsuggest" / "nimsuggest.nim") import messageenums @@ -97,32 +95,115 @@ func nimSymDetails*(suggest: Suggest): string = of "skVar": "var of " & suggest.forth else: suggest.forth -func nimDocstring*(suggest: Suggest): string = - suggest.doc +macro createCommands(fileOnly:static[bool] = false, commands: varargs[untyped]) = + + result = nnkStmtList.newTree + for cmd in commands: + let cmdStr = cmd.strVal + var params = nnkFormalParams.newTree( + nnkBracketExpr.newTree( + ident("seq"), + ident"Suggest" + ), + nnkIdentDefs.newTree( + ident("nimsuggest"), + ident("NimSuggest"), + newEmptyNode() + ), + nnkIdentDefs.newTree( + ident("file"), + ident("string"), + newEmptyNode() + ), + nnkIdentDefs.newTree( + ident("dirtyfile"), + newEmptyNode(), + newLit("") + ), + + ) + if not fileOnly: + params.add nnkIdentDefs.newTree( + ident("line"), + ident("int"), + newEmptyNode() + ) + params.add nnkIdentDefs.newTree( + ident("col"), + ident("int"), + newEmptyNode() + ) + var call = nnkCall.newTree( + nnkDotExpr.newTree( + ident("nimsuggest"), + ident("runCmd") + ), + ident("ide" & cmdStr) + , + nnkCommand.newTree( + ident("AbsoluteFile"), + ident("file") + ), + nnkCommand.newTree( + ident("AbsoluteFile"), + ident("dirtyfile") + ) + ) + if not fileOnly: + call.add ident("line") + call.add ident("col") + else: + call.add newLit(0) + call.add newLit(0) + var tryCatch = nnkTryStmt.newTree( + nnkStmtList.newTree( + nnkAsgn.newTree( + newIdentNode("result"), + call + ) + ), + nnkExceptBranch.newTree( + nnkInfix.newTree( + newIdentNode("as"), + newIdentNode("Exception"), + newIdentNode("e") + ), + nnkStmtList.newTree( + nnkCommand.newTree( + newIdentNode("debug"), + nnkPrefix.newTree( + newIdentNode("$"), + nnkCall.newTree( + newIdentNode("getStackTraceEntries") + ) + ) + ) + ) + ) + ) + result.add nnkStmtList.newTree( + nnkProcDef.newTree( + nnkPostfix.newTree( + ident("*"), + ident(cmdStr) + ), + newEmptyNode(), + newEmptyNode(), + params, + newEmptyNode(), + newEmptyNode(), + nnkStmtList.newTree( + tryCatch + ) + ) + ) -template createFullCommand(command: untyped) {.dirty.} = - proc command*(nimsuggest: NimSuggest, file: string, dirtyfile = "", - line: int, col: int): seq[Suggest] = - nimsuggest.runCmd(`ide command`, AbsoluteFile file, AbsoluteFile dirtyfile, line, col) - -template createFileOnlyCommand(command: untyped) {.dirty.} = - proc command*(nimsuggest: NimSuggest, file: string, dirtyfile = ""): seq[Suggest] = - nimsuggest.runCmd(`ide command`, AbsoluteFile file, AbsoluteFile dirtyfile, 0, 0) - -createFullCommand(sug) -createFullCommand(con) -createFullCommand(def) -createFullCommand(use) -createFullCommand(dus) -createFileOnlyCommand(chk) -#createFileOnlyCommand(`mod`) -createFileOnlyCommand(highlight) -createFileOnlyCommand(outline) -createFileOnlyCommand(known) +createCommands(false,sug,con,def,use,dus) +createCommands(true,chk,highlight,outline,known) when isMainModule: - var graph = initNimSuggest("/home/peter/div/nimlsp/suglibtest.nim", nimPath = "/home/peter/div/Nim") - var suggestions = graph.sug("/home/peter/div/nimlsp/suglibtest.nim", "/home/peter/div/nimlsp/suglibtest.nim", 7, 2) + var graph = initNimSuggest(currentSourcePath, nimPath = getCurrentCompilerExe().parentDir.parentDir) + var suggestions = graph.sug(currentSourcePath, currentSourcePath, 206, 26) echo "Got ", suggestions.len, " suggestions" for suggestion in suggestions: echo suggestion diff --git a/src/nimlsppkg/suggestlib.nims b/src/nimlsppkg/suggestlib.nims new file mode 100644 index 0000000..c3f38e0 --- /dev/null +++ b/src/nimlsppkg/suggestlib.nims @@ -0,0 +1,6 @@ +import os + +switch "path", getCurrentCompilerExe().parentDir.parentDir +--define:nimsuggest +--define:nimcore +--threads:on \ No newline at end of file