mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-18 00:48:35 +00:00
--stdout support; idetools implemented
This commit is contained in:
@@ -1,22 +1,28 @@
|
||||
Advanced commands:
|
||||
//compileToC, cc compile project with C code generator
|
||||
//compileToOC, oc compile project to Objective C code
|
||||
//rst2html converts a reStructuredText file to HTML
|
||||
//rst2tex converts a reStructuredText file to TeX
|
||||
//run run the project (with Tiny C backend; Linux only!)
|
||||
//rst2html convert a reStructuredText file to HTML
|
||||
//rst2tex convert a reStructuredText file to TeX
|
||||
//run run the project (with Tiny C backend; buggy!)
|
||||
//pretty pretty print the inputfile
|
||||
//genDepend generate a DOT file containing the
|
||||
module dependency graph
|
||||
//listDef list all defined conditionals and exit
|
||||
//dump dump all defined conditionals and search paths
|
||||
//check checks the project for syntax and semantic
|
||||
//parse parses a single file (for debugging Nimrod)
|
||||
//idetools compiler support for IDEs: possible options:
|
||||
--track:FILE,LINE,COL track a file/cursor position
|
||||
--suggest suggest all possible symbols at position
|
||||
--def list all possible symbols at position
|
||||
--context list possible invokation context
|
||||
|
||||
Advanced options:
|
||||
-o, --out:FILE set the output filename
|
||||
--stdout output to stdout
|
||||
-w, --warnings:on|off turn all warnings on|off
|
||||
--warning[X]:on|off turn specific warning X on|off
|
||||
--hints:on|off turn all hints on|off
|
||||
--hint[X]:on|off turn specific hint X on|off
|
||||
--lib:PATH set the path to the system.nim library
|
||||
--lib:PATH set the system library path
|
||||
-c, --compileOnly compile only; do not assemble or link
|
||||
--noLinking compile but do not link
|
||||
--noMain do not generate a main procedure
|
||||
@@ -35,10 +41,11 @@ Advanced options:
|
||||
--skipCfg do not read the general configuration file
|
||||
--skipProjCfg do not read the project's configuration file
|
||||
--gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC
|
||||
--index:FILE use FILE to generate a documenation index file
|
||||
--index:FILE use FILE to generate a documentation index file
|
||||
--putenv:key=value set an environment variable
|
||||
--listCmd list the commands used to execute external programs
|
||||
--parallelBuild=0|1|... perform a parallel build
|
||||
value = number of processors (0 for auto-detect)
|
||||
--verbosity:0|1|2|3 set Nimrod's verbosity level (0 is default)
|
||||
-v, --version show detailed version information
|
||||
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
Usage::
|
||||
nimrod command [options] inputfile [arguments]
|
||||
nimrod command [options] [projectfile] [arguments]
|
||||
|
||||
Command:
|
||||
//compile, c compile project with default code generator (C)
|
||||
//doc generate the documentation for inputfile
|
||||
//i start Nimrod in interactive mode (limited)
|
||||
|
||||
//compile, c compile project with default code generator (C)
|
||||
//doc generate the documentation for inputfile
|
||||
//i start Nimrod in interactive mode (limited)
|
||||
|
||||
Arguments:
|
||||
arguments are passed to the program being run (if --run option is selected)
|
||||
Options:
|
||||
-p, --path:PATH add path to search paths
|
||||
-o, --out:FILE set the output filename
|
||||
-d, --define:SYMBOL define a conditional symbol
|
||||
-u, --undef:SYMBOL undefine a conditional symbol
|
||||
-f, --forceBuild force rebuilding of all modules
|
||||
@@ -33,3 +32,4 @@ Options:
|
||||
-r, --run run the compiled program with given arguments
|
||||
--advanced show advanced command line switches
|
||||
-h, --help show this help
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@ Arguments:
|
||||
arguments are passed to the program being run (if --run option is selected)
|
||||
Options:
|
||||
-p, --path:PATH add path to search paths
|
||||
-o, --out:FILE set the output filename
|
||||
-d, --define:SYMBOL define a conditional symbol
|
||||
-u, --undef:SYMBOL undefine a conditional symbol
|
||||
-f, --forceBuild force rebuilding of all modules
|
||||
@@ -70,17 +69,22 @@ Options:
|
||||
Advanced commands:
|
||||
compileToC, cc compile project with C code generator
|
||||
compileToOC, oc compile project to Objective C code
|
||||
rst2html converts a reStructuredText file to HTML
|
||||
rst2tex converts a reStructuredText file to TeX
|
||||
rst2html convert a reStructuredText file to HTML
|
||||
rst2tex convert a reStructuredText file to TeX
|
||||
run run the project (with Tiny C backend; buggy!)
|
||||
pretty pretty print the inputfile
|
||||
genDepend generate a DOT file containing the
|
||||
module dependency graph
|
||||
listDef list all defined conditionals and exit
|
||||
dump dump all defined conditionals and search paths
|
||||
check checks the project for syntax and semantic
|
||||
suggest list all possible symbols at position;
|
||||
use with --track option
|
||||
idetools compiler support for IDEs: possible options:
|
||||
--track:FILE,LINE,COL track a file/cursor position
|
||||
--suggest suggest all possible symbols at position
|
||||
--def list all possible symbols at position
|
||||
--context list possible invokation context
|
||||
Advanced options:
|
||||
-o, --out:FILE set the output filename
|
||||
--stdout output to stdout
|
||||
-w, --warnings:on|off turn all warnings on|off
|
||||
--warning[X]:on|off turn specific warning X on|off
|
||||
--hints:on|off turn all hints on|off
|
||||
@@ -104,9 +108,8 @@ Advanced options:
|
||||
--skipCfg do not read the general configuration file
|
||||
--skipProjCfg do not read the project's configuration file
|
||||
--gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC
|
||||
--index:FILE use FILE to generate a documenation index file
|
||||
--index:FILE use FILE to generate a documentation index file
|
||||
--putenv:key=value set an environment variable
|
||||
--track:FILE,LINE,COLUMN track a file position for 'suggest'
|
||||
--listCmd list the commands used to execute external programs
|
||||
--parallelBuild=0|1|... perform a parallel build
|
||||
value = number of processors (0 for auto-detect)
|
||||
@@ -415,9 +418,6 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||
excl(gGlobalOptions, optGenGuiApp)
|
||||
defineSymbol("library")
|
||||
else: LocalError(info, errGuiConsoleOrLibExpectedButXFound, arg)
|
||||
of wListDef:
|
||||
expectNoArg(switch, arg, pass, info)
|
||||
if pass in {passCmd2, passPP}: condsyms.listSymbols()
|
||||
of wPassC, wT:
|
||||
expectArg(switch, arg, pass, info)
|
||||
if pass in {passCmd2, passPP}: extccomp.addCompileOption(arg)
|
||||
@@ -496,6 +496,18 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||
of wTrack:
|
||||
expectArg(switch, arg, pass, info)
|
||||
track(arg, info)
|
||||
of wSuggest:
|
||||
expectNoArg(switch, arg, pass, info)
|
||||
incl(gGlobalOptions, optSuggest)
|
||||
of wDef:
|
||||
expectNoArg(switch, arg, pass, info)
|
||||
incl(gGlobalOptions, optDef)
|
||||
of wContext:
|
||||
expectNoArg(switch, arg, pass, info)
|
||||
incl(gGlobalOptions, optContext)
|
||||
of wStdout:
|
||||
expectNoArg(switch, arg, pass, info)
|
||||
incl(gGlobalOptions, optStdout)
|
||||
else:
|
||||
if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg)
|
||||
else: InvalidCmdLineOption(pass, switch, info)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
||||
@@ -857,6 +857,13 @@ proc generateIndex(d: PDoc) =
|
||||
sortIndex(d.theIndex)
|
||||
writeRope(renderRstToRst(d, d.indexFile), gIndexFile)
|
||||
|
||||
proc writeOutput(d: PDoc, filename, outExt: string) =
|
||||
var content = genOutFile(d)
|
||||
if optStdout in gGlobalOptions:
|
||||
writeRope(stdout, content)
|
||||
else:
|
||||
writeRope(content, getOutFile(filename, outExt))
|
||||
|
||||
proc CommandDoc(filename: string) =
|
||||
var ast = parseFile(addFileExt(filename, nimExt))
|
||||
if ast == nil: return
|
||||
@@ -864,7 +871,7 @@ proc CommandDoc(filename: string) =
|
||||
initIndexFile(d)
|
||||
d.hasToc = true
|
||||
generateDoc(d, ast)
|
||||
writeRope(genOutFile(d), getOutFile(filename, HtmlExt))
|
||||
writeOutput(d, filename, HtmlExt)
|
||||
generateIndex(d)
|
||||
|
||||
proc CommandRstAux(filename, outExt: string) =
|
||||
@@ -873,8 +880,7 @@ proc CommandRstAux(filename, outExt: string) =
|
||||
initIndexFile(d)
|
||||
var rst = rstParse(readFile(filen), false, filen, 0, 1, d.hasToc)
|
||||
d.modDesc = renderRstToOut(d, rst)
|
||||
var code = genOutFile(d)
|
||||
writeRope(code, getOutFile(filename, outExt))
|
||||
writeOutput(d, filename, outExt)
|
||||
generateIndex(d)
|
||||
|
||||
proc CommandRst2Html(filename: string) =
|
||||
|
||||
11
rod/main.nim
11
rod/main.nim
@@ -251,9 +251,10 @@ proc MainCommand(cmd, filename: string) =
|
||||
gCmd = cmdGenDepend
|
||||
wantFile(filename)
|
||||
CommandGenDepend(filename)
|
||||
of wListDef:
|
||||
gCmd = cmdListDef
|
||||
of wDump:
|
||||
gCmd = cmdDump
|
||||
condsyms.ListSymbols()
|
||||
for it in iterSearchPath(): MessageOut(it)
|
||||
of wCheck:
|
||||
gCmd = cmdCheck
|
||||
wantFile(filename)
|
||||
@@ -270,9 +271,9 @@ proc MainCommand(cmd, filename: string) =
|
||||
of wI:
|
||||
gCmd = cmdInteractive
|
||||
CommandInteractive()
|
||||
of wSuggest:
|
||||
gCmd = cmdSuggest
|
||||
of wIdeTools:
|
||||
gCmd = cmdIdeTools
|
||||
wantFile(filename)
|
||||
CommandSuggest(filename)
|
||||
else: rawMessage(errInvalidCommandX, cmd)
|
||||
|
||||
|
||||
|
||||
@@ -42,15 +42,21 @@ type # please make sure we have under 32 options
|
||||
optSkipConfigFile, # skip the general config file
|
||||
optSkipProjConfigFile, # skip the project's config file
|
||||
optNoMain, # do not generate a "main" proc
|
||||
optThreads # support for multi-threading
|
||||
optThreads, # support for multi-threading
|
||||
optStdout, # output to stdout
|
||||
optSuggest, # ideTools: 'suggest'
|
||||
optContext, # ideTools: 'context'
|
||||
optDef # ideTools: 'def'
|
||||
TGlobalOptions* = set[TGlobalOption]
|
||||
TCommands* = enum # Nimrod's commands
|
||||
cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
|
||||
cmdCompileToEcmaScript, cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc,
|
||||
cmdGenDepend, cmdListDef, cmdCheck, # semantic checking for whole project
|
||||
cmdGenDepend, cmdDump,
|
||||
cmdCheck, # semantic checking for whole project
|
||||
cmdParse, # parse a single file (for debugging)
|
||||
cmdScan, # scan a single file (for debugging)
|
||||
cmdSuggest, # suggest feature (auto-completion for IDEs)
|
||||
cmdIdeTools, # ide tools
|
||||
cmdDef, # def feature (find definition for IDEs)
|
||||
cmdRst2html, # convert a reStructuredText file to HTML
|
||||
cmdRst2tex, # convert a reStructuredText file to TeX
|
||||
cmdInteractive, # start interactive session
|
||||
@@ -121,8 +127,7 @@ proc getOutFile*(filename, ext: string): string =
|
||||
else: result = changeFileExt(filename, ext)
|
||||
|
||||
proc addImplicitMod(filename: string) =
|
||||
var length: int
|
||||
length = len(gImplicitMods)
|
||||
var length = len(gImplicitMods)
|
||||
setlen(gImplicitMods, length + 1)
|
||||
gImplicitMods[length] = filename
|
||||
|
||||
@@ -166,15 +171,19 @@ proc completeGeneratedFilePath(f: string, createSubDir: bool = true): string =
|
||||
quit(1)
|
||||
result = joinPath(subdir, tail)
|
||||
|
||||
iterator iterSearchPath*(): string =
|
||||
var it = PStrEntry(SearchPaths.head)
|
||||
while it != nil:
|
||||
yield it.data
|
||||
it = PStrEntry(it.Next)
|
||||
|
||||
proc rawFindFile(f: string): string =
|
||||
if ExistsFile(f):
|
||||
result = f
|
||||
else:
|
||||
var it = PStrEntry(SearchPaths.head)
|
||||
while it != nil:
|
||||
result = JoinPath(it.data, f)
|
||||
if ExistsFile(result): return
|
||||
it = PStrEntry(it.Next)
|
||||
for it in iterSearchPath():
|
||||
result = JoinPath(it, f)
|
||||
if ExistsFile(result): return
|
||||
result = ""
|
||||
|
||||
proc FindFile(f: string): string =
|
||||
|
||||
@@ -1058,9 +1058,13 @@ proc renderModule(n: PNode, filename: string, renderFlags: TRenderFlags = {}) =
|
||||
of nkTypeSection, nkConstSection, nkVarSection, nkCommentStmt: putNL(g)
|
||||
else: nil
|
||||
gcoms(g)
|
||||
if open(f, filename, fmWrite):
|
||||
if optStdout in gGlobalOptions:
|
||||
write(stdout, g.buf)
|
||||
elif open(f, filename, fmWrite):
|
||||
write(f, g.buf)
|
||||
close(f)
|
||||
else:
|
||||
rawMessage(errCannotOpenFile, filename)
|
||||
|
||||
proc initTokRender(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {}) =
|
||||
initSrcGen(r, renderFlags)
|
||||
|
||||
@@ -274,15 +274,7 @@ proc app(a: var PRope, b: PRope) = a = con(a, b)
|
||||
proc app(a: var PRope, b: string) = a = con(a, b)
|
||||
proc prepend(a: var PRope, b: PRope) = a = con(b, a)
|
||||
|
||||
proc WriteRopeRec(f: var tfile, c: PRope) =
|
||||
if c == nil: return
|
||||
if (c.data != nil):
|
||||
write(f, c.data)
|
||||
else:
|
||||
writeRopeRec(f, c.left)
|
||||
writeRopeRec(f, c.right)
|
||||
|
||||
proc newWriteRopeRec(f: var tfile, c: PRope) =
|
||||
proc writeRope*(f: var tfile, c: PRope) =
|
||||
var stack = @[c]
|
||||
while len(stack) > 0:
|
||||
var it = pop(stack)
|
||||
@@ -296,7 +288,7 @@ proc newWriteRopeRec(f: var tfile, c: PRope) =
|
||||
proc WriteRope(head: PRope, filename: string) =
|
||||
var f: tfile # we use a textfile for automatic buffer handling
|
||||
if open(f, filename, fmWrite):
|
||||
if head != nil: newWriteRopeRec(f, head)
|
||||
if head != nil: WriteRope(f, head)
|
||||
close(f)
|
||||
else:
|
||||
rawMessage(errCannotOpenFile, filename)
|
||||
|
||||
@@ -953,7 +953,7 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
|
||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
result = n
|
||||
if gCmd == cmdSuggest:
|
||||
if gCmd == cmdIdeTools:
|
||||
suggestExpr(c, n)
|
||||
if nfSem in n.flags: return
|
||||
case n.kind # atoms:
|
||||
|
||||
@@ -67,7 +67,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
|
||||
L: int
|
||||
a: PNode
|
||||
result = n
|
||||
if gCmd == cmdSuggest: suggestStmt(c, n)
|
||||
if gCmd == cmdIdeTools: suggestStmt(c, n)
|
||||
case n.kind
|
||||
of nkIdent:
|
||||
var s = SymtabGet(c.Tab, n.ident)
|
||||
|
||||
@@ -275,7 +275,7 @@ proc semVar(c: PContext, n: PNode): PNode =
|
||||
result = copyNode(n)
|
||||
for i in countup(0, sonsLen(n)-1):
|
||||
var a = n.sons[i]
|
||||
if gCmd == cmdSuggest: suggestStmt(c, a)
|
||||
if gCmd == cmdIdeTools: suggestStmt(c, a)
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): IllFormedAst(a)
|
||||
checkMinSonsLen(a, 3)
|
||||
@@ -332,7 +332,7 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||
result = copyNode(n)
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var a = n.sons[i]
|
||||
if gCmd == cmdSuggest: suggestStmt(c, a)
|
||||
if gCmd == cmdIdeTools: suggestStmt(c, a)
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if (a.kind != nkConstDef): IllFormedAst(a)
|
||||
checkSonsLen(a, 3)
|
||||
@@ -485,7 +485,7 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
|
||||
# we even look at the type definitions on the right
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var a = n.sons[i]
|
||||
if gCmd == cmdSuggest: suggestStmt(c, a)
|
||||
if gCmd == cmdIdeTools: suggestStmt(c, a)
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if a.kind != nkTypeDef: IllFormedAst(a)
|
||||
checkSonsLen(a, 3)
|
||||
@@ -795,7 +795,7 @@ proc SemStmt(c: PContext, n: PNode): PNode =
|
||||
const # must be last statements in a block:
|
||||
LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
|
||||
result = n
|
||||
if gCmd == cmdSuggest:
|
||||
if gCmd == cmdIdeTools:
|
||||
suggestStmt(c, n)
|
||||
if nfSem in n.flags: return
|
||||
case n.kind
|
||||
|
||||
@@ -566,6 +566,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
s: PSym
|
||||
t: PType
|
||||
result = nil
|
||||
if gCmd == cmdIdeTools: suggestExpr(c, n)
|
||||
case n.kind
|
||||
of nkEmpty: nil
|
||||
of nkTypeOfExpr:
|
||||
|
||||
131
rod/suggest.nim
131
rod/suggest.nim
@@ -9,13 +9,17 @@
|
||||
|
||||
## This file implements features required for IDE support.
|
||||
|
||||
import scanner, idents, ast, astalgo, semdata, msgs, types, sigmatch
|
||||
import scanner, idents, ast, astalgo, semdata, msgs, types, sigmatch, options
|
||||
|
||||
const
|
||||
sep = '\t'
|
||||
sectionSuggest = "sug"
|
||||
sectionDef = "def"
|
||||
sectionContext = "con"
|
||||
|
||||
proc SymToStr(s: PSym, isLocal: bool): string =
|
||||
result = ""
|
||||
proc SymToStr(s: PSym, isLocal: bool, section: string): string =
|
||||
result = section
|
||||
result.add(sep)
|
||||
result.add($s.kind)
|
||||
result.add(sep)
|
||||
if not isLocal:
|
||||
@@ -38,13 +42,13 @@ proc filterSym(s: PSym): bool {.inline.} =
|
||||
|
||||
proc suggestField(s: PSym) =
|
||||
if filterSym(s):
|
||||
MessageOut(SymToStr(s, isLocal=true))
|
||||
MessageOut(SymToStr(s, isLocal=true, sectionSuggest))
|
||||
|
||||
template wholeSymTab(cond: expr) =
|
||||
template wholeSymTab(cond, section: expr) =
|
||||
for i in countdown(c.tab.tos-1, 0):
|
||||
for it in items(c.tab.stack[i]):
|
||||
if cond:
|
||||
MessageOut(SymToStr(it, isLocal = i > ModuleTablePos))
|
||||
MessageOut(SymToStr(it, isLocal = i > ModuleTablePos, section))
|
||||
|
||||
proc suggestSymList(list: PNode) =
|
||||
for i in countup(0, sonsLen(list) - 1):
|
||||
@@ -86,7 +90,8 @@ proc argsFit(c: PContext, candidate: PSym, n: PNode): bool =
|
||||
result = false
|
||||
|
||||
proc suggestCall(c: PContext, n: PNode) =
|
||||
wholeSymTab(filterSym(it) and nameFits(c, it, n) and argsFit(c, it, n))
|
||||
wholeSymTab(filterSym(it) and nameFits(c, it, n) and argsFit(c, it, n),
|
||||
sectionContext)
|
||||
|
||||
proc typeFits(c: PContext, s: PSym, firstArg: PType): bool {.inline.} =
|
||||
if s.typ != nil and sonsLen(s.typ) > 1 and s.typ.sons[1] != nil:
|
||||
@@ -94,10 +99,10 @@ proc typeFits(c: PContext, s: PSym, firstArg: PType): bool {.inline.} =
|
||||
|
||||
proc suggestOperations(c: PContext, n: PNode, typ: PType) =
|
||||
assert typ != nil
|
||||
wholeSymTab(filterSym(it) and typeFits(c, it, typ))
|
||||
wholeSymTab(filterSym(it) and typeFits(c, it, typ), sectionSuggest)
|
||||
|
||||
proc suggestEverything(c: PContext, n: PNode) =
|
||||
wholeSymTab(filterSym(it))
|
||||
wholeSymTab(filterSym(it), sectionSuggest)
|
||||
|
||||
proc suggestFieldAccess(c: PContext, n: PNode) =
|
||||
# special code that deals with ``myObj.``. `n` is NOT the nkDotExpr-node, but
|
||||
@@ -109,10 +114,12 @@ proc suggestFieldAccess(c: PContext, n: PNode) =
|
||||
if n.sym == c.module:
|
||||
# all symbols accessible, because we are in the current module:
|
||||
for it in items(c.tab.stack[ModuleTablePos]):
|
||||
if filterSym(it): MessageOut(SymToStr(it, isLocal=false))
|
||||
if filterSym(it):
|
||||
MessageOut(SymToStr(it, isLocal=false, sectionSuggest))
|
||||
else:
|
||||
for it in items(n.sym.tab):
|
||||
if filterSym(it): MessageOut(SymToStr(it, isLocal=false))
|
||||
if filterSym(it):
|
||||
MessageOut(SymToStr(it, isLocal=false, sectionSuggest))
|
||||
else:
|
||||
# fallback:
|
||||
suggestEverything(c, n)
|
||||
@@ -139,55 +146,89 @@ proc suggestFieldAccess(c: PContext, n: PNode) =
|
||||
# fallback:
|
||||
suggestEverything(c, n)
|
||||
|
||||
proc interestingNode(n: PNode): bool {.inline.} =
|
||||
result = n.kind == nkDotExpr
|
||||
|
||||
proc findClosestNode(n: PNode): PNode =
|
||||
proc findClosestDot(n: PNode): PNode =
|
||||
if msgs.inCheckpoint(n.info) == cpExact:
|
||||
result = n
|
||||
elif n.kind notin {nkNone..nkNilLit}:
|
||||
for i in 0.. <sonsLen(n):
|
||||
if interestingNode(n.sons[i]):
|
||||
result = findClosestNode(n.sons[i])
|
||||
if n.sons[i].kind == nkDotExpr:
|
||||
result = findClosestDot(n.sons[i])
|
||||
if result != nil: return
|
||||
|
||||
const
|
||||
CallNodes = {nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit,
|
||||
nkMacroStmt}
|
||||
|
||||
proc findClosestCall(n: PNode): PNode =
|
||||
if msgs.inCheckpoint(n.info) == cpExact:
|
||||
result = n
|
||||
elif n.kind notin {nkNone..nkNilLit}:
|
||||
for i in 0.. <sonsLen(n):
|
||||
if n.sons[i].kind in callNodes:
|
||||
result = findClosestCall(n.sons[i])
|
||||
if result != nil: return
|
||||
|
||||
proc findClosestSym(n: PNode): PNode =
|
||||
if n.kind == nkSym and msgs.inCheckpoint(n.info) == cpExact:
|
||||
result = n
|
||||
elif n.kind notin {nkNone..nkNilLit}:
|
||||
for i in 0.. <sonsLen(n):
|
||||
result = findClosestSym(n.sons[i])
|
||||
if result != nil: return
|
||||
|
||||
var recursiveCheck = 0
|
||||
|
||||
proc safeSemExpr(c: PContext, n: PNode): PNode =
|
||||
try:
|
||||
result = c.semExpr(c, n)
|
||||
except ERecoverableError:
|
||||
result = ast.emptyNode
|
||||
|
||||
proc fuzzySemCheck(c: PContext, n: PNode): PNode =
|
||||
result = safeSemExpr(c, n)
|
||||
if result == nil or result.kind == nkEmpty:
|
||||
result = newNodeI(n.kind, n.info)
|
||||
if n.kind notin {nkNone..nkNilLit}:
|
||||
for i in 0 .. < sonsLen(n): result.addSon(fuzzySemCheck(c, n.sons[i]))
|
||||
|
||||
proc suggestExpr*(c: PContext, node: PNode) =
|
||||
var cp = msgs.inCheckpoint(node.info)
|
||||
if cp == cpNone: return
|
||||
# HACK: This keeps semExpr() from coming here recursively:
|
||||
if recursiveCheck > 0: return
|
||||
inc(recursiveCheck)
|
||||
var n = findClosestNode(node)
|
||||
if n == nil: n = node
|
||||
else: cp = msgs.inCheckpoint(n.info)
|
||||
block:
|
||||
case n.kind
|
||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand,
|
||||
nkCallStrLit, nkMacroStmt:
|
||||
when false:
|
||||
# this provides "context information", not "type suggestion":
|
||||
var a = copyNode(n)
|
||||
var x = c.semExpr(c, n.sons[0])
|
||||
if x.kind == nkEmpty or x.typ == nil: x = n.sons[0]
|
||||
|
||||
if optSuggest in gGlobalOptions:
|
||||
var n = findClosestDot(node)
|
||||
if n == nil: n = node
|
||||
else: cp = cpExact
|
||||
|
||||
if n.kind == nkDotExpr and cp == cpExact:
|
||||
var obj = safeSemExpr(c, n.sons[0])
|
||||
suggestFieldAccess(c, obj)
|
||||
else:
|
||||
suggestEverything(c, n)
|
||||
|
||||
if optContext in gGlobalOptions:
|
||||
var n = findClosestCall(node)
|
||||
if n == nil: n = node
|
||||
else: cp = cpExact
|
||||
|
||||
if n.kind in CallNodes:
|
||||
var a = copyNode(n)
|
||||
var x = safeSemExpr(c, n.sons[0])
|
||||
if x.kind == nkEmpty or x.typ == nil: x = n.sons[0]
|
||||
addSon(a, x)
|
||||
for i in 1..sonsLen(n)-1:
|
||||
# use as many typed arguments as possible:
|
||||
var x = safeSemExpr(c, n.sons[i])
|
||||
if x.kind == nkEmpty or x.typ == nil: break
|
||||
addSon(a, x)
|
||||
for i in 1..sonsLen(n)-1:
|
||||
# use as many typed arguments as possible:
|
||||
var x = c.semExpr(c, n.sons[i])
|
||||
if x.kind == nkEmpty or x.typ == nil: break
|
||||
addSon(a, x)
|
||||
suggestCall(c, a)
|
||||
break
|
||||
else:
|
||||
nil
|
||||
of nkDotExpr:
|
||||
if cp == cpExact:
|
||||
var obj = c.semExpr(c, n.sons[0])
|
||||
suggestFieldAccess(c, obj)
|
||||
break
|
||||
else: nil
|
||||
suggestEverything(c, n)
|
||||
suggestCall(c, a)
|
||||
|
||||
if optDef in gGlobalOptions:
|
||||
var n = findClosestSym(fuzzySemCheck(c, node))
|
||||
if n != nil: MessageOut(SymToStr(n.sym, isLocal=false, sectionDef))
|
||||
quit(0)
|
||||
|
||||
proc suggestStmt*(c: PContext, n: PNode) =
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# Implements the dispatcher for the different parsers.
|
||||
## Implements the dispatcher for the different parsers.
|
||||
|
||||
import
|
||||
strutils, llstream, ast, astalgo, idents, scanner, options, msgs, pnimsyn,
|
||||
|
||||
@@ -57,10 +57,12 @@ type
|
||||
wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM,
|
||||
wCompileToOC,
|
||||
wPretty,
|
||||
wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wJs, wOC,
|
||||
wDoc, wGenDepend, wDump, wCheck, wParse, wScan, wJs, wOC,
|
||||
wRst2html, wRst2tex, wI,
|
||||
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit, wThreads,
|
||||
wRecursivePath, wSuggest, wTrack
|
||||
wRecursivePath,
|
||||
wStdout,
|
||||
wIdeTools, wSuggest, wTrack, wDef, wContext
|
||||
|
||||
TSpecialWords* = set[TSpecialWord]
|
||||
|
||||
@@ -106,10 +108,12 @@ const
|
||||
"nomain", "subschar", "acyclic", "index",
|
||||
"compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm",
|
||||
"compiletooc",
|
||||
"pretty", "doc", "gendepend", "listdef", "check", "parse", "scan",
|
||||
"pretty", "doc", "gendepend", "dump", "check", "parse", "scan",
|
||||
"js", "oc", "rst2html", "rst2tex", "i",
|
||||
"write", "putenv", "prependenv", "appendenv", "threadvar", "emit",
|
||||
"threads", "recursivepath", "suggest", "track"]
|
||||
"threads", "recursivepath",
|
||||
"stdout",
|
||||
"idetools", "suggest", "track", "def", "context"]
|
||||
|
||||
proc whichKeyword*(id: PIdent): TSpecialWord
|
||||
proc whichKeyword*(id: String): TSpecialWord
|
||||
|
||||
Reference in New Issue
Block a user