summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xrod/sigmatch.nim2
-rw-r--r--rod/suggest.nim63
-rwxr-xr-xtests/tester.nim43
-rwxr-xr-xtodo.txt1
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