mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-17 00:24:16 +00:00
next steps to perfect 'suggest'
This commit is contained in:
23
rod/msgs.nim
23
rod/msgs.nim
@@ -398,8 +398,8 @@ proc UnknownLineInfo*(): TLineInfo =
|
||||
result.fileIndex = -1
|
||||
|
||||
var
|
||||
filenames: seq[string] = @ []
|
||||
msgContext: seq[TLineInfo] = @ []
|
||||
filenames: seq[string] = @[]
|
||||
msgContext: seq[TLineInfo] = @[]
|
||||
|
||||
proc pushInfoContext*(info: TLineInfo) =
|
||||
msgContext.add(info)
|
||||
@@ -424,10 +424,10 @@ proc ToFilename*(info: TLineInfo): string =
|
||||
if info.fileIndex == - 1: result = "???"
|
||||
else: result = filenames[info.fileIndex]
|
||||
|
||||
proc ToLinenumber*(info: TLineInfo): int =
|
||||
proc ToLinenumber*(info: TLineInfo): int {.inline.} =
|
||||
result = info.line
|
||||
|
||||
proc toColumn*(info: TLineInfo): int =
|
||||
proc toColumn*(info: TLineInfo): int {.inline.} =
|
||||
result = info.col
|
||||
|
||||
var checkPoints: seq[TLineInfo] = @[]
|
||||
@@ -453,11 +453,18 @@ proc MsgKindToString*(kind: TMsgKind): string =
|
||||
proc getMessageStr(msg: TMsgKind, arg: string): string =
|
||||
result = `%`(msgKindToString(msg), [arg])
|
||||
|
||||
proc inCheckpoint*(current: TLineInfo): bool =
|
||||
type
|
||||
TCheckPointResult* = enum
|
||||
cpNone, cpFuzzy, cpExact
|
||||
|
||||
proc inCheckpoint*(current: TLineInfo): TCheckPointResult =
|
||||
for i in countup(0, high(checkPoints)):
|
||||
if (current.line >= checkPoints[i].line) and
|
||||
(current.fileIndex == (checkPoints[i].fileIndex)):
|
||||
return true
|
||||
if current.fileIndex == checkPoints[i].fileIndex:
|
||||
if current.line == checkPoints[i].line and
|
||||
abs(current.col-checkPoints[i].col) < 4:
|
||||
return cpExact
|
||||
if current.line >= checkPoints[i].line:
|
||||
return cpFuzzy
|
||||
|
||||
type
|
||||
TErrorHandling = enum doNothing, doAbort, doRaise
|
||||
|
||||
@@ -28,8 +28,10 @@ proc considerAcc(n: PNode): PIdent =
|
||||
GlobalError(n.info, errIdentifierExpected, renderTree(n))
|
||||
result = nil
|
||||
|
||||
proc isTopLevel(c: PContext): bool =
|
||||
result = c.tab.tos <= 2
|
||||
proc isTopLevel(c: PContext): bool {.inline.} =
|
||||
# if we encountered an error, we treat as top-level so that
|
||||
# cascading errors are not that strange:
|
||||
result = c.tab.tos <= 2 or msgs.gErrorCounter > 0
|
||||
|
||||
proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||
result = newSym(kind, considerAcc(n), getCurrOwner())
|
||||
|
||||
@@ -641,8 +641,6 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
|
||||
checkSonsLen(n, 2)
|
||||
n.sons[0] = semExprWithType(c, n.sons[0], {efAllowType} + flags)
|
||||
if gCmd == cmdSuggest:
|
||||
suggestFieldAccess(c, n.sons[0])
|
||||
var i = considerAcc(n.sons[1])
|
||||
var ty = n.sons[0].Typ
|
||||
var f: PSym = nil
|
||||
|
||||
@@ -7,11 +7,7 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# This module does the instantiation of generic procs.
|
||||
|
||||
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
info: TLineInfo): PSym
|
||||
# generates an instantiated proc
|
||||
# This module implements the instantiation of generic procs.
|
||||
|
||||
proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
|
||||
if (n.kind != nkGenericParams):
|
||||
|
||||
@@ -561,11 +561,17 @@ proc IndexTypesMatch*(c: PContext, f, a: PType, arg: PNode): PNode =
|
||||
initCandidate(m, f)
|
||||
result = paramTypesMatch(c, m, f, a, arg)
|
||||
|
||||
proc argtypeMatches*(c: PContext, f, a: PType): bool =
|
||||
var m: TCandidate
|
||||
initCandidate(m, f)
|
||||
result = paramTypesMatch(c, m, f, a, nil) != nil
|
||||
|
||||
proc setSon(father: PNode, at: int, son: PNode) =
|
||||
if sonsLen(father) <= at: setlen(father.sons, at + 1)
|
||||
father.sons[at] = son
|
||||
|
||||
proc matches*(c: PContext, n: PNode, m: var TCandidate) =
|
||||
proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
|
||||
marker: var TIntSet) =
|
||||
var f = 1 # iterates over formal parameters
|
||||
var a = 1 # iterates over the actual given arguments
|
||||
m.state = csMatch # until proven otherwise
|
||||
@@ -573,8 +579,6 @@ proc matches*(c: PContext, n: PNode, m: var TCandidate) =
|
||||
m.call.typ = base(m.callee) # may be nil
|
||||
var formalLen = sonsLen(m.callee.n)
|
||||
addSon(m.call, copyTree(n.sons[0]))
|
||||
var marker: TIntSet
|
||||
IntSetInit(marker)
|
||||
var container: PNode = nil # constructed container
|
||||
var formal: PSym = nil
|
||||
while a < sonsLen(n):
|
||||
@@ -656,13 +660,26 @@ proc matches*(c: PContext, n: PNode, m: var TCandidate) =
|
||||
setSon(m.call, formal.position + 1, arg)
|
||||
inc(a)
|
||||
inc(f)
|
||||
f = 1
|
||||
|
||||
proc partialMatch*(c: PContext, n: PNode, m: var TCandidate) =
|
||||
# for 'suggest' support:
|
||||
var marker: TIntSet
|
||||
IntSetInit(marker)
|
||||
matchesAux(c, n, m, marker)
|
||||
|
||||
proc matches*(c: PContext, n: PNode, m: var TCandidate) =
|
||||
var marker: TIntSet
|
||||
IntSetInit(marker)
|
||||
matchesAux(c, n, m, marker)
|
||||
if m.state == csNoMatch: return
|
||||
# check that every formal parameter got a value:
|
||||
var f = 1
|
||||
while f < sonsLen(m.callee.n):
|
||||
formal = m.callee.n.sons[f].sym
|
||||
var formal = m.callee.n.sons[f].sym
|
||||
if not IntSetContainsOrIncl(marker, formal.position):
|
||||
if formal.ast == nil:
|
||||
if formal.typ.kind == tyOpenArray:
|
||||
container = newNodeI(nkBracket, n.info)
|
||||
var container = newNodeI(nkBracket, n.info)
|
||||
addSon(m.call, implicitConv(nkHiddenStdConv, formal.typ,
|
||||
container, m, c))
|
||||
else:
|
||||
|
||||
@@ -40,17 +40,11 @@ proc suggestField(s: PSym) =
|
||||
if filterSym(s):
|
||||
MessageOut(SymToStr(s, isLocal=true))
|
||||
|
||||
proc suggestExpr*(c: PContext, n: PNode) =
|
||||
if not msgs.inCheckpoint(n.info): return
|
||||
|
||||
template wholeSymTab(cond: expr) =
|
||||
for i in countdown(c.tab.tos-1, 0):
|
||||
for it in items(c.tab.stack[i]):
|
||||
if filterSym(it):
|
||||
if cond:
|
||||
MessageOut(SymToStr(it, isLocal = i > ModuleTablePos))
|
||||
quit(0)
|
||||
|
||||
proc suggestStmt*(c: PContext, n: PNode) =
|
||||
suggestExpr(c, n)
|
||||
|
||||
proc suggestSymList(list: PNode) =
|
||||
for i in countup(0, sonsLen(list) - 1):
|
||||
@@ -60,20 +54,45 @@ proc suggestSymList(list: PNode) =
|
||||
proc suggestObject(n: PNode) =
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in countup(0, sonsLen(n) - 1): suggestObject(n.sons[i])
|
||||
for i in countup(0, sonsLen(n)-1): suggestObject(n.sons[i])
|
||||
of nkRecCase:
|
||||
var L = sonsLen(n)
|
||||
if L > 0:
|
||||
suggestObject(n.sons[0])
|
||||
for i in countup(1, L-1):
|
||||
suggestObject(lastSon(n.sons[i]))
|
||||
for i in countup(1, L-1): suggestObject(lastSon(n.sons[i]))
|
||||
of nkSym: suggestField(n.sym)
|
||||
else: nil
|
||||
|
||||
proc suggestOperations(c: PContext, n: PNode, typ: PType) =
|
||||
nil
|
||||
proc nameFits(c: PContext, s: PSym, n: PNode): bool =
|
||||
result = n.sons[0].kind == nkSym and n.sons[0].sym.name.id == s.name.id
|
||||
|
||||
proc suggestFieldAccess*(c: PContext, n: PNode) =
|
||||
proc argsFit(c: PContext, candidate: PSym, n: PNode): bool =
|
||||
case candidate.kind
|
||||
of skProc, skIterator, skMethod:
|
||||
var m: TCandidate
|
||||
initCandidate(m, candidate, nil)
|
||||
sigmatch.partialMatch(c, n, m)
|
||||
result = m.state != csNoMatch
|
||||
of skTemplate, skMacro:
|
||||
result = true
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc suggestCall*(c: PContext, n: PNode) =
|
||||
wholeSymTab(filterSym(it) and nameFits(c, it, n) and argsFit(c, it, n))
|
||||
|
||||
proc typeFits(c: PContext, s: PSym, firstArg: PType): bool {.inline.} =
|
||||
if s.typ != nil and sonsLen(s.typ) > 1:
|
||||
result = sigmatch.argtypeMatches(c, s.typ.sons[1], firstArg)
|
||||
|
||||
proc suggestOperations(c: PContext, n: PNode, typ: PType) =
|
||||
assert typ != nil
|
||||
wholeSymTab(filterSym(it) and typeFits(c, it, typ))
|
||||
|
||||
proc suggestEverything(c: PContext, n: PNode) =
|
||||
wholeSymTab(filterSym(it))
|
||||
|
||||
proc suggestFieldAccess(c: PContext, n: PNode) =
|
||||
# special code that deals with ``myObj.``. `n` is NOT the nkDotExpr-node, but
|
||||
# ``myObj``.
|
||||
var typ = n.Typ
|
||||
@@ -89,7 +108,7 @@ proc suggestFieldAccess*(c: PContext, n: PNode) =
|
||||
if filterSym(it): MessageOut(SymToStr(it, isLocal=false))
|
||||
else:
|
||||
# fallback:
|
||||
suggestExpr(c, n)
|
||||
suggestEverything(c, n)
|
||||
elif typ.kind == tyEnum:
|
||||
# look up if the identifier belongs to the enum:
|
||||
var t = typ
|
||||
@@ -111,5 +130,32 @@ proc suggestFieldAccess*(c: PContext, n: PNode) =
|
||||
suggestOperations(c, n, typ)
|
||||
else:
|
||||
# fallback:
|
||||
suggestExpr(c, n)
|
||||
suggestEverything(c, n)
|
||||
|
||||
proc suggestExpr*(c: PContext, n: PNode) =
|
||||
var cp = msgs.inCheckpoint(n.info)
|
||||
if cp == cpNone: return
|
||||
block:
|
||||
case n.kind
|
||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand,
|
||||
nkCallStrLit, nkMacroStmt:
|
||||
var a = copyNode(n)
|
||||
for i in 0..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, n)
|
||||
break
|
||||
of nkDotExpr:
|
||||
if cp == cpExact:
|
||||
var obj = c.semExpr(c, n.sons[0])
|
||||
suggestFieldAccess(c, obj)
|
||||
break
|
||||
else: nil
|
||||
suggestEverything(c, n)
|
||||
quit(0)
|
||||
|
||||
proc suggestStmt*(c: PContext, n: PNode) =
|
||||
suggestExpr(c, n)
|
||||
|
||||
|
||||
3
todo.txt
3
todo.txt
@@ -1,4 +1,4 @@
|
||||
- 'suggest' needs tweaking: support for '.'
|
||||
- 'suggest' needs tweaking: end-token; testing!
|
||||
- stdout support for doc, pretty
|
||||
|
||||
- thread support: threadvar on Windows seems broken;
|
||||
@@ -16,7 +16,6 @@
|
||||
High priority (version 0.9.0)
|
||||
=============================
|
||||
|
||||
|
||||
- fix implicit generic routines
|
||||
- fix the streams implementation so that it uses methods
|
||||
- fix overloading resolution
|
||||
|
||||
Reference in New Issue
Block a user