diff options
-rwxr-xr-x | rod/sigmatch.nim | 2 | ||||
-rw-r--r-- | rod/suggest.nim | 63 | ||||
-rwxr-xr-x | tests/tester.nim | 43 | ||||
-rwxr-xr-x | todo.txt | 1 |
4 files changed, 70 insertions, 39 deletions
diff --git a/rod/sigmatch.nim b/rod/sigmatch.nim index b25008e1e..59112a7f4 100755 --- a/rod/sigmatch.nim +++ b/rod/sigmatch.nim @@ -564,7 +564,7 @@ proc IndexTypesMatch*(c: PContext, f, a: PType, arg: PNode): PNode = proc argtypeMatches*(c: PContext, f, a: PType): bool = var m: TCandidate 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) = if sonsLen(father) <= at: setlen(father.sons, at + 1) diff --git a/rod/suggest.nim b/rod/suggest.nim index bddb247c3..5e0788ae3 100644 --- a/rod/suggest.nim +++ b/rod/suggest.nim @@ -9,7 +9,7 @@ ## 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 sep = '\t' @@ -64,7 +64,14 @@ proc suggestObject(n: PNode) = else: 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 + 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 = case candidate.kind @@ -78,11 +85,11 @@ proc argsFit(c: PContext, candidate: PSym, n: PNode): bool = else: 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)) 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) proc suggestOperations(c: PContext, n: PNode, typ: PType) = @@ -132,21 +139,51 @@ proc suggestFieldAccess(c: PContext, n: PNode) = # fallback: suggestEverything(c, n) -proc suggestExpr*(c: PContext, n: PNode) = - var cp = msgs.inCheckpoint(n.info) +proc interestingNode(n: PNode): bool {.inline.} = + 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 + # 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: + debug n 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 + 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] addSon(a, x) - suggestCall(c, n) - break + 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]) diff --git a/tests/tester.nim b/tests/tester.nim index 37dbf1388..93fc3f433 100755 --- a/tests/tester.nim +++ b/tests/tester.nim @@ -17,14 +17,14 @@ const resultsFile = "testresults.html" type - TMsg = tuple[ - file: string, - line: int, - msg: string, - err: bool, - disabled: bool] - TOutp = tuple[file, outp: string, disabled: bool] - TResults = object + TSpec {.pure.} = object + file: string + outp: string + line: int + msg: string + err: bool + disabled: bool + TResults {.pure.} = object total, passed, skipped: int data: string @@ -49,7 +49,7 @@ proc extractSpec(filename: string): string = else: echo "warning: file does not contain spec: " & filename -template parseTest(fillResult: stmt) = +template parseSpecAux(fillResult: stmt) = var ss = newStringStream(extractSpec(filename)) var p: TCfgParser open(p, ss, filename, 1) @@ -63,25 +63,17 @@ template parseTest(fillResult: stmt) = fillResult close(p) -proc parseRejectTest(filename: string): TMsg = +proc parseSpec(filename: string): TSpec = result.file = filename result.err = true result.msg = "" - parseTest: - case normalize(e.key) - of "file": result.file = e.value - 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: + parseSpecAux: case normalize(e.key) of "file": result.file = e.value + of "line": discard parseInt(e.value, result.line) of "output": result.outp = e.value + of "errormsg", "msg": result.msg = e.value of "disabled": result.disabled = parseCfgBool(e.value) else: echo ignoreMsg(p, e) @@ -96,7 +88,7 @@ var pegSuccess = peg"'Hint: operation successful'.*" pegOfInterest = pegLineError / pegOtherError / pegSuccess -proc callCompiler(filename, options: string): TMsg = +proc callCompiler(filename, options: string): TSpec = var c = parseCmdLine(cmdTemplate % [options, filename]) var a: seq[string] = @[] # slicing is not yet implemented :-( for i in 1 .. c.len-1: add(a, c[i]) @@ -111,6 +103,7 @@ proc callCompiler(filename, options: string): TMsg = s = x result.msg = "" result.file = "" + result.outp = "" result.err = true result.line = -1 if s =~ pegLineError: @@ -171,7 +164,7 @@ proc listResults(reject, compile, run: TResults) = write(outp, s) 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) if strip(expected.msg) notin strip(given.msg): r.addResult(test, expected.msg, given.msg, false) @@ -189,7 +182,7 @@ proc reject(r: var TResults, dir, options: string) = var t = extractFilename(test) inc(r.total) echo t - var expected = parseRejectTest(test) + var expected = parseSpec(test) if expected.disabled: inc(r.skipped) else: var given = callCompiler(test, options) @@ -209,7 +202,7 @@ proc run(r: var TResults, dir, options: string) = var t = extractFilename(test) echo t inc(r.total) - var expected = parseRunTest(test) + var expected = parseSpec(test) if expected.disabled: inc(r.skipped) else: var given = callCompiler(test, options) diff --git a/todo.txt b/todo.txt index aa51ab09a..15360628a 100755 --- a/todo.txt +++ b/todo.txt @@ -1,5 +1,6 @@ - 'suggest' needs tweaking: end-token; testing! - stdout support for doc, pretty +- BUG: gcleak.nim - thread support: threadvar on Windows seems broken; add --deadlock_prevention:on|off switch |