nimsuggest: chk checks the full project lazily; much better suggestions orderings

This commit is contained in:
Andreas Rumpf 2017-03-08 00:38:48 +01:00
commit 91a4b448fd
8 changed files with 164 additions and 68 deletions

View file

@ -17,7 +17,7 @@ import compiler / [options, commands, modules, sem,
passes, passaux, msgs, nimconf,
extccomp, condsyms,
sigmatch, ast, scriptconfig,
idents, modulegraphs, vm]
idents, modulegraphs, vm, prefixmatches]
when defined(windows):
import winlean
@ -51,6 +51,11 @@ are supported.
"""
type
Mode = enum mstdin, mtcp, mepc, mcmdline
CachedMsg = object
info: TLineInfo
msg: string
sev: Severity
CachedMsgs = seq[CachedMsg]
var
gPort = 6000.Port
@ -93,7 +98,7 @@ proc parseQuoted(cmd: string; outp: var string; start: int): int =
i += parseUntil(cmd, outp, seps, i)
result = i
proc sexp(s: IdeCmd|TSymKind): SexpNode = sexp($s)
proc sexp(s: IdeCmd|TSymKind|PrefixMatch): SexpNode = sexp($s)
proc sexp(s: Suggest): SexpNode =
# If you change the order here, make sure to change it over in
@ -110,6 +115,8 @@ proc sexp(s: Suggest): SexpNode =
s.doc,
s.quality
])
if s.section == ideSug:
result.add convertSexp(s.prefix)
proc sexp(s: seq[Suggest]): SexpNode =
result = newSList()
@ -363,7 +370,7 @@ proc replEpc(x: ThreadParams) {.thread.} =
"unexpected call: " & epcAPI
quit errMessage
proc execCmd(cmd: string; graph: ModuleGraph; cache: IdentCache) =
proc execCmd(cmd: string; graph: ModuleGraph; cache: IdentCache; cachedMsgs: CachedMsgs) =
template sentinel() =
# send sentinel for the input reading thread:
results.send(Suggest(section: ideNone))
@ -415,17 +422,19 @@ proc execCmd(cmd: string; graph: ModuleGraph; cache: IdentCache) =
if gIdeCmd == ideKnown:
results.send(Suggest(section: ideKnown, quality: ord(fileInfoKnown(orig))))
else:
if gIdeCmd == ideChk:
for cm in cachedMsgs: errorHook(cm.info, cm.msg, cm.sev)
execute(gIdeCmd, orig, dirtyfile, line, col-1, graph, cache)
sentinel()
proc recompileFullProject(graph: ModuleGraph; cache: IdentCache) =
echo "recompiling full project"
#echo "recompiling full project"
resetSystemArtifacts()
vm.globalCtx = nil
graph.resetAllModules()
GC_fullcollect()
compileProject(graph, cache)
echo GC_getStatistics()
#echo GC_getStatistics()
proc mainThread(graph: ModuleGraph; cache: IdentCache) =
if gLogging:
@ -442,12 +451,13 @@ proc mainThread(graph: ModuleGraph; cache: IdentCache) =
suggestionResultHook = sugResultHook
graph.doStopCompile = proc (): bool = requests.peek() > 0
var idle = 0
var cachedMsgs: CachedMsgs = @[]
while true:
let (hasData, req) = requests.tryRecv()
if hasData:
msgs.writelnHook = wrHook
suggestionResultHook = sugResultHook
execCmd(req, graph, cache)
execCmd(req, graph, cache, cachedMsgs)
idle = 0
else:
os.sleep 250
@ -456,7 +466,9 @@ proc mainThread(graph: ModuleGraph; cache: IdentCache) =
# we use some nimsuggest activity to enable a lazy recompile:
gIdeCmd = ideChk
msgs.writelnHook = proc (s: string) = discard
msgs.structuredErrorHook = nil
cachedMsgs.setLen 0
msgs.structuredErrorHook = proc (info: TLineInfo; msg: string; sev: Severity) =
cachedMsgs.add(CachedMsg(info: info, msg: msg, sev: sev))
suggestionResultHook = proc (s: Suggest) = discard
recompileFullProject(graph, cache)
@ -525,8 +537,13 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
suggestVersion = 2
gMode = mstdin
gEmitEof = true
gRefresh = false
of "log": gLogging = true
of "refresh": gRefresh = true
of "refresh":
if p.val.len > 0:
gRefresh = parseBool(p.val)
else:
gRefresh = true
else: processSwitch(pass, p)
of cmdArgument:
options.gProjectName = unixToNativePath(p.key)

View file

@ -20,6 +20,7 @@ template tpath(): untyped = getAppDir() / "tests"
proc parseTest(filename: string; epcMode=false): Test =
const cursorMarker = "#[!]#"
let nimsug = curDir & addFileExt("nimsuggest", ExeExt)
let libpath = findExe("nim").splitFile().dir /../ "lib"
result.dest = getTempDir() / extractFilename(filename)
result.cmd = nimsug & " --tester " & result.dest
result.script = @[]
@ -42,7 +43,7 @@ proc parseTest(filename: string; epcMode=false): Test =
inc specSection
elif specSection == 1:
if x.startsWith("$nimsuggest"):
result.cmd = x % ["nimsuggest", nimsug, "file", filename]
result.cmd = x % ["nimsuggest", nimsug, "file", filename, "lib", libpath]
elif x.startsWith("!"):
if result.cmd.len == 0:
result.startup.add x
@ -54,7 +55,7 @@ proc parseTest(filename: string; epcMode=false): Test =
result.script.add((x.substr(1).replaceWord("$path", tpath()), ""))
elif x.len > 0:
# expected output line:
let x = x % ["file", filename]
let x = x % ["file", filename, "lib", libpath]
result.script[^1][1].add x.replace(";;", "\t") & '\L'
# else: ignore empty lines for better readability of the specs
inc i
@ -203,6 +204,9 @@ proc sexpToAnswer(s: SexpNode): string =
result.add doc
result.add '\t'
result.add a[8].getNum
if a.len >= 10:
result.add '\t'
result.add a[9].getStr
result.add '\L'
proc doReport(filename, answer, resp: string; report: var string) =

View file

@ -9,6 +9,6 @@ x.#[!]#
discard """
$nimsuggest --tester $file
>sug $1
sug;;skProc;;tno_deref.foo;;proc (y: ptr int)*;;$file;;4;;5;;"";;100
sug;;skProc;;tno_deref.foo;;proc (y: ptr int)*;;$file;;4;;5;;"";;100;;None
*
"""

View file

@ -0,0 +1,28 @@
# test we only get suggestions, not error messages:
import tables, sets, parsecfg
type X = object
proc main =
# bug #52
var
set0 = initSet[int]()
set1 = initSet[X]()
set2 = initSet[ref int]()
map0 = initTable[int, int]()
map1 = initOrderedTable[string, int]()
cfg = loadConfig("file")
map0.#[!]#
discard """
$nimsuggest --tester $file
>sug $1
sug;;skProc;;tables.getOrDefault;;proc (t: Table[getOrDefault.A, getOrDefault.B], key: A): B;;$lib/pure/collections/tables.nim;;178;;5;;"";;100;;None
sug;;skProc;;tables.hasKey;;proc (t: Table[hasKey.A, hasKey.B], key: A): bool;;$lib/pure/collections/tables.nim;;233;;5;;"returns true iff `key` is in the table `t`.";;100;;None
sug;;skProc;;tables.add;;proc (t: var Table[add.A, add.B], key: A, val: B);;$lib/pure/collections/tables.nim;;297;;5;;"puts a new (key, value)-pair into `t` even if ``t[key]`` already exists.";;100;;None
sug;;skIterator;;tables.allValues;;iterator (t: Table[allValues.A, allValues.B], key: A): B{.inline.};;$lib/pure/collections/tables.nim;;225;;9;;"iterates over any value in the table `t` that belongs to the given `key`.";;100;;None
sug;;skProc;;tables.clear;;proc (t: var Table[clear.A, clear.B]);;$lib/pure/collections/tables.nim;;121;;5;;"Resets the table so that it is empty.";;100;;None
*
"""

View file

@ -204,10 +204,10 @@ echo r
discard """
$nimsuggest --tester $file
>sug $1
sug;;skField;;name;;string;;$file;;166;;6;;"";;100
sug;;skField;;age;;int;;$file;;167;;6;;"";;100
sug;;skMethod;;twithin_macro.age_human_yrs;;proc (self: Animal): int;;$file;;169;;9;;"";;100
sug;;skMacro;;twithin_macro.class;;proc (head: untyped, body: untyped): untyped{.gcsafe, locks: <unknown>.};;$file;;4;;6;;"Iterates over the children of the NimNode ``n``.";;100
sug;;skMethod;;twithin_macro.vocalize;;proc (self: Animal): string;;$file;;168;;9;;"";;100
sug;;skMethod;;twithin_macro.vocalize;;proc (self: Rabbit): string;;$file;;184;;9;;"";;100*
sug;;skField;;age;;int;;$file;;167;;6;;"";;100;;None
sug;;skField;;name;;string;;$file;;166;;6;;"";;100;;None
sug;;skMethod;;twithin_macro.age_human_yrs;;proc (self: Animal): int;;$file;;169;;9;;"";;100;;None
sug;;skMethod;;twithin_macro.vocalize;;proc (self: Animal): string;;$file;;168;;9;;"";;100;;None
sug;;skMethod;;twithin_macro.vocalize;;proc (self: Rabbit): string;;$file;;184;;9;;"";;100;;None
sug;;skMacro;;twithin_macro.class;;proc (head: untyped, body: untyped): untyped{.gcsafe, locks: <unknown>.};;$file;;4;;6;;"";;50;;None*
"""

View file

@ -204,6 +204,6 @@ echo r
discard """
$nimsuggest --tester $file
>sug $1
sug;;skField;;age;;int;;$file;;167;;6;;"";;100
sug;;skMethod;;twithin_macro_prefix.age_human_yrs;;proc (self: Animal): int;;$file;;169;;9;;"";;100
sug;;skField;;age;;int;;$file;;167;;6;;"";;100;;Prefix
sug;;skMethod;;twithin_macro_prefix.age_human_yrs;;proc (self: Animal): int;;$file;;169;;9;;"";;100;;Prefix
"""