mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-04 02:44:44 +00:00
made compiler more robust for idetools; implemented idetools.usages
This commit is contained in:
@@ -455,7 +455,10 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||
of "context":
|
||||
expectNoArg(switch, arg, pass, info)
|
||||
incl(gGlobalOptions, optContext)
|
||||
of "stdout":
|
||||
of "usages":
|
||||
expectNoArg(switch, arg, pass, info)
|
||||
incl(gGlobalOptions, optUsages)
|
||||
of "stdout":
|
||||
expectNoArg(switch, arg, pass, info)
|
||||
incl(gGlobalOptions, optStdout)
|
||||
else:
|
||||
|
||||
@@ -31,7 +31,9 @@ proc cardSet*(s: PNode): BiggestInt
|
||||
# implementation
|
||||
|
||||
proc inSet(s: PNode, elem: PNode): bool =
|
||||
if s.kind != nkCurly: InternalError(s.info, "inSet")
|
||||
if s.kind != nkCurly:
|
||||
InternalError(s.info, "inSet")
|
||||
return false
|
||||
for i in countup(0, sonsLen(s) - 1):
|
||||
if s.sons[i].kind == nkRange:
|
||||
if leValue(s.sons[i].sons[0], elem) and
|
||||
@@ -48,17 +50,19 @@ proc overlap(a, b: PNode): bool =
|
||||
result = leValue(a.sons[0], b.sons[1]) and
|
||||
leValue(b.sons[1], a.sons[1]) or
|
||||
leValue(a.sons[0], b.sons[0]) and leValue(b.sons[0], a.sons[1])
|
||||
else:
|
||||
else:
|
||||
result = leValue(a.sons[0], b) and leValue(b, a.sons[1])
|
||||
else:
|
||||
if b.kind == nkRange:
|
||||
else:
|
||||
if b.kind == nkRange:
|
||||
result = leValue(b.sons[0], a) and leValue(a, b.sons[1])
|
||||
else:
|
||||
else:
|
||||
result = sameValue(a, b)
|
||||
|
||||
proc SomeInSet(s: PNode, a, b: PNode): bool =
|
||||
# checks if some element of a..b is in the set s
|
||||
if s.kind != nkCurly: InternalError(s.info, "SomeInSet")
|
||||
if s.kind != nkCurly:
|
||||
InternalError(s.info, "SomeInSet")
|
||||
return false
|
||||
for i in countup(0, sonsLen(s) - 1):
|
||||
if s.sons[i].kind == nkRange:
|
||||
if leValue(s.sons[i].sons[0], b) and leValue(b, s.sons[i].sons[1]) or
|
||||
@@ -164,7 +168,9 @@ proc cardSet(s: PNode): BiggestInt =
|
||||
Inc(result)
|
||||
|
||||
proc SetHasRange(s: PNode): bool =
|
||||
if s.kind != nkCurly: InternalError(s.info, "SetHasRange")
|
||||
if s.kind != nkCurly:
|
||||
InternalError(s.info, "SetHasRange")
|
||||
return false
|
||||
for i in countup(0, sonsLen(s) - 1):
|
||||
if s.sons[i].kind == nkRange:
|
||||
return true
|
||||
|
||||
@@ -51,6 +51,7 @@ type # please make sure we have under 32 options
|
||||
optSuggest, # ideTools: 'suggest'
|
||||
optContext, # ideTools: 'context'
|
||||
optDef, # ideTools: 'def'
|
||||
optUsages, # ideTools: 'usages'
|
||||
optThreadAnalysis, # thread analysis pass
|
||||
optTaintMode, # taint mode turned on
|
||||
optTlsEmulation, # thread var emulation turned on
|
||||
|
||||
@@ -338,7 +338,9 @@ proc atom(n: PNode): string =
|
||||
of nkType:
|
||||
if (n.typ != nil) and (n.typ.sym != nil): result = n.typ.sym.name.s
|
||||
else: result = "[type node]"
|
||||
else: InternalError("rnimsyn.atom " & $n.kind)
|
||||
else:
|
||||
InternalError("rnimsyn.atom " & $n.kind)
|
||||
result = ""
|
||||
|
||||
proc lcomma(n: PNode, start: int = 0, theEnd: int = - 1): int =
|
||||
assert(theEnd < 0)
|
||||
|
||||
@@ -146,14 +146,16 @@ proc PushOwner(owner: PSym) =
|
||||
|
||||
proc PopOwner() =
|
||||
var length = len(gOwners)
|
||||
if (length <= 0): InternalError("popOwner")
|
||||
setlen(gOwners, length - 1)
|
||||
if length > 0: setlen(gOwners, length - 1)
|
||||
else: InternalError("popOwner")
|
||||
|
||||
proc lastOptionEntry(c: PContext): POptionEntry =
|
||||
result = POptionEntry(c.optionStack.tail)
|
||||
|
||||
proc pushProcCon*(c: PContext, owner: PSym) {.inline.} =
|
||||
if owner == nil: InternalError("owner is nil")
|
||||
if owner == nil:
|
||||
InternalError("owner is nil")
|
||||
return
|
||||
var x: PProcCon
|
||||
new(x)
|
||||
x.owner = owner
|
||||
|
||||
@@ -118,8 +118,10 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
LocalError(n.info, errIllegalCaptureX, s.name.s)
|
||||
result = newSymNode(s, n.info)
|
||||
of skGenericParam:
|
||||
if s.ast == nil: InternalError(n.info, "no default for")
|
||||
result = semExpr(c, s.ast)
|
||||
if s.ast != nil: result = semExpr(c, s.ast)
|
||||
else:
|
||||
InternalError(n.info, "no default for")
|
||||
result = emptyNode
|
||||
of skType:
|
||||
markUsed(n, s)
|
||||
result = newSymNode(s, n.info)
|
||||
@@ -322,14 +324,17 @@ proc changeType(n: PNode, newType: PType) =
|
||||
of nkPar:
|
||||
if newType.kind != tyTuple:
|
||||
InternalError(n.info, "changeType: no tuple type for constructor")
|
||||
if newType.n == nil: nil
|
||||
elif newType.n == nil: nil
|
||||
elif sonsLen(n) > 0 and n.sons[0].kind == nkExprColonExpr:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var m = n.sons[i].sons[0]
|
||||
if m.kind != nkSym:
|
||||
internalError(m.info, "changeType(): invalid tuple constr")
|
||||
return
|
||||
var f = getSymFromList(newType.n, m.sym.name)
|
||||
if f == nil: internalError(m.info, "changeType(): invalid identifier")
|
||||
if f == nil:
|
||||
internalError(m.info, "changeType(): invalid identifier")
|
||||
return
|
||||
changeType(n.sons[i].sons[1], f.typ)
|
||||
else:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
@@ -485,7 +490,9 @@ proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
|
||||
result = newHiddenAddrTaken(c, n)
|
||||
of nkDotExpr:
|
||||
checkSonsLen(n, 2)
|
||||
if n.sons[1].kind != nkSym: internalError(n.info, "analyseIfAddressTaken")
|
||||
if n.sons[1].kind != nkSym:
|
||||
internalError(n.info, "analyseIfAddressTaken")
|
||||
return
|
||||
if skipTypes(n.sons[1].sym.typ, abstractInst).kind != tyVar:
|
||||
incl(n.sons[1].sym.flags, sfAddrTaken)
|
||||
result = newHiddenAddrTaken(c, n)
|
||||
@@ -590,6 +597,7 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||
if result != nil:
|
||||
if result.sons[0].kind != nkSym:
|
||||
InternalError("semDirectCallAnalyseEffects")
|
||||
return
|
||||
let callee = result.sons[0].sym
|
||||
case callee.kind
|
||||
of skMacro, skTemplate: nil
|
||||
@@ -1225,8 +1233,8 @@ proc semIfExpr(c: PContext, n: PNode): PNode =
|
||||
of nkElseExpr:
|
||||
checkSonsLen(it, 1)
|
||||
it.sons[0] = semExprWithType(c, it.sons[0])
|
||||
if typ == nil: InternalError(it.info, "semIfExpr")
|
||||
it.sons[0] = fitNode(c, typ, it.sons[0])
|
||||
if typ != nil: it.sons[0] = fitNode(c, typ, it.sons[0])
|
||||
else: InternalError(it.info, "semIfExpr")
|
||||
else: illFormedAst(n)
|
||||
result.typ = typ
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
checkSonsLen(it, 2)
|
||||
var e = semConstExpr(c, it.sons[0])
|
||||
if e.kind != nkIntLit: InternalError(n.info, "semWhen")
|
||||
if e.intVal != 0 and result == nil:
|
||||
elif e.intVal != 0 and result == nil:
|
||||
setResult(it.sons[1])
|
||||
of nkElse, nkElseExpr:
|
||||
checkSonsLen(it, 1)
|
||||
@@ -514,8 +514,8 @@ proc addGenericParamListToScope(c: PContext, n: PNode) =
|
||||
InternalError(n.info, "addGenericParamListToScope")
|
||||
for i in countup(0, sonsLen(n)-1):
|
||||
var a = n.sons[i]
|
||||
if a.kind != nkSym: internalError(a.info, "addGenericParamListToScope")
|
||||
addDecl(c, a.sym)
|
||||
if a.kind == nkSym: addDecl(c, a.sym)
|
||||
else: internalError(a.info, "addGenericParamListToScope")
|
||||
|
||||
proc typeSectionLeftSidePass(c: PContext, n: PNode) =
|
||||
# process the symbols on the left side for the whole type section, before
|
||||
@@ -628,8 +628,8 @@ proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) =
|
||||
|
||||
proc addParams(c: PContext, n: PNode, kind: TSymKind) =
|
||||
for i in countup(1, sonsLen(n)-1):
|
||||
if (n.sons[i].kind != nkSym): InternalError(n.info, "addParams")
|
||||
addParamOrResult(c, n.sons[i].sym, kind)
|
||||
if n.sons[i].kind == nkSym: addParamOrResult(c, n.sons[i].sym, kind)
|
||||
else: InternalError(n.info, "addParams")
|
||||
|
||||
proc semBorrow(c: PContext, n: PNode, s: PSym) =
|
||||
# search for the correct alias:
|
||||
|
||||
@@ -367,7 +367,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||
checkMinSonsLen(n, 2)
|
||||
semRecordNodeAux(c, n.sons[0], check, pos, a, rectype)
|
||||
if a.sons[0].kind != nkSym:
|
||||
internalError("semRecordCase: dicriminant is no symbol")
|
||||
internalError("semRecordCase: discriminant is no symbol")
|
||||
return
|
||||
incl(a.sons[0].sym.flags, sfDiscriminant)
|
||||
var covered: biggestInt = 0
|
||||
@@ -412,7 +412,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||
if c.InGenericContext == 0:
|
||||
var e = semConstBoolExpr(c, it.sons[0])
|
||||
if e.kind != nkIntLit: InternalError(e.info, "semRecordNodeAux")
|
||||
if e.intVal != 0 and branch == nil: branch = it.sons[1]
|
||||
elif e.intVal != 0 and branch == nil: branch = it.sons[1]
|
||||
else:
|
||||
it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0]))
|
||||
of nkElse:
|
||||
@@ -735,6 +735,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
|
||||
isConcrete = false
|
||||
elif s.typ.containerID == 0:
|
||||
InternalError(n.info, "semtypes.semGeneric")
|
||||
return errorType(c)
|
||||
elif sonsLen(n) != sonsLen(s.typ):
|
||||
LocalError(n.info, errWrongNumberOfArguments)
|
||||
return errorType(c)
|
||||
@@ -930,7 +931,9 @@ proc semGenericConstraints(c: PContext, n: PNode, result: PType) =
|
||||
|
||||
proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
result = copyNode(n)
|
||||
if n.kind != nkGenericParams: InternalError(n.info, "semGenericParamList")
|
||||
if n.kind != nkGenericParams:
|
||||
InternalError(n.info, "semGenericParamList")
|
||||
return
|
||||
for i in countup(0, sonsLen(n)-1):
|
||||
var a = n.sons[i]
|
||||
if a.kind != nkIdentDefs: illFormedAst(n)
|
||||
|
||||
@@ -228,24 +228,25 @@ proc minRel(a, b: TTypeRelation): TTypeRelation =
|
||||
if a <= b: result = a
|
||||
else: result = b
|
||||
|
||||
proc tupleRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||
proc tupleRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||
result = isNone
|
||||
if sameType(f, a):
|
||||
result = isEqual
|
||||
elif sonsLen(a) == sonsLen(f):
|
||||
elif sonsLen(a) == sonsLen(f):
|
||||
result = isEqual
|
||||
for i in countup(0, sonsLen(f) - 1):
|
||||
for i in countup(0, sonsLen(f) - 1):
|
||||
var m = typeRel(c, f.sons[i], a.sons[i])
|
||||
if m < isSubtype: return isNone
|
||||
result = minRel(result, m)
|
||||
if f.n != nil and a.n != nil:
|
||||
for i in countup(0, sonsLen(f.n) - 1):
|
||||
if f.n != nil and a.n != nil:
|
||||
for i in countup(0, sonsLen(f.n) - 1):
|
||||
# check field names:
|
||||
if f.n.sons[i].kind != nkSym: InternalError(f.n.info, "tupleRel")
|
||||
if a.n.sons[i].kind != nkSym: InternalError(a.n.info, "tupleRel")
|
||||
var x = f.n.sons[i].sym
|
||||
var y = a.n.sons[i].sym
|
||||
if x.name.id != y.name.id: return isNone
|
||||
elif a.n.sons[i].kind != nkSym: InternalError(a.n.info, "tupleRel")
|
||||
else:
|
||||
var x = f.n.sons[i].sym
|
||||
var y = a.n.sons[i].sym
|
||||
if x.name.id != y.name.id: return isNone
|
||||
|
||||
proc matchTypeClass(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||
for i in countup(0, f.sonsLen - 1):
|
||||
@@ -501,7 +502,7 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||
for i in countup(1, sonsLen(f) - 1):
|
||||
if a.sons[i].kind == tyGenericParam:
|
||||
InternalError("wrong instantiated type!")
|
||||
if typeRel(c, f.sons[i], a.sons[i]) <= isSubtype: return
|
||||
elif typeRel(c, f.sons[i], a.sons[i]) <= isSubtype: return
|
||||
result = isGeneric
|
||||
else:
|
||||
result = typeRel(c, f.sons[0], a)
|
||||
@@ -539,7 +540,7 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||
result = isNone
|
||||
of tyExpr, tyStmt:
|
||||
result = isGeneric
|
||||
else: internalError("typeRel(" & $f.kind & ')')
|
||||
else: internalError("typeRel: " & $f.kind)
|
||||
|
||||
proc cmpTypes*(f, a: PType): TTypeRelation =
|
||||
var c: TCandidate
|
||||
@@ -551,7 +552,9 @@ proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
|
||||
result = PType(idTableGet(m.bindings, f))
|
||||
if result == nil:
|
||||
result = generateTypeInstance(c, m.bindings, arg, f)
|
||||
if result == nil: InternalError(arg.info, "getInstantiatedType")
|
||||
if result == nil:
|
||||
InternalError(arg.info, "getInstantiatedType")
|
||||
result = errorType(c)
|
||||
|
||||
proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
|
||||
c: PContext): PNode =
|
||||
@@ -794,6 +797,7 @@ proc matchesAux*(c: PContext, n, nOrig: PNode,
|
||||
else:
|
||||
if m.callee.n.sons[f].kind != nkSym:
|
||||
InternalError(n.sons[a].info, "matches")
|
||||
return
|
||||
formal = m.callee.n.sons[f].sym
|
||||
if ContainsOrIncl(marker, formal.position):
|
||||
# already in namedParams:
|
||||
|
||||
@@ -19,7 +19,7 @@ const
|
||||
sectionDef = "def"
|
||||
sectionContext = "con"
|
||||
|
||||
proc SymToStr(s: PSym, isLocal: bool, section: string): string =
|
||||
proc SymToStr(s: PSym, isLocal: bool, section: string, li: TLineInfo): string =
|
||||
result = section
|
||||
result.add(sep)
|
||||
result.add($s.kind)
|
||||
@@ -33,11 +33,14 @@ proc SymToStr(s: PSym, isLocal: bool, section: string): string =
|
||||
if s.typ != nil:
|
||||
result.add(typeToString(s.typ))
|
||||
result.add(sep)
|
||||
result.add(toFilename(s.info))
|
||||
result.add(toFilename(li))
|
||||
result.add(sep)
|
||||
result.add($ToLinenumber(s.info))
|
||||
result.add($ToLinenumber(li))
|
||||
result.add(sep)
|
||||
result.add($ToColumn(s.info))
|
||||
result.add($ToColumn(li))
|
||||
|
||||
proc SymToStr(s: PSym, isLocal: bool, section: string): string =
|
||||
result = SymToStr(s, isLocal, section, s.info)
|
||||
|
||||
proc filterSym(s: PSym): bool {.inline.} =
|
||||
result = s.name.s[0] in lexer.SymChars
|
||||
@@ -196,6 +199,9 @@ proc fuzzySemCheck(c: PContext, n: PNode): PNode =
|
||||
if n.kind notin {nkNone..nkNilLit}:
|
||||
for i in 0 .. < sonsLen(n): result.addSon(fuzzySemCheck(c, n.sons[i]))
|
||||
|
||||
var
|
||||
usageSym: PSym
|
||||
|
||||
proc suggestExpr*(c: PContext, node: PNode) =
|
||||
var cp = msgs.inCheckpoint(node.info)
|
||||
if cp == cpNone: return
|
||||
@@ -233,13 +239,26 @@ proc suggestExpr*(c: PContext, node: PNode) =
|
||||
suggestCall(c, a, n, outputs)
|
||||
|
||||
if optDef in gGlobalOptions:
|
||||
var n = findClosestSym(fuzzySemCheck(c, node))
|
||||
if n != nil:
|
||||
let n = findClosestSym(fuzzySemCheck(c, node))
|
||||
if n != nil:
|
||||
OutWriteln(SymToStr(n.sym, isLocal=false, sectionDef))
|
||||
inc outputs
|
||||
|
||||
if optUsages in gGlobalOptions:
|
||||
if usageSym == nil:
|
||||
let n = findClosestSym(fuzzySemCheck(c, node))
|
||||
if n != nil:
|
||||
usageSym = n.sym
|
||||
OutWriteln(SymToStr(n.sym, isLocal=false, sectionDef))
|
||||
inc outputs
|
||||
else:
|
||||
let n = node
|
||||
if n.kind == nkSym and n.sym == usageSym:
|
||||
OutWriteln(SymToStr(n.sym, isLocal=false, sectionDef, n.info))
|
||||
inc outputs
|
||||
|
||||
dec(c.InCompilesContext)
|
||||
if outputs > 0: quit(0)
|
||||
if outputs > 0 and optUsages notin gGlobalOptions: quit(0)
|
||||
|
||||
proc suggestStmt*(c: PContext, n: PNode) =
|
||||
suggestExpr(c, n)
|
||||
|
||||
@@ -13,8 +13,9 @@ Advanced commands:
|
||||
//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
|
||||
--def list all possible definitions at position
|
||||
--context list possible invokation context
|
||||
--usages list all usages of the symbol at position
|
||||
|
||||
Advanced options:
|
||||
-m, --mainmodule:FILE set the project main module
|
||||
|
||||
Reference in New Issue
Block a user