summary refs log tree commit diff stats
path: root/rod/suggest.nim
diff options
context:
space:
mode:
Diffstat (limited to 'rod/suggest.nim')
-rw-r--r--rod/suggest.nim74
1 files changed, 67 insertions, 7 deletions
diff --git a/rod/suggest.nim b/rod/suggest.nim
index 377c988bd..5eaa2bd9e 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
+import scanner, ast, astalgo, semdata, msgs, types, sigmatch
 
 const
   sep = '\t'
@@ -33,23 +33,83 @@ proc SymToStr(s: PSym, isLocal: bool): string =
   result.add(sep)
   result.add($ToColumn(s.info))
 
-proc suggestSym(s: PSym): bool {.inline.} = 
+proc filterSym(s: PSym): bool {.inline.} = 
   result = s.name.s[0] in scanner.SymChars
 
+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
 
   for i in countdown(c.tab.tos-1, 0): 
     for it in items(c.tab.stack[i]): 
-      if suggestSym(it):
-        MessageOut(SymToStr(it, i > ModuleTablePos))
+      if filterSym(it):
+        MessageOut(SymToStr(it, isLocal = i > ModuleTablePos))
   quit(0)
 
 proc suggestStmt*(c: PContext, n: PNode) = 
-  suggestExpr(c, n) 
+  suggestExpr(c, n)
+
+proc suggestSymList(list: PNode) = 
+  for i in countup(0, sonsLen(list) - 1): 
+    if list.sons[i].kind != nkSym: InternalError(list.info, "getSymFromList")
+    suggestField(list.sons[i].sym)
+
+proc suggestObject(n: PNode) = 
+  case n.kind
+  of nkRecList: 
+    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]))
+  of nkSym: suggestField(n.sym)
+  else: nil
 
+proc suggestOperations(c: PContext, n: PNode, typ: PType) =
+  nil
 
 proc suggestFieldAccess*(c: PContext, n: PNode) =
-  suggestExpr(c, n) 
-  # XXX provide a better implementation based on n[0].typ
+  # special code that deals with ``myObj.``. `n` is NOT the nkDotExpr-node, but
+  # ``myObj``.
+  var typ = n.Typ
+  if typ == nil:
+    # a module symbol has no type for example:
+    if n.kind == nkSym and n.sym.kind == skModule: 
+      if n.sym == c.module: 
+        # all symbols accessible, because we are in the current module:
+        for it in items(c.tab.stack[ModuleTablePos]): 
+          if filterSym(it): MessageOut(SymToStr(it, isLocal=false))
+      else: 
+        for it in items(n.sym.tab): 
+          if filterSym(it): MessageOut(SymToStr(it, isLocal=false))
+    else:
+      # fallback:
+      suggestExpr(c, n)
+  elif typ.kind == tyEnum: 
+    # look up if the identifier belongs to the enum:
+    var t = typ
+    while t != nil: 
+      suggestSymList(t.n)
+      t = t.sons[0]
+    suggestOperations(c, n, typ)
+  else:
+    typ = skipTypes(typ, {tyGenericInst, tyVar, tyPtr, tyRef})
+    if typ.kind == tyObject: 
+      var t = typ
+      while true: 
+        suggestObject(t.n)
+        if t.sons[0] == nil: break 
+        t = skipTypes(t.sons[0], {tyGenericInst})
+      suggestOperations(c, n, typ)
+    elif typ.kind == tyTuple and typ.n != nil: 
+      suggestSymList(typ.n)
+      suggestOperations(c, n, typ)
+    else:
+      # fallback: 
+      suggestExpr(c, n)