fixes #8671; show helpful msg (lookup symbol, eg iterator) on 'attempting to call undeclared routine' error (#8786)
This commit is contained in:
parent
8232bd04f9
commit
eb946f37a7
10 changed files with 98 additions and 10 deletions
|
|
@ -224,6 +224,7 @@ const
|
||||||
errButExpected = "but expected one of: "
|
errButExpected = "but expected one of: "
|
||||||
errUndeclaredField = "undeclared field: '$1'"
|
errUndeclaredField = "undeclared field: '$1'"
|
||||||
errUndeclaredRoutine = "attempting to call undeclared routine: '$1'"
|
errUndeclaredRoutine = "attempting to call undeclared routine: '$1'"
|
||||||
|
errBadRoutine = "attempting to call routine: '$1'$2"
|
||||||
errAmbiguousCallXYZ = "ambiguous call; both $1 and $2 match for: $3"
|
errAmbiguousCallXYZ = "ambiguous call; both $1 and $2 match for: $3"
|
||||||
|
|
||||||
proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
|
proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
|
||||||
|
|
@ -262,6 +263,30 @@ proc bracketNotFoundError(c: PContext; n: PNode) =
|
||||||
else:
|
else:
|
||||||
notFoundError(c, n, errors)
|
notFoundError(c, n, errors)
|
||||||
|
|
||||||
|
proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
|
||||||
|
if c.compilesContextId > 0:
|
||||||
|
# we avoid running more diagnostic when inside a `compiles(expr)`, to
|
||||||
|
# errors while running diagnostic (see test D20180828T234921), and
|
||||||
|
# also avoid slowdowns in evaluating `compiles(expr)`.
|
||||||
|
discard
|
||||||
|
else:
|
||||||
|
var o: TOverloadIter
|
||||||
|
var sym = initOverloadIter(o, c, f)
|
||||||
|
while sym != nil:
|
||||||
|
proc toHumanStr(kind: TSymKind): string =
|
||||||
|
result = $kind
|
||||||
|
assert result.startsWith "sk"
|
||||||
|
result = result[2..^1].toLowerAscii
|
||||||
|
result &= "\n found '$1' of kind '$2'" % [getSymRepr(c.config, sym), sym.kind.toHumanStr]
|
||||||
|
sym = nextOverloadIter(o, c, n)
|
||||||
|
|
||||||
|
let ident = considerQuotedIdent(c, f, n).s
|
||||||
|
if nfDotField in n.flags and nfExplicitCall notin n.flags:
|
||||||
|
result = errUndeclaredField % ident & result
|
||||||
|
else:
|
||||||
|
if result.len == 0: result = errUndeclaredRoutine % ident
|
||||||
|
else: result = errBadRoutine % [ident, result]
|
||||||
|
|
||||||
proc resolveOverloads(c: PContext, n, orig: PNode,
|
proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
filter: TSymKinds, flags: TExprFlags,
|
filter: TSymKinds, flags: TExprFlags,
|
||||||
errors: var CandidateErrors,
|
errors: var CandidateErrors,
|
||||||
|
|
@ -330,11 +355,8 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
pickBest(callOp)
|
pickBest(callOp)
|
||||||
|
|
||||||
if overloadsState == csEmpty and result.state == csEmpty:
|
if overloadsState == csEmpty and result.state == csEmpty:
|
||||||
if efNoUndeclared notin flags:
|
if efNoUndeclared notin flags: # for tests/pragmas/tcustom_pragma.nim
|
||||||
if nfDotField in n.flags and nfExplicitCall notin n.flags:
|
localError(c.config, n.info, getMsgDiagnostic(c, flags, n, f))
|
||||||
localError(c.config, n.info, errUndeclaredField % considerQuotedIdent(c, f, n).s)
|
|
||||||
else:
|
|
||||||
localError(c.config, n.info, errUndeclaredRoutine % considerQuotedIdent(c, f, n).s)
|
|
||||||
return
|
return
|
||||||
elif result.state != csMatch:
|
elif result.state != csMatch:
|
||||||
if nfExprCall in n.flags:
|
if nfExprCall in n.flags:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
discard """
|
discard """
|
||||||
line: 7
|
line: 7
|
||||||
errormsg: "attempting to call undeclared routine: 'items'"
|
errormsg: "attempting to call routine: 'items'"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type a = enum b,c,d
|
type a = enum b,c,d
|
||||||
|
|
|
||||||
13
tests/errmsgs/undeclared_routime.nim
Normal file
13
tests/errmsgs/undeclared_routime.nim
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
discard """
|
||||||
|
cmd: '''nim c --hints:off $file'''
|
||||||
|
errormsg: "attempting to call routine: 'myiter'"
|
||||||
|
nimout: '''undeclared_routime.nim(13, 15) Error: attempting to call routine: 'myiter'
|
||||||
|
found 'undeclared_routime.myiter(a: string)[declared in undeclared_routime.nim(10, 9)]' of kind 'iterator'
|
||||||
|
found 'undeclared_routime.myiter()[declared in undeclared_routime.nim(11, 9)]' of kind 'iterator'
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
iterator myiter(a:string): int = discard
|
||||||
|
iterator myiter(): int = discard
|
||||||
|
|
||||||
|
let a = myiter(1)
|
||||||
9
tests/errmsgs/undeclared_routime2.nim
Normal file
9
tests/errmsgs/undeclared_routime2.nim
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
discard """
|
||||||
|
cmd: '''nim c --hints:off $file'''
|
||||||
|
errormsg: "invalid pragma: myPragma"
|
||||||
|
"""
|
||||||
|
|
||||||
|
proc myPragma():int=discard
|
||||||
|
iterator myPragma():int=discard
|
||||||
|
proc myfun(a:int): int {.myPragma.} = 1
|
||||||
|
let a = myfun(1)
|
||||||
13
tests/errmsgs/undeclared_routime3.nim
Normal file
13
tests/errmsgs/undeclared_routime3.nim
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
discard """
|
||||||
|
cmd: '''nim c --hints:off $file'''
|
||||||
|
errormsg: "undeclared field: 'bar'"
|
||||||
|
nimout: '''undeclared_routime3.nim(13, 10) Error: undeclared field: 'bar'
|
||||||
|
found 'undeclared_routime3.bar()[declared in undeclared_routime3.nim(12, 9)]' of kind 'iterator'
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
type Foo = object
|
||||||
|
var a = Foo()
|
||||||
|
iterator bar():int=discard
|
||||||
|
let a = a.bar
|
||||||
10
tests/errmsgs/undeclared_routime4.nim
Normal file
10
tests/errmsgs/undeclared_routime4.nim
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
discard """
|
||||||
|
cmd: '''nim c --hints:off $file'''
|
||||||
|
errormsg: "undeclared field: 'bar'"
|
||||||
|
nimout: '''undeclared_routime4.nim(10, 10) Error: undeclared field: 'bar'
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
type Foo = object
|
||||||
|
var a = Foo()
|
||||||
|
let a = a.bar
|
||||||
9
tests/errmsgs/undeclared_routime5.nim
Normal file
9
tests/errmsgs/undeclared_routime5.nim
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
discard """
|
||||||
|
cmd: '''nim c --hints:off $file'''
|
||||||
|
errormsg: "undeclared identifier: 'myfun'"
|
||||||
|
nimout: '''undeclared_routime5.nim(9, 9) Error: undeclared identifier: 'myfun'
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
let a = myfun(1)
|
||||||
11
tests/errmsgs/undeclared_routime_compiles.nim
Normal file
11
tests/errmsgs/undeclared_routime_compiles.nim
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# D20180828T234921:here
|
||||||
|
template foo*(iter: untyped): untyped =
|
||||||
|
when compiles(iter.unexistingField): 0
|
||||||
|
elif compiles(iter.len): 1
|
||||||
|
else: 2
|
||||||
|
|
||||||
|
proc foo[A]()=
|
||||||
|
let a2 = @[10, 11]
|
||||||
|
let a3 = foo(pairs(a2))
|
||||||
|
|
||||||
|
foo[int]()
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
discard """
|
discard """
|
||||||
file: "tissue710.nim"
|
file: "tissue710.nim"
|
||||||
line: 8
|
line: 8
|
||||||
errorMsg: "attempting to call undeclared routine: '||'"
|
errorMsg: "attempting to call routine: '||'"
|
||||||
"""
|
"""
|
||||||
var sum = 0
|
var sum = 0
|
||||||
for x in 3..1000:
|
for x in 3..1000:
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
discard """
|
discard """
|
||||||
|
nimout: '''
|
||||||
|
found 'a' of kind 'var''''
|
||||||
file: "tnoop.nim"
|
file: "tnoop.nim"
|
||||||
line: 11
|
line: 12
|
||||||
errormsg: "attempting to call undeclared routine: 'a'"
|
errormsg: "attempting to call routine: 'a'"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
var
|
var
|
||||||
a: int
|
a: int
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue