mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-04 06:28:38 +00:00
WIP: nim-check grows one-shot queries for nimsuggest-like functionality
This commit is contained in:
@@ -34,6 +34,7 @@ from icconfig import produceIcConfig
|
||||
when not defined(nimKochBootstrap):
|
||||
import nifbackend
|
||||
import deps
|
||||
import idetools
|
||||
|
||||
when not defined(leanCompiler):
|
||||
import docgen
|
||||
@@ -415,7 +416,26 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||
|
||||
for it in conf.searchPaths: msgWriteln(conf, it.string)
|
||||
of cmdCheck:
|
||||
commandCheck(graph)
|
||||
when not defined(nimKochBootstrap):
|
||||
if conf.ideCmd in {ideDef, ideUse}:
|
||||
# `nim check --def:`/`--usages:`: run a whole-project check that also
|
||||
# emits each cleanly-compiled module's `.s.bif` (see
|
||||
# pipelines.shouldWriteNif), then scan those NIF files to answer the
|
||||
# goto-definition / find-usages query. The NIF writer needs the IC setup
|
||||
# `cmdM` uses (disabled rod files + `useIc`) to serialize full module
|
||||
# content; we keep `cmd == cmdCheck` for its error-tolerant sem and the
|
||||
# VM guards that run compile-time code faithfully for this mode (see
|
||||
# vm.nim/vmgen.nim), so the emitted NIF reflects macro/gorge symbols.
|
||||
graph.config.symbolFiles = disabledSf
|
||||
setUseIc(true)
|
||||
excl conf.features, Feature.vtables
|
||||
createDir(getNimcacheDir(conf).string)
|
||||
commandCheck(graph)
|
||||
runIdeQuery(conf)
|
||||
else:
|
||||
commandCheck(graph)
|
||||
else:
|
||||
commandCheck(graph)
|
||||
of cmdM:
|
||||
# cmdM uses NIF files, not ROD files
|
||||
graph.config.symbolFiles = disabledSf
|
||||
|
||||
@@ -40,9 +40,10 @@ proc processPipeline(graph: ModuleGraph; semNode: PNode; bModule: PPassContext):
|
||||
of GenDependPass:
|
||||
result = addDotDependency(bModule, semNode)
|
||||
of SemPass:
|
||||
# Return the semantic node for cmdM (NIF generation needs it)
|
||||
# For regular check, we don't need the result
|
||||
if graph.config.cmd == cmdM:
|
||||
# Return the semantic node for cmdM (NIF generation needs it), and likewise
|
||||
# for a `--def`/`--usages` query under cmdCheck which emits `.s.bif` too.
|
||||
# For regular check, we don't need the result.
|
||||
if graph.config.cmd == cmdM or graph.config.ideCmd in {ideDef, ideUse}:
|
||||
result = semNode
|
||||
else:
|
||||
result = graph.emptyNode
|
||||
@@ -167,7 +168,10 @@ proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator
|
||||
s = stream
|
||||
graph.interactive = stream.kind == llsStdIn
|
||||
var topLevelStmts =
|
||||
if optCompress in graph.config.globalOptions or graph.config.cmd == cmdM:
|
||||
if optCompress in graph.config.globalOptions or graph.config.cmd == cmdM or
|
||||
graph.config.ideCmd in {ideDef, ideUse}:
|
||||
# A `--def`/`--usages` query emits every module's `.s.bif` under cmdCheck
|
||||
# (see shouldWriteNif below), which needs the collected top-level stmts.
|
||||
newNodeI(nkStmtList, module.info)
|
||||
else:
|
||||
nil
|
||||
@@ -247,7 +251,18 @@ proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator
|
||||
# current strongly-connected import group (`--icGroup`) are the exception:
|
||||
# they are compiled from source here, so each must write its own NIF.
|
||||
let shouldWriteNif =
|
||||
if graph.config.ideActive:
|
||||
if graph.config.ideCmd in {ideDef, ideUse}:
|
||||
# `nim check --def:`/`--usages:` query: this whole-project check runs
|
||||
# under cmdCheck and emits each cleanly-compiled, non-dirty PROJECT
|
||||
# module's `.s.bif` so `idetools.runIdeQuery` can scan them afterwards.
|
||||
# Stdlib modules are skipped: they serialize robustly only via `nim ic`'s
|
||||
# per-module `cmdM` build, and the common query targets a project symbol
|
||||
# (whose def + uses all live in project modules). Skip the edited buffer
|
||||
# and any module reached after an error (incomplete NIF).
|
||||
graph.config.errorCounter == 0 and
|
||||
not belongsToStdlib(graph, module) and
|
||||
graph.config.m.fileInfos[module.position].dirtyFile.isEmpty
|
||||
elif graph.config.ideActive:
|
||||
# nimsuggest (cmdM): persist NIF for cleanly-compiled, SAVED modules so
|
||||
# later queries load them instead of recompiling. Never persist the
|
||||
# actively edited buffer (it may hold unsaved/incomplete code) nor a
|
||||
|
||||
@@ -926,7 +926,7 @@ proc semWithPContext*(c: PContext, n: PNode): PNode =
|
||||
#if c.config.ideActive: findSuggest(c, n)
|
||||
|
||||
proc reportUnusedModules(c: PContext) =
|
||||
if c.config.cmd == cmdM: return
|
||||
if c.config.cmd == cmdM or c.config.ideCmd in {ideDef, ideUse}: return
|
||||
for (s, info) in c.unusedImports:
|
||||
if sfUsed notin s.flags:
|
||||
message(c.config, info, warnUnusedImportX, s.name.s)
|
||||
|
||||
@@ -2892,9 +2892,10 @@ proc incMod(c: PContext, n: PNode, it: PNode, includeStmtResult, resolvedIncStmt
|
||||
proc evalInclude(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
var resolvedIncStmt: PNode = nil
|
||||
if optCompress in c.config.globalOptions or c.config.cmd == cmdM:
|
||||
if optCompress in c.config.globalOptions or c.config.cmd == cmdM or
|
||||
c.config.ideCmd in {ideDef, ideUse}:
|
||||
# New resolve the include filenames to string literals that contain absolute paths,
|
||||
# nicer for IC:
|
||||
# nicer for IC (also for a `--def`/`--usages` query, which emits `.s.bif`):
|
||||
resolvedIncStmt = newNodeI(nkIncludeStmt, n.info)
|
||||
result.add resolvedIncStmt
|
||||
else:
|
||||
|
||||
@@ -2033,7 +2033,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
inc pc
|
||||
let rd = c.code[pc].regA
|
||||
createStr regs[ra]
|
||||
if defined(nimsuggest) or c.config.cmd == cmdCheck:
|
||||
if defined(nimsuggest) or (c.config.cmd == cmdCheck and c.config.ideCmd == ideNone):
|
||||
# Don't run staticExec for plain `nim check` / `nim suggest`. A
|
||||
# `--def`/`--usages` query (ideCmd != ideNone) is the exception: it wants
|
||||
# faithful compile-time execution so the emitted `.bif` — which the query
|
||||
# then scans — reflects macro/gorge-produced symbols. See idetools.nim.
|
||||
discard "don't run staticExec for 'nim suggest'"
|
||||
regs[ra].node.strVal = ""
|
||||
else:
|
||||
|
||||
@@ -359,7 +359,9 @@ proc genBlock(c: PCtx; n: PNode; dest: var TDest) =
|
||||
#if c.prc.regInfo[i].kind in {slotFixedVar, slotFixedLet}:
|
||||
if i != dest:
|
||||
when not defined(release):
|
||||
if c.config.cmd != cmdCheck:
|
||||
# A `--def`/`--usages` query runs the VM faithfully (ideCmd != ideNone),
|
||||
# so re-arm the leaking-temporary assert for it as in a real compile.
|
||||
if c.config.cmd != cmdCheck or c.config.ideCmd != ideNone:
|
||||
if c.prc.regInfo[i].inUse and c.prc.regInfo[i].kind in {slotTempUnknown,
|
||||
slotTempInt,
|
||||
slotTempFloat,
|
||||
@@ -1598,9 +1600,11 @@ proc setSlot(c: PCtx; v: PSym) =
|
||||
v.positionImpl = getFreeRegister(c, if v.kind == skLet: slotFixedLet else: slotFixedVar, start = 1)
|
||||
|
||||
template cannotEval(c: PCtx; n: PNode) =
|
||||
if c.config.cmd == cmdCheck and c.config.m.errorOutputs != {}:
|
||||
if c.config.cmd == cmdCheck and c.config.ideCmd == ideNone and c.config.m.errorOutputs != {}:
|
||||
# nim check command with no error outputs doesn't need to cascade here,
|
||||
# includes `tryConstExpr` case which should not continue generating code
|
||||
# includes `tryConstExpr` case which should not continue generating code.
|
||||
# A `--def`/`--usages` query (ideCmd != ideNone) falls through to the hard
|
||||
# `globalError` below so its compile-time evaluation is faithful.
|
||||
localError(c.config, n.info, "cannot evaluate at compile time: " & n.renderTree)
|
||||
c.cannotEval = true
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user