diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2021-04-19 22:37:09 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-19 22:37:09 +0200 |
commit | 3b80f0dc8ef2bc9d2a981a7c92a6355dfc72b7ef (patch) | |
tree | 343dfdc727acde6e8e349661a94c208d1ceda9c0 | |
parent | 24abe10aa8cdf3daa69854bba403ad4cee527503 (diff) | |
download | Nim-3b80f0dc8ef2bc9d2a981a7c92a6355dfc72b7ef.tar.gz |
IC navigator: added support for include files (#17784)
* ic fixed navigator crash when track wrong/missed Also fixed an issue with getNimcacheDir not observing the outDir. * closer, but not sure how to test[skip ci][ci skip] * IC navigator: added support for include files * update * make posix happy via expandFilename * update Co-authored-by: Saem Ghani <saemghani+github@gmail.com>
-rw-r--r-- | compiler/commands.nim | 69 | ||||
-rw-r--r-- | compiler/ic/ic.nim | 2 | ||||
-rw-r--r-- | compiler/ic/navigator.nim | 28 | ||||
-rw-r--r-- | compiler/msgs.nim | 3 | ||||
-rw-r--r-- | compiler/options.nim | 5 | ||||
-rw-r--r-- | testament/categories.nim | 2 | ||||
-rw-r--r-- | tests/navigator/minclude.nim | 2 | ||||
-rw-r--r-- | tests/navigator/tincludefile.nim | 29 | ||||
-rw-r--r-- | tests/navigator/tnav1.nim | 4 |
9 files changed, 111 insertions, 33 deletions
diff --git a/compiler/commands.nim b/compiler/commands.nim index e918979fb..5d6e45fb5 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -28,7 +28,7 @@ bootSwitch(usedNoGC, defined(nogc), "--gc:none") import os, msgs, options, nversion, condsyms, strutils, extccomp, platform, wordrecg, parseutils, nimblecmd, parseopt, sequtils, lineinfos, - pathutils, strtabs + pathutils, strtabs, pathnorm from ast import eqTypeFlags, tfGcSafe, tfNoSideEffect @@ -359,31 +359,52 @@ proc processCfgPath(conf: ConfigRef; path: string, info: TLineInfo): AbsoluteDir const errInvalidNumber = "$1 is not a valid number" +proc makeAbsolute(s: string): AbsoluteFile = + if isAbsolute(s): + AbsoluteFile pathnorm.normalizePath(s) + else: + AbsoluteFile pathnorm.normalizePath(os.getCurrentDir() / s) + +proc setTrackingInfo(conf: ConfigRef; dirty, file, line, column: string, + info: TLineInfo) = + ## set tracking info, common code for track, trackDirty, & ideTrack + var ln, col: int + if parseUtils.parseInt(line, ln) <= 0: + localError(conf, info, errInvalidNumber % line) + if parseUtils.parseInt(column, col) <= 0: + localError(conf, info, errInvalidNumber % column) + + let a = makeAbsolute(file) + if dirty == "": + conf.m.trackPos = newLineInfo(conf, a, ln, col) + else: + let dirtyOriginalIdx = fileInfoIdx(conf, a) + if dirtyOriginalIdx.int32 >= 0: + msgs.setDirtyFile(conf, dirtyOriginalIdx, makeAbsolute(dirty)) + conf.m.trackPos = newLineInfo(dirtyOriginalIdx, ln, col) + proc trackDirty(conf: ConfigRef; arg: string, info: TLineInfo) = var a = arg.split(',') if a.len != 4: localError(conf, info, "DIRTY_BUFFER,ORIGINAL_FILE,LINE,COLUMN expected") - var line, column: int - if parseUtils.parseInt(a[2], line) <= 0: - localError(conf, info, errInvalidNumber % a[1]) - if parseUtils.parseInt(a[3], column) <= 0: - localError(conf, info, errInvalidNumber % a[2]) - - let dirtyOriginalIdx = fileInfoIdx(conf, AbsoluteFile a[1]) - if dirtyOriginalIdx.int32 >= 0: - msgs.setDirtyFile(conf, dirtyOriginalIdx, AbsoluteFile a[0]) - - conf.m.trackPos = newLineInfo(dirtyOriginalIdx, line, column) + setTrackingInfo(conf, a[0], a[1], a[2], a[3], info) proc track(conf: ConfigRef; arg: string, info: TLineInfo) = var a = arg.split(',') if a.len != 3: localError(conf, info, "FILE,LINE,COLUMN expected") - var line, column: int - if parseUtils.parseInt(a[1], line) <= 0: - localError(conf, info, errInvalidNumber % a[1]) - if parseUtils.parseInt(a[2], column) <= 0: - localError(conf, info, errInvalidNumber % a[2]) - conf.m.trackPos = newLineInfo(conf, AbsoluteFile a[0], line, column) + setTrackingInfo(conf, "", a[0], a[1], a[2], info) + +proc trackIde(conf: ConfigRef; cmd: IdeCmd, arg: string, info: TLineInfo) = + ## set the tracking info related to an ide cmd, supports optional dirty file + var a = arg.split(',') + case a.len + of 4: + setTrackingInfo(conf, a[0], a[1], a[2], a[3], info) + of 3: + setTrackingInfo(conf, "", a[0], a[1], a[2], info) + else: + localError(conf, info, "[DIRTY_BUFFER,]ORIGINAL_FILE,LINE,COLUMN expected") + conf.ideCmd = cmd proc dynlibOverride(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = if pass in {passCmd2, passPP}: @@ -851,17 +872,17 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; expectNoArg(conf, switch, arg, pass, info) conf.ideCmd = ideSug of "def": - expectNoArg(conf, switch, arg, pass, info) - conf.ideCmd = ideDef + expectArg(conf, switch, arg, pass, info) + trackIde(conf, ideDef, arg, info) of "context": expectNoArg(conf, switch, arg, pass, info) conf.ideCmd = ideCon of "usages": - expectNoArg(conf, switch, arg, pass, info) - conf.ideCmd = ideUse + expectArg(conf, switch, arg, pass, info) + trackIde(conf, ideUse, arg, info) of "defusages": - expectNoArg(conf, switch, arg, pass, info) - conf.ideCmd = ideDus + expectArg(conf, switch, arg, pass, info) + trackIde(conf, ideDus, arg, info) of "stdout": processOnOffSwitchG(conf, {optStdout}, arg, pass, info) of "listfullpaths": diff --git a/compiler/ic/ic.nim b/compiler/ic/ic.nim index a23685be7..d9a8756f1 100644 --- a/compiler/ic/ic.nim +++ b/compiler/ic/ic.nim @@ -29,7 +29,7 @@ type PackedModule* = object ## the parts of a PackedEncoder that are part of the .rod file definedSymbols: string moduleFlags: TSymFlags - includes: seq[(LitId, string)] # first entry is the module filename itself + includes*: seq[(LitId, string)] # first entry is the module filename itself imports: seq[LitId] # the modules this module depends on toReplay*: PackedTree # pragmas and VM specific state to replay. topLevel*: PackedTree # top level statements diff --git a/compiler/ic/navigator.nim b/compiler/ic/navigator.nim index b1a237cf7..cedf41579 100644 --- a/compiler/ic/navigator.nim +++ b/compiler/ic/navigator.nim @@ -98,11 +98,31 @@ proc list(c: var NavContext; tree: PackedTree; sym: ItemId) = usage(c, tree.nodes[i].info, isDecl(tree, parent(NodePos i))) else: discard +proc searchForIncludeFile(g: ModuleGraph; fullPath: string): int = + for i in 0..high(g.packed): + for k in 1..high(g.packed[i].fromDisk.includes): + # we start from 1 because the first "include" file is + # the module's filename. + if os.cmpPaths(g.packed[i].fromDisk.strings[g.packed[i].fromDisk.includes[k][0]], fullPath) == 0: + return i + return -1 + proc nav(g: ModuleGraph) = # translate the track position to a packed position: let unpacked = g.config.m.trackPos - let mid = unpacked.fileIndex - let fileId = g.packed[int32 mid].fromDisk.strings.getKeyId(toFullPath(g.config, mid)) + var mid = unpacked.fileIndex.int + + let fullPath = toFullPath(g.config, unpacked.fileIndex) + + if g.packed[mid].status == undefined: + # check if 'mid' is an include file of some other module: + mid = searchForIncludeFile(g, fullPath) + + if mid < 0: + localError(g.config, unpacked, "unknown file name: " & fullPath) + return + + let fileId = g.packed[mid].fromDisk.strings.getKeyId(fullPath) if fileId == LitId(0): internalError(g.config, unpacked, "cannot find a valid file ID") @@ -114,9 +134,9 @@ proc nav(g: ModuleGraph) = trackPos: PackedLineInfo(line: unpacked.line, col: unpacked.col, file: fileId), outputSep: if isDefined(g.config, "nimIcNavigatorTests"): ' ' else: '\t' ) - var symId = search(c, g.packed[int32 mid].fromDisk.topLevel) + var symId = search(c, g.packed[mid].fromDisk.topLevel) if symId == EmptyItemId: - symId = search(c, g.packed[int32 mid].fromDisk.bodies) + symId = search(c, g.packed[mid].fromDisk.bodies) if symId == EmptyItemId: localError(g.config, unpacked, "no symbol at this position") diff --git a/compiler/msgs.nim b/compiler/msgs.nim index c1e1f9e39..39b10d7df 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -582,6 +582,9 @@ template globalError*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") template globalError*(conf: ConfigRef; info: TLineInfo, arg: string) = liMessage(conf, info, errGenerated, arg, doRaise, instLoc()) +template globalError*(conf: ConfigRef; format: string, params: openArray[string]) = + liMessage(conf, unknownLineInfo, errGenerated, format % params, doRaise, instLoc()) + template localError*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") = liMessage(conf, info, msg, arg, doNothing, instLoc()) diff --git a/compiler/options.nim b/compiler/options.nim index 5475410a4..c1ac6b1e0 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -701,7 +701,10 @@ proc getNimcacheDir*(conf: ConfigRef): AbsoluteDir = result = if not conf.nimcacheDir.isEmpty: conf.nimcacheDir elif conf.backend == backendJs: - conf.projectPath / genSubDir + if conf.outDir.isEmpty: + conf.projectPath / genSubDir + else: + conf.outDir / genSubDir else: AbsoluteDir(getOsCacheDir() / splitFile(conf.projectName).name & nimcacheSuffix(conf)) diff --git a/testament/categories.nim b/testament/categories.nim index 4c3a0b1f5..d05112a25 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -490,7 +490,7 @@ proc icTests(r: var TResults; testsDir: string, cat: Category, options: string; writeOnly = " --incremental:writeonly " readOnly = " --incremental:readonly " incrementalOn = " --incremental:on -d:nimIcIntegrityChecks " - navTestConfig = " --ic:on --defusages -d:nimIcNavigatorTests --hint[Conf]:off --warnings:off " + navTestConfig = " --ic:on -d:nimIcNavigatorTests --hint[Conf]:off --warnings:off " template test(x: untyped) = testSpecWithNimcache(r, makeRawTest(file, x & options, cat), nimcache) diff --git a/tests/navigator/minclude.nim b/tests/navigator/minclude.nim new file mode 100644 index 000000000..f65ebfab9 --- /dev/null +++ b/tests/navigator/minclude.nim @@ -0,0 +1,2 @@ +# An include file. +foo(3) diff --git a/tests/navigator/tincludefile.nim b/tests/navigator/tincludefile.nim new file mode 100644 index 000000000..f35ab2ec9 --- /dev/null +++ b/tests/navigator/tincludefile.nim @@ -0,0 +1,29 @@ +discard """ + cmd: "nim check $options --defusages:$file,12,7 $file" + nimout: '''def tincludefile_temp.nim(11, 10) +usage tincludefile_temp.nim(12, 8) + ''' +""" + + + + +proc foo(x: int) = + echo x + +foo(3) +echo "yes", 1 != 3 + +#!EDIT!# +discard """ + cmd: "nim check $options --defusages:$file/../minclude.nim,2,2 $file" + nimout: '''def tincludefile_temp.nim(10, 6) +usage minclude.nim(2, 1) + ''' +""" + + +proc foo(x: int) = + echo x + +include minclude diff --git a/tests/navigator/tnav1.nim b/tests/navigator/tnav1.nim index d7c6f63e2..b6bbdbf19 100644 --- a/tests/navigator/tnav1.nim +++ b/tests/navigator/tnav1.nim @@ -1,5 +1,5 @@ discard """ - cmd: "nim check $options --track:$file,12,7 $file" + cmd: "nim check $options --defusages:$file,12,7 $file" nimout: '''def tnav1_temp.nim(11, 10) usage tnav1_temp.nim(12, 8) ''' @@ -16,7 +16,7 @@ echo "yes", 1 != 3 #!EDIT!# discard """ - cmd: "nim check $options --track:$file,15,2 $file" + cmd: "nim check $options --defusages:$file,15,2 $file" nimout: '''def tnav1_temp.nim(12, 6) usage tnav1_temp.nim(15, 1) ''' |