suggest: improvements

This commit is contained in:
Araq 2011-02-23 00:15:36 +01:00
commit 82514c9c1c
4 changed files with 70 additions and 39 deletions

View file

@ -564,7 +564,7 @@ proc IndexTypesMatch*(c: PContext, f, a: PType, arg: PNode): PNode =
proc argtypeMatches*(c: PContext, f, a: PType): bool = proc argtypeMatches*(c: PContext, f, a: PType): bool =
var m: TCandidate var m: TCandidate
initCandidate(m, f) initCandidate(m, f)
result = paramTypesMatch(c, m, f, a, nil) != nil result = paramTypesMatch(c, m, f, a, ast.emptyNode) != nil
proc setSon(father: PNode, at: int, son: PNode) = proc setSon(father: PNode, at: int, son: PNode) =
if sonsLen(father) <= at: setlen(father.sons, at + 1) if sonsLen(father) <= at: setlen(father.sons, at + 1)

View file

@ -9,7 +9,7 @@
## This file implements features required for IDE support. ## This file implements features required for IDE support.
import scanner, ast, astalgo, semdata, msgs, types, sigmatch import scanner, idents, ast, astalgo, semdata, msgs, types, sigmatch
const const
sep = '\t' sep = '\t'
@ -64,7 +64,14 @@ proc suggestObject(n: PNode) =
else: nil else: nil
proc nameFits(c: PContext, s: PSym, n: PNode): bool = 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 var op = n.sons[0]
if op.kind == nkSymChoice: op = op.sons[0]
var opr: PIdent
case op.kind
of nkSym: opr = op.sym.name
of nkIdent: opr = op.ident
else: return false
result = opr.id == s.name.id
proc argsFit(c: PContext, candidate: PSym, n: PNode): bool = proc argsFit(c: PContext, candidate: PSym, n: PNode): bool =
case candidate.kind case candidate.kind
@ -78,11 +85,11 @@ proc argsFit(c: PContext, candidate: PSym, n: PNode): bool =
else: else:
result = false result = false
proc suggestCall*(c: PContext, n: PNode) = 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))
proc typeFits(c: PContext, s: PSym, firstArg: PType): bool {.inline.} = proc typeFits(c: PContext, s: PSym, firstArg: PType): bool {.inline.} =
if s.typ != nil and sonsLen(s.typ) > 1: if s.typ != nil and sonsLen(s.typ) > 1 and s.typ.sons[1] != nil:
result = sigmatch.argtypeMatches(c, s.typ.sons[1], firstArg) result = sigmatch.argtypeMatches(c, s.typ.sons[1], firstArg)
proc suggestOperations(c: PContext, n: PNode, typ: PType) = proc suggestOperations(c: PContext, n: PNode, typ: PType) =
@ -132,21 +139,51 @@ proc suggestFieldAccess(c: PContext, n: PNode) =
# fallback: # fallback:
suggestEverything(c, n) suggestEverything(c, n)
proc suggestExpr*(c: PContext, n: PNode) = proc interestingNode(n: PNode): bool {.inline.} =
var cp = msgs.inCheckpoint(n.info) result = n.kind == nkDotExpr
proc findClosestNode(n: PNode): PNode =
if msgs.inCheckpoint(n.info) == cpExact:
result = n
echo "came here"
debug result
elif n.kind notin {nkNone..nkNilLit}:
for i in 0.. <sonsLen(n):
if interestingNode(n.sons[i]):
result = findClosestNode(n.sons[i])
if result != nil: return
var recursiveCheck = 0
proc suggestExpr*(c: PContext, node: PNode) =
var cp = msgs.inCheckpoint(node.info)
if cp == cpNone: return 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: block:
debug n
case n.kind case n.kind
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand,
nkCallStrLit, nkMacroStmt: nkCallStrLit, nkMacroStmt:
var a = copyNode(n) when false:
for i in 0..sonsLen(n)-1: # this provides "context information", not "type suggestion":
# use as many typed arguments as possible: var a = copyNode(n)
var x = c.semExpr(c, n.sons[i]) var x = c.semExpr(c, n.sons[0])
if x.kind == nkEmpty or x.typ == nil: break if x.kind == nkEmpty or x.typ == nil: x = n.sons[0]
addSon(a, x) addSon(a, x)
suggestCall(c, n) for i in 1..sonsLen(n)-1:
break # 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: of nkDotExpr:
if cp == cpExact: if cp == cpExact:
var obj = c.semExpr(c, n.sons[0]) var obj = c.semExpr(c, n.sons[0])

View file

@ -17,14 +17,14 @@ const
resultsFile = "testresults.html" resultsFile = "testresults.html"
type type
TMsg = tuple[ TSpec {.pure.} = object
file: string, file: string
line: int, outp: string
msg: string, line: int
err: bool, msg: string
disabled: bool] err: bool
TOutp = tuple[file, outp: string, disabled: bool] disabled: bool
TResults = object TResults {.pure.} = object
total, passed, skipped: int total, passed, skipped: int
data: string data: string
@ -49,7 +49,7 @@ proc extractSpec(filename: string): string =
else: else:
echo "warning: file does not contain spec: " & filename echo "warning: file does not contain spec: " & filename
template parseTest(fillResult: stmt) = template parseSpecAux(fillResult: stmt) =
var ss = newStringStream(extractSpec(filename)) var ss = newStringStream(extractSpec(filename))
var p: TCfgParser var p: TCfgParser
open(p, ss, filename, 1) open(p, ss, filename, 1)
@ -63,25 +63,17 @@ template parseTest(fillResult: stmt) =
fillResult fillResult
close(p) close(p)
proc parseRejectTest(filename: string): TMsg = proc parseSpec(filename: string): TSpec =
result.file = filename result.file = filename
result.err = true result.err = true
result.msg = "" result.msg = ""
parseTest: result.outp = ""
parseSpecAux:
case normalize(e.key) case normalize(e.key)
of "file": result.file = e.value of "file": result.file = e.value
of "line": discard parseInt(e.value, result.line) of "line": discard parseInt(e.value, result.line)
of "errormsg": result.msg = e.value
of "disabled": result.disabled = parseCfgBool(e.value)
else: echo ignoreMsg(p, e)
proc parseRunTest(filename: string): TOutp =
result.file = filename
result.outp = ""
parseTest:
case normalize(e.key)
of "file": result.file = e.value
of "output": result.outp = e.value of "output": result.outp = e.value
of "errormsg", "msg": result.msg = e.value
of "disabled": result.disabled = parseCfgBool(e.value) of "disabled": result.disabled = parseCfgBool(e.value)
else: echo ignoreMsg(p, e) else: echo ignoreMsg(p, e)
@ -96,7 +88,7 @@ var
pegSuccess = peg"'Hint: operation successful'.*" pegSuccess = peg"'Hint: operation successful'.*"
pegOfInterest = pegLineError / pegOtherError / pegSuccess pegOfInterest = pegLineError / pegOtherError / pegSuccess
proc callCompiler(filename, options: string): TMsg = proc callCompiler(filename, options: string): TSpec =
var c = parseCmdLine(cmdTemplate % [options, filename]) var c = parseCmdLine(cmdTemplate % [options, filename])
var a: seq[string] = @[] # slicing is not yet implemented :-( var a: seq[string] = @[] # slicing is not yet implemented :-(
for i in 1 .. c.len-1: add(a, c[i]) for i in 1 .. c.len-1: add(a, c[i])
@ -111,6 +103,7 @@ proc callCompiler(filename, options: string): TMsg =
s = x s = x
result.msg = "" result.msg = ""
result.file = "" result.file = ""
result.outp = ""
result.err = true result.err = true
result.line = -1 result.line = -1
if s =~ pegLineError: if s =~ pegLineError:
@ -171,7 +164,7 @@ proc listResults(reject, compile, run: TResults) =
write(outp, s) write(outp, s)
close(outp) close(outp)
proc cmpMsgs(r: var TResults, expected, given: TMsg, test: string) = proc cmpMsgs(r: var TResults, expected, given: TSpec, test: string) =
inc(r.total) inc(r.total)
if strip(expected.msg) notin strip(given.msg): if strip(expected.msg) notin strip(given.msg):
r.addResult(test, expected.msg, given.msg, false) r.addResult(test, expected.msg, given.msg, false)
@ -189,7 +182,7 @@ proc reject(r: var TResults, dir, options: string) =
var t = extractFilename(test) var t = extractFilename(test)
inc(r.total) inc(r.total)
echo t echo t
var expected = parseRejectTest(test) var expected = parseSpec(test)
if expected.disabled: inc(r.skipped) if expected.disabled: inc(r.skipped)
else: else:
var given = callCompiler(test, options) var given = callCompiler(test, options)
@ -209,7 +202,7 @@ proc run(r: var TResults, dir, options: string) =
var t = extractFilename(test) var t = extractFilename(test)
echo t echo t
inc(r.total) inc(r.total)
var expected = parseRunTest(test) var expected = parseSpec(test)
if expected.disabled: inc(r.skipped) if expected.disabled: inc(r.skipped)
else: else:
var given = callCompiler(test, options) var given = callCompiler(test, options)

View file

@ -1,5 +1,6 @@
- 'suggest' needs tweaking: end-token; testing! - 'suggest' needs tweaking: end-token; testing!
- stdout support for doc, pretty - stdout support for doc, pretty
- BUG: gcleak.nim
- thread support: threadvar on Windows seems broken; - thread support: threadvar on Windows seems broken;
add --deadlock_prevention:on|off switch add --deadlock_prevention:on|off switch