From f962de4fe37fab6f3bce999c6ae8bfe04640d135 Mon Sep 17 00:00:00 2001 From: bung87 Date: Wed, 4 Nov 2020 15:15:08 +0800 Subject: [PATCH 1/7] init formatting --- src/nimlsp.nim | 25 ++++++++++++++++++++++--- src/nimlsp.nim.cfg | 1 + src/nimlsppkg/messages.nim | 2 +- src/nimlsppkg/prettylib.nim | 20 ++++++++++++++++++++ src/nimlsppkg/prettylib.nim.cfg | 1 + 5 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 src/nimlsppkg/prettylib.nim create mode 100644 src/nimlsppkg/prettylib.nim.cfg diff --git a/src/nimlsp.nim b/src/nimlsp.nim index 43cb57f..ab42c65 100644 --- a/src/nimlsp.nim +++ b/src/nimlsp.nim @@ -1,4 +1,4 @@ -import nimlsppkg / [baseprotocol, utfmapping, suggestlib] +import nimlsppkg / [baseprotocol, utfmapping, suggestlib, prettylib] include nimlsppkg / messages import streams import tables @@ -73,7 +73,7 @@ template textDocumentRequest(message, kind, name, body) {.dirty.} = fileuri = name["textDocument"]["uri"].getStr filestash = storage / (hash(fileuri).toHex & ".nim" ) debugEcho "Got request for URI: ", fileuri, " copied to " & filestash - when kind isnot DocumentSymbolParams: + when kind isnot DocumentSymbolParams and kind isnot DocumentFormattingParams: let rawLine = name["position"]["line"].getInt rawChar = name["position"]["character"].getInt @@ -215,7 +215,7 @@ while true: workspaceSymbolProvider = none(bool), #?: bool codeActionProvider = none(bool), #?: bool codeLensProvider = none(CodeLensOptions), #?: CodeLensOptions - documentFormattingProvider = none(bool), #?: bool + documentFormattingProvider = some(true), #?: bool documentRangeFormattingProvider = none(bool), #?: bool documentOnTypeFormattingProvider = none(DocumentOnTypeFormattingOptions), #?: DocumentOnTypeFormattingOptions renameProvider = some(true), #?: bool @@ -402,6 +402,25 @@ while true: none(string) ).JsonNode message.respond response + of "textDocument/formatting": + message.textDocumentRequest(DocumentFormattingParams, documentFormattingRequest): + let infile = fileuri[7..^1] + let dirtyfile = filestash + let params = message["params"].unsafeGet + let tabSize = params["tabSize"].getInt + var opt = PrettyOptions(indWidth: tabSize, maxLineLen: 80) + prettyPrintFile(infile, dirtyfile, opt) + let newText = readFile(dirtyfile) + let lines = countLines(newText) + var response = newJarray() + response.add create(TextEdit, + create(Range, + create(Position, 0, 0), + create(Position, lines, 999) + ), + newText + ).JsonNode + message.respond response #of "textDocument/signatureHelp": # if message["params"].isSome: # let signRequest = message["params"].unsafeGet diff --git a/src/nimlsp.nim.cfg b/src/nimlsp.nim.cfg index 93c3b02..734cbde 100644 --- a/src/nimlsp.nim.cfg +++ b/src/nimlsp.nim.cfg @@ -7,6 +7,7 @@ path:"$lib/packages/docutils" define:useStdoutAsStdmsg define:nimsuggest define:nimcore +define:nimPretty # die when nimsuggest uses more than 4GB: @if cpu32: diff --git a/src/nimlsppkg/messages.nim b/src/nimlsppkg/messages.nim index 83970d5..9080517 100644 --- a/src/nimlsppkg/messages.nim +++ b/src/nimlsppkg/messages.nim @@ -573,7 +573,7 @@ jsonSchema: textDocument: TextDocumentIdentifier options: any # FormattingOptions - #FormattingOptions: + # FormattingOptions: # tabSize: int or float # insertSpaces: bool # [key: string]: boolean | int or float | string (jsonschema doesn't support variable key objects) diff --git a/src/nimlsppkg/prettylib.nim b/src/nimlsppkg/prettylib.nim new file mode 100644 index 0000000..e83cdb8 --- /dev/null +++ b/src/nimlsppkg/prettylib.nim @@ -0,0 +1,20 @@ +import macros, os + +const explicitSourcePath {.strdefine.} = getCurrentCompilerExe().parentDir.parentDir + +macro mImport(path: static[string]): untyped = + result = newNimNode(nnkStmtList) + result.add(quote do: + import `path` + ) + +mImport(explicitSourcePath / "nimpretty" / "nimpretty.nim") +export nimpretty + +proc prettyPrintFile*(infile, outfile: string, opt: PrettyOptions) = + prettyPrint(infile, outfile, opt) + +when isMainModule: + var opt = PrettyOptions(indWidth: 2, maxLineLen: 80) + prettyPrintFile(currentSourcePath, currentSourcePath, opt) + diff --git a/src/nimlsppkg/prettylib.nim.cfg b/src/nimlsppkg/prettylib.nim.cfg new file mode 100644 index 0000000..fc7efd6 --- /dev/null +++ b/src/nimlsppkg/prettylib.nim.cfg @@ -0,0 +1 @@ +define:nimPretty \ No newline at end of file From d0cea5b6ef06fba8f6fd7443397b8f33ad27ba37 Mon Sep 17 00:00:00 2001 From: bung87 Date: Wed, 4 Nov 2020 17:42:48 +0800 Subject: [PATCH 2/7] o --- src/nimlsp.nim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/nimlsp.nim b/src/nimlsp.nim index ab42c65..b6b8561 100644 --- a/src/nimlsp.nim +++ b/src/nimlsp.nim @@ -164,7 +164,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" @@ -409,6 +410,7 @@ while true: let params = message["params"].unsafeGet let tabSize = params["tabSize"].getInt var opt = PrettyOptions(indWidth: tabSize, maxLineLen: 80) + debugEcho "Formatting infile: ", infile, " outfile: ", dirtyfile prettyPrintFile(infile, dirtyfile, opt) let newText = readFile(dirtyfile) let lines = countLines(newText) From 4c61f1557763c733758484acccbbb49e893e61bd Mon Sep 17 00:00:00 2001 From: bung87 Date: Thu, 5 Nov 2020 08:54:27 +0800 Subject: [PATCH 3/7] replace message.whenValid to msg.isValid reduce the complexity, because a Notifition could run into whenValid Request else branch --- src/nimlsp.nim | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/nimlsp.nim b/src/nimlsp.nim index b6b8561..c9351b4 100644 --- a/src/nimlsp.nim +++ b/src/nimlsp.nim @@ -176,8 +176,9 @@ while true: debugEcho "Trying to read frame" let frame = ins.readFrame debugEcho "Got frame:\n" & frame - let message = frame.parseJson - whenValid(message, RequestMessage): + let msg = frame.parseJson + if msg.isValid(RequestMessage): + let message = RequestMessage(msg) debugEcho "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()) @@ -439,7 +440,8 @@ while true: else: debugEcho "Unknown request" continue - whenValid(message, NotificationMessage): + elif msg.isValid(NotificationMessage): + let message = NotificationMessage(msg) debugEcho "Got valid Notification message of type " & message["method"].getStr if not initialized and message["method"].getStr != "exit": continue @@ -544,6 +546,7 @@ while true: else: debugEcho "Got unknown notification message" continue + except IOError: break except CatchableError as e: From 7a8520d3956ca435eb54bd58afb58602e0ad5c18 Mon Sep 17 00:00:00 2001 From: bung87 Date: Thu, 5 Nov 2020 10:38:09 +0800 Subject: [PATCH 4/7] o --- nimlsp.nimble | 2 +- src/nimlsp.nim | 4 ++-- src/nimlsp.nim.cfg | 2 +- src/nimlsppkg/prettylib.nim | 2 +- src/nimlsppkg/prettylib.nim.cfg | 1 - 5 files changed, 5 insertions(+), 6 deletions(-) delete mode 100644 src/nimlsppkg/prettylib.nim.cfg diff --git a/nimlsp.nimble b/nimlsp.nimble index 75de9f9..3905897 100644 --- a/nimlsp.nimble +++ b/nimlsp.nimble @@ -20,7 +20,7 @@ requires "jsonschema >= 0.2.1" # exec "nim c -d:debugLogging -d:jsonSchemaDebug -r tests/test_messages2.nim" task debug, "Builds the language server": - exec "nim c --threads:on -d:nimcore -d:nimsuggest -d:debugCommunication -d:debugLogging -o:nimlsp src/nimlsp" + exec "nim c --threads:on -d:nimcore -d:nimpretty -d:nimsuggest -d:debugCommunication -d:debugLogging -o:nimlsp src/nimlsp" before test: if not fileExists("nimlsp"): diff --git a/src/nimlsp.nim b/src/nimlsp.nim index c9351b4..29542d6 100644 --- a/src/nimlsp.nim +++ b/src/nimlsp.nim @@ -459,14 +459,14 @@ while true: let file = open(filestash, fmWrite) projectFile = getProjectFile(fileuri[7..^1]) - debugEcho "New document opened for URI: ", fileuri, " saving to " & filestash + debugEcho "New document opened for URI: ", fileuri, " \nsaving to " & filestash openFiles[fileuri] = ( #nimsuggest: initNimsuggest(fileuri[7..^1]), projectFile: projectFile, fingerTable: @[] ) if not projectFiles.hasKey(projectFile): - debugEcho "Initialising project with ", projectFile, ":", nimpath + debugEcho "Initialising project with project file: ", projectFile, "\nnimpath: ", nimpath projectFiles[projectFile] = (nimsuggest: initNimsuggest(projectFile, nimpath), openFiles: 1) else: projectFiles[projectFile].openFiles += 1 diff --git a/src/nimlsp.nim.cfg b/src/nimlsp.nim.cfg index 734cbde..0dab156 100644 --- a/src/nimlsp.nim.cfg +++ b/src/nimlsp.nim.cfg @@ -7,7 +7,7 @@ path:"$lib/packages/docutils" define:useStdoutAsStdmsg define:nimsuggest define:nimcore -define:nimPretty +define:nimpretty # die when nimsuggest uses more than 4GB: @if cpu32: diff --git a/src/nimlsppkg/prettylib.nim b/src/nimlsppkg/prettylib.nim index e83cdb8..cec4322 100644 --- a/src/nimlsppkg/prettylib.nim +++ b/src/nimlsppkg/prettylib.nim @@ -9,7 +9,7 @@ macro mImport(path: static[string]): untyped = ) mImport(explicitSourcePath / "nimpretty" / "nimpretty.nim") -export nimpretty +export PrettyOptions proc prettyPrintFile*(infile, outfile: string, opt: PrettyOptions) = prettyPrint(infile, outfile, opt) diff --git a/src/nimlsppkg/prettylib.nim.cfg b/src/nimlsppkg/prettylib.nim.cfg deleted file mode 100644 index fc7efd6..0000000 --- a/src/nimlsppkg/prettylib.nim.cfg +++ /dev/null @@ -1 +0,0 @@ -define:nimPretty \ No newline at end of file From cb64c2961117593793a2ac81ed59c9ef03a77b5c Mon Sep 17 00:00:00 2001 From: bung87 Date: Thu, 5 Nov 2020 11:30:14 +0800 Subject: [PATCH 5/7] use macro instead of template for creating commands, reduce complexity and compile error --- src/nimlsppkg/suggestlib.nim | 99 +++++++++++++++++++++++++------- src/nimlsppkg/suggestlib.nim.cfg | 3 + 2 files changed, 82 insertions(+), 20 deletions(-) create mode 100644 src/nimlsppkg/suggestlib.nim.cfg diff --git a/src/nimlsppkg/suggestlib.nim b/src/nimlsppkg/suggestlib.nim index 7185a05..51fad4c 100644 --- a/src/nimlsppkg/suggestlib.nim +++ b/src/nimlsppkg/suggestlib.nim @@ -100,29 +100,88 @@ func nimSymDetails*(suggest: Suggest): string = func nimDocstring*(suggest: Suggest): string = suggest.doc -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) +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( + newIdentNode("seq"), + newIdentNode("Suggest") + ), + nnkIdentDefs.newTree( + newIdentNode("nimsuggest"), + newIdentNode("NimSuggest"), + newEmptyNode() + ), + nnkIdentDefs.newTree( + newIdentNode("file"), + newIdentNode("string"), + newEmptyNode() + ), + nnkIdentDefs.newTree( + newIdentNode("dirtyfile"), + newEmptyNode(), + newLit("") + ), + + ) + if not fileOnly: + params.add nnkIdentDefs.newTree( + newIdentNode("line"), + newIdentNode("int"), + newEmptyNode() + ) + params.add nnkIdentDefs.newTree( + newIdentNode("col"), + newIdentNode("int"), + newEmptyNode() + ) + var call = nnkCall.newTree( + nnkDotExpr.newTree( + newIdentNode("nimsuggest"), + newIdentNode("runCmd") + ), + ident("ide" & cmdStr) + , + nnkCommand.newTree( + newIdentNode("AbsoluteFile"), + newIdentNode("file") + ), + nnkCommand.newTree( + newIdentNode("AbsoluteFile"), + newIdentNode("dirtyfile") + ) + ) + if not fileOnly: + call.add newIdentNode("line") + call.add newIdentNode("col") + else: + call.add newLit(0) + call.add newLit(0) + result.add nnkStmtList.newTree( + nnkProcDef.newTree( + nnkPostfix.newTree( + newIdentNode("*"), + newIdentNode(cmdStr) + ), + newEmptyNode(), + newEmptyNode(), + params, + newEmptyNode(), + newEmptyNode(), + nnkStmtList.newTree( + call + ) + ) + ) -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, 184, 26) echo "Got ", suggestions.len, " suggestions" for suggestion in suggestions: echo suggestion diff --git a/src/nimlsppkg/suggestlib.nim.cfg b/src/nimlsppkg/suggestlib.nim.cfg new file mode 100644 index 0000000..132a1cb --- /dev/null +++ b/src/nimlsppkg/suggestlib.nim.cfg @@ -0,0 +1,3 @@ +define:nimsuggest +define:nimcore +--threads:on \ No newline at end of file From 172df11b2c4bede843377a1628630bb814e9c173 Mon Sep 17 00:00:00 2001 From: bung87 Date: Thu, 5 Nov 2020 14:03:32 +0800 Subject: [PATCH 6/7] o --- nimlsp.nimble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimlsp.nimble b/nimlsp.nimble index 3905897..35cb849 100644 --- a/nimlsp.nimble +++ b/nimlsp.nimble @@ -20,7 +20,7 @@ requires "jsonschema >= 0.2.1" # exec "nim c -d:debugLogging -d:jsonSchemaDebug -r tests/test_messages2.nim" task debug, "Builds the language server": - exec "nim c --threads:on -d:nimcore -d:nimpretty -d:nimsuggest -d:debugCommunication -d:debugLogging -o:nimlsp src/nimlsp" + exec "nim c --threads:on -d:nimcore -d:nimsuggest -d:nimpretty -d:debugCommunication -d:debugLogging -o:nimlsp src/nimlsp" before test: if not fileExists("nimlsp"): From 5df86cdb238002bce6eed5c9e03114f6c5424981 Mon Sep 17 00:00:00 2001 From: bung87 Date: Sat, 7 Nov 2020 16:03:16 +0800 Subject: [PATCH 7/7] well, use nimpretty will cause initNimsuggest fails while compile module, it only gets default conf with projecname --- nimlsp.nimble | 2 +- src/nimlsp.nim | 27 ++++++++++++---------- src/nimlsp.nim.cfg | 2 +- src/nimlsppkg/suggestlib.nim | 45 ++++++++++++++++++------------------ 4 files changed, 40 insertions(+), 36 deletions(-) diff --git a/nimlsp.nimble b/nimlsp.nimble index 35cb849..75de9f9 100644 --- a/nimlsp.nimble +++ b/nimlsp.nimble @@ -20,7 +20,7 @@ requires "jsonschema >= 0.2.1" # exec "nim c -d:debugLogging -d:jsonSchemaDebug -r tests/test_messages2.nim" task debug, "Builds the language server": - exec "nim c --threads:on -d:nimcore -d:nimsuggest -d:nimpretty -d:debugCommunication -d:debugLogging -o:nimlsp src/nimlsp" + exec "nim c --threads:on -d:nimcore -d:nimsuggest -d:debugCommunication -d:debugLogging -o:nimlsp src/nimlsp" before test: if not fileExists("nimlsp"): diff --git a/src/nimlsp.nim b/src/nimlsp.nim index 29542d6..5706c10 100644 --- a/src/nimlsp.nim +++ b/src/nimlsp.nim @@ -1,4 +1,6 @@ -import nimlsppkg / [baseprotocol, utfmapping, suggestlib, prettylib] +import nimlsppkg / [baseprotocol, utfmapping, suggestlib] +when defined(nimpretty): + import nimlsppkg / prettylib include nimlsppkg / messages import streams import tables @@ -175,7 +177,6 @@ while true: try: debugEcho "Trying to read frame" let frame = ins.readFrame - debugEcho "Got frame:\n" & frame let msg = frame.parseJson if msg.isValid(RequestMessage): let message = RequestMessage(msg) @@ -410,19 +411,20 @@ while true: let dirtyfile = filestash let params = message["params"].unsafeGet let tabSize = params["tabSize"].getInt - var opt = PrettyOptions(indWidth: tabSize, maxLineLen: 80) - debugEcho "Formatting infile: ", infile, " outfile: ", dirtyfile - prettyPrintFile(infile, dirtyfile, opt) - let newText = readFile(dirtyfile) - let lines = countLines(newText) var response = newJarray() - response.add create(TextEdit, + when defined(nimpretty): + var opt = PrettyOptions(indWidth: tabSize, maxLineLen: 80) + debugEcho "Formatting infile: ", infile, " outfile: ", dirtyfile + prettyPrintFile(infile, dirtyfile, opt) + let newText = readFile(dirtyfile) + let lines = countLines(newText) + response.add create(TextEdit, create(Range, create(Position, 0, 0), create(Position, lines, 999) - ), - newText - ).JsonNode + ), + newText + ).JsonNode message.respond response #of "textDocument/signatureHelp": # if message["params"].isSome: @@ -546,7 +548,8 @@ while true: else: debugEcho "Got unknown notification message" continue - + else: + debugEcho "Got unknown message" & frame except IOError: break except CatchableError as e: diff --git a/src/nimlsp.nim.cfg b/src/nimlsp.nim.cfg index 0dab156..b5e4972 100644 --- a/src/nimlsp.nim.cfg +++ b/src/nimlsp.nim.cfg @@ -7,7 +7,7 @@ path:"$lib/packages/docutils" define:useStdoutAsStdmsg define:nimsuggest define:nimcore -define:nimpretty +# define:nimpretty # die when nimsuggest uses more than 4GB: @if cpu32: diff --git a/src/nimlsppkg/suggestlib.nim b/src/nimlsppkg/suggestlib.nim index 51fad4c..ed30686 100644 --- a/src/nimlsppkg/suggestlib.nim +++ b/src/nimlsppkg/suggestlib.nim @@ -101,26 +101,27 @@ 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( - newIdentNode("seq"), - newIdentNode("Suggest") + ident("seq"), + ident"Suggest" ), nnkIdentDefs.newTree( - newIdentNode("nimsuggest"), - newIdentNode("NimSuggest"), + ident("nimsuggest"), + ident("NimSuggest"), newEmptyNode() ), nnkIdentDefs.newTree( - newIdentNode("file"), - newIdentNode("string"), + ident("file"), + ident("string"), newEmptyNode() ), nnkIdentDefs.newTree( - newIdentNode("dirtyfile"), + ident("dirtyfile"), newEmptyNode(), newLit("") ), @@ -128,42 +129,42 @@ macro createCommands(fileOnly:static[bool] = false, commands: varargs[untyped]) ) if not fileOnly: params.add nnkIdentDefs.newTree( - newIdentNode("line"), - newIdentNode("int"), + ident("line"), + ident("int"), newEmptyNode() ) params.add nnkIdentDefs.newTree( - newIdentNode("col"), - newIdentNode("int"), + ident("col"), + ident("int"), newEmptyNode() ) var call = nnkCall.newTree( nnkDotExpr.newTree( - newIdentNode("nimsuggest"), - newIdentNode("runCmd") + ident("nimsuggest"), + ident("runCmd") ), ident("ide" & cmdStr) , nnkCommand.newTree( - newIdentNode("AbsoluteFile"), - newIdentNode("file") + ident("AbsoluteFile"), + ident("file") ), nnkCommand.newTree( - newIdentNode("AbsoluteFile"), - newIdentNode("dirtyfile") + ident("AbsoluteFile"), + ident("dirtyfile") ) ) if not fileOnly: - call.add newIdentNode("line") - call.add newIdentNode("col") + call.add ident("line") + call.add ident("col") else: call.add newLit(0) call.add newLit(0) result.add nnkStmtList.newTree( nnkProcDef.newTree( nnkPostfix.newTree( - newIdentNode("*"), - newIdentNode(cmdStr) + ident("*"), + ident(cmdStr) ), newEmptyNode(), newEmptyNode(), @@ -181,7 +182,7 @@ createCommands(true,chk,highlight,outline,known) when isMainModule: var graph = initNimSuggest(currentSourcePath, nimPath = getCurrentCompilerExe().parentDir.parentDir) - var suggestions = graph.sug(currentSourcePath, currentSourcePath, 184, 26) + var suggestions = graph.sug(currentSourcePath, currentSourcePath, 185, 26) echo "Got ", suggestions.len, " suggestions" for suggestion in suggestions: echo suggestion