Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP]Formatting #59

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 36 additions & 9 deletions src/nimlsp.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import nimlsppkg / [baseprotocol, utfmapping, suggestlib]
when defined(nimpretty):
import nimlsppkg / prettylib
include nimlsppkg / messages
import streams
import tables
Expand Down Expand Up @@ -73,7 +75,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
Expand Down Expand Up @@ -164,7 +166,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"
Expand All @@ -174,9 +177,9 @@ while true:
try:
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())
Expand Down Expand Up @@ -215,7 +218,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
Expand Down Expand Up @@ -402,6 +405,27 @@ 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 response = newJarray()
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
message.respond response
#of "textDocument/signatureHelp":
# if message["params"].isSome:
# let signRequest = message["params"].unsafeGet
Expand All @@ -418,7 +442,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
Expand All @@ -436,14 +461,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
Expand Down Expand Up @@ -523,6 +548,8 @@ while true:
else:
debugEcho "Got unknown notification message"
continue
else:
debugEcho "Got unknown message" & frame
except IOError:
break
except CatchableError as e:
Expand Down
1 change: 1 addition & 0 deletions src/nimlsp.nim.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion src/nimlsppkg/messages.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
20 changes: 20 additions & 0 deletions src/nimlsppkg/prettylib.nim
Original file line number Diff line number Diff line change
@@ -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 PrettyOptions

proc prettyPrintFile*(infile, outfile: string, opt: PrettyOptions) =
prettyPrint(infile, outfile, opt)

when isMainModule:
var opt = PrettyOptions(indWidth: 2, maxLineLen: 80)
prettyPrintFile(currentSourcePath, currentSourcePath, opt)

100 changes: 80 additions & 20 deletions src/nimlsppkg/suggestlib.nim
Original file line number Diff line number Diff line change
Expand Up @@ -100,29 +100,89 @@ 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(
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)
result.add nnkStmtList.newTree(
nnkProcDef.newTree(
nnkPostfix.newTree(
ident("*"),
ident(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, 185, 26)
echo "Got ", suggestions.len, " suggestions"
for suggestion in suggestions:
echo suggestion
3 changes: 3 additions & 0 deletions src/nimlsppkg/suggestlib.nim.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
define:nimsuggest
define:nimcore
--threads:on