diff options
author | Araq <rumpf_a@web.de> | 2017-03-09 14:58:14 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2017-03-09 14:58:14 +0100 |
commit | 475579541621ca83cfcbb35df7f5d9ef4236cdfa (patch) | |
tree | 81f95f9ae846b61c7f2878a275413f5a3fc9bea3 /nimsuggest/tests | |
parent | da821a22d9e390d59f66018630fb4c39ba83eaf3 (diff) | |
download | Nim-475579541621ca83cfcbb35df7f5d9ef4236cdfa.tar.gz |
nimsuggest: more precise cursor tracking
Diffstat (limited to 'nimsuggest/tests')
-rw-r--r-- | nimsuggest/tests/dep_v1.nim | 8 | ||||
-rw-r--r-- | nimsuggest/tests/dep_v2.nim | 9 | ||||
-rw-r--r-- | nimsuggest/tests/tchk1.nim | 27 | ||||
-rw-r--r-- | nimsuggest/tests/tcursor_at_end.nim | 12 | ||||
-rw-r--r-- | nimsuggest/tests/tdef1.nim | 16 | ||||
-rw-r--r-- | nimsuggest/tests/tdot1.nim | 14 | ||||
-rw-r--r-- | nimsuggest/tests/tdot2.nim | 29 | ||||
-rw-r--r-- | nimsuggest/tests/tdot3.nim | 27 | ||||
-rw-r--r-- | nimsuggest/tests/tinclude.nim | 7 | ||||
-rw-r--r-- | nimsuggest/tests/tno_deref.nim | 14 | ||||
-rw-r--r-- | nimsuggest/tests/tstrutils.nim | 9 | ||||
-rw-r--r-- | nimsuggest/tests/tsug_regression.nim | 28 | ||||
-rw-r--r-- | nimsuggest/tests/twithin_macro.nim | 213 | ||||
-rw-r--r-- | nimsuggest/tests/twithin_macro_prefix.nim | 209 |
14 files changed, 622 insertions, 0 deletions
diff --git a/nimsuggest/tests/dep_v1.nim b/nimsuggest/tests/dep_v1.nim new file mode 100644 index 000000000..eae230e85 --- /dev/null +++ b/nimsuggest/tests/dep_v1.nim @@ -0,0 +1,8 @@ + + + + + +type + Foo* = object + x*, y*: int diff --git a/nimsuggest/tests/dep_v2.nim b/nimsuggest/tests/dep_v2.nim new file mode 100644 index 000000000..ab39721c4 --- /dev/null +++ b/nimsuggest/tests/dep_v2.nim @@ -0,0 +1,9 @@ + + + + + +type + Foo* = object + x*, y*: int + z*: string diff --git a/nimsuggest/tests/tchk1.nim b/nimsuggest/tests/tchk1.nim new file mode 100644 index 000000000..f9f0dc8fe --- /dev/null +++ b/nimsuggest/tests/tchk1.nim @@ -0,0 +1,27 @@ +# test we get some suggestion at the end of the file + + + + + + + +type + + +template foo() = + +proc main = + +#[!]# +discard """ +$nimsuggest --tester $file +>chk $1 +chk;;skUnknown;;;;Hint;;???;;-1;;-1;;"tchk1 [Processing]";;0 +chk;;skUnknown;;;;Error;;$file;;12;;0;;"identifier expected, but found \'keyword template\'";;0 +chk;;skUnknown;;;;Error;;$file;;14;;0;;"complex statement requires indentation";;0 +chk;;skUnknown;;;;Error;;$file;;12;;0;;"implementation of \'foo\' expected";;0 +chk;;skUnknown;;;;Error;;$file;;17;;0;;"invalid indentation";;0 +chk;;skUnknown;;;;Hint;;$file;;12;;9;;"\'foo\' is declared but not used [XDeclaredButNotUsed]";;0 +chk;;skUnknown;;;;Hint;;$file;;14;;5;;"\'tchk1.main()\' is declared but not used [XDeclaredButNotUsed]";;0 +""" diff --git a/nimsuggest/tests/tcursor_at_end.nim b/nimsuggest/tests/tcursor_at_end.nim new file mode 100644 index 000000000..b3a0d1133 --- /dev/null +++ b/nimsuggest/tests/tcursor_at_end.nim @@ -0,0 +1,12 @@ +# test we get some suggestion at the end of the file + +discard """ +$nimsuggest --tester $file +>sug $1 +sug;;skProc;;tcursor_at_end.main;;proc ();;$file;;10;;5;;"";;* +""" + + +proc main = discard + +#[!]# diff --git a/nimsuggest/tests/tdef1.nim b/nimsuggest/tests/tdef1.nim new file mode 100644 index 000000000..2cd040ea1 --- /dev/null +++ b/nimsuggest/tests/tdef1.nim @@ -0,0 +1,16 @@ +discard """ +$nimsuggest --tester $file +>def $1 +def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe, locks: 0.};;$file;;9;;5;;"Return hello";;100 +>def $1 +def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe, locks: 0.};;$file;;9;;5;;"Return hello";;100 +""" + +proc hello(): string = + ## Return hello + "Hello" + +hel#[!]#lo() + +# v uncompleted id for sug (13,2) +he diff --git a/nimsuggest/tests/tdot1.nim b/nimsuggest/tests/tdot1.nim new file mode 100644 index 000000000..9ac92f8a5 --- /dev/null +++ b/nimsuggest/tests/tdot1.nim @@ -0,0 +1,14 @@ +discard """ +$nimsuggest --tester $file +>sug $1 +sug;;skField;;x;;int;;$file;;11;;4;;"";;100;;None +sug;;skField;;y;;int;;$file;;11;;7;;"";;100;;None +sug;;skProc;;tdot1.main;;proc (f: Foo);;$file;;13;;5;;"";;100;;None +""" + +type + Foo = object + x, y: int + +proc main(f: Foo) = + if f.#[!]#: diff --git a/nimsuggest/tests/tdot2.nim b/nimsuggest/tests/tdot2.nim new file mode 100644 index 000000000..f02b5cf16 --- /dev/null +++ b/nimsuggest/tests/tdot2.nim @@ -0,0 +1,29 @@ +# Test basic editing. We replace the 'false' by 'true' to +# see whether then the z field is suggested. + +const zField = 0i32 + +type + Foo = object + x, y: int + when zField == 1i32: + z: string + +proc main(f: Foo) = + f.#[!]# + +# the tester supports the spec section at the bottom of the file and +# this way, the line numbers more often stay the same +discard """ +$nimsuggest --tester $file +>sug $1 +sug;;skField;;x;;int;;$file;;8;;4;;"";;100;;None +sug;;skField;;y;;int;;$file;;8;;7;;"";;100;;None +sug;;skProc;;tdot2.main;;proc (f: Foo);;$file;;12;;5;;"";;100;;None +!edit 0i32 1i32 +>sug $1 +sug;;skField;;x;;int;;$file;;8;;4;;"";;100;;None +sug;;skField;;y;;int;;$file;;8;;7;;"";;100;;None +sug;;skField;;z;;string;;$file;;10;;6;;"";;100;;None +sug;;skProc;;tdot2.main;;proc (f: Foo);;$file;;12;;5;;"";;100;;None +""" diff --git a/nimsuggest/tests/tdot3.nim b/nimsuggest/tests/tdot3.nim new file mode 100644 index 000000000..15fc1cd1c --- /dev/null +++ b/nimsuggest/tests/tdot3.nim @@ -0,0 +1,27 @@ +# Test basic module dependency recompilations. + +import dep + +proc main(f: Foo) = + f.#[!]# + +# the tester supports the spec section at the bottom of the file and +# this way, the line numbers more often stay the same + +discard """ +!copy dep_v1.nim dep.nim +$nimsuggest --tester $file +>sug $1 +sug;;skField;;x;;int;;*dep.nim;;8;;4;;"";;100;;None +sug;;skField;;y;;int;;*dep.nim;;8;;8;;"";;100;;None +sug;;skProc;;tdot3.main;;proc (f: Foo);;$file;;5;;5;;"";;100;;None + +!copy dep_v2.nim dep.nim +>mod $path/dep.nim +>sug $1 +sug;;skField;;x;;int;;*dep.nim;;8;;4;;"";;100;;None +sug;;skField;;y;;int;;*dep.nim;;8;;8;;"";;100;;None +sug;;skField;;z;;string;;*dep.nim;;9;;4;;"";;100;;None +sug;;skProc;;tdot3.main;;proc (f: Foo);;$file;;5;;5;;"";;100;;None +!del dep.nim +""" diff --git a/nimsuggest/tests/tinclude.nim b/nimsuggest/tests/tinclude.nim new file mode 100644 index 000000000..27391c522 --- /dev/null +++ b/nimsuggest/tests/tinclude.nim @@ -0,0 +1,7 @@ +discard """ +$nimsuggest --tester compiler/nim.nim +>def compiler/semexprs.nim:13:50 +def;;skType;;ast.PSym;;PSym;;*ast.nim;;669;;2;;"";;100 +>def compiler/semexprs.nim:13:50 +def;;skType;;ast.PSym;;PSym;;*ast.nim;;669;;2;;"";;100 +""" diff --git a/nimsuggest/tests/tno_deref.nim b/nimsuggest/tests/tno_deref.nim new file mode 100644 index 000000000..05cffa507 --- /dev/null +++ b/nimsuggest/tests/tno_deref.nim @@ -0,0 +1,14 @@ + +var x: ptr int + +proc foo(y: ptr int) = + discard + +x.#[!]# + +discard """ +$nimsuggest --tester $file +>sug $1 +sug;;skProc;;tno_deref.foo;;proc (y: ptr int)*;;$file;;4;;5;;"";;100;;None +* +""" diff --git a/nimsuggest/tests/tstrutils.nim b/nimsuggest/tests/tstrutils.nim new file mode 100644 index 000000000..34da8cb53 --- /dev/null +++ b/nimsuggest/tests/tstrutils.nim @@ -0,0 +1,9 @@ +discard """ +$nimsuggest --tester lib/pure/strutils.nim +>def lib/pure/strutils.nim:2300:6 +def;;skTemplate;;system.doAssert;;proc (cond: bool, msg: string): typed;;*/lib/system.nim;;*;;9;;"same as `assert` but is always turned on and not affected by the\x0A``--assertions`` command line switch.";;100 +""" + +# Line 2300 in strutils.nim is doAssert and this is unlikely to change +# soon since there are a whole lot of doAsserts there. + diff --git a/nimsuggest/tests/tsug_regression.nim b/nimsuggest/tests/tsug_regression.nim new file mode 100644 index 000000000..1e440db2d --- /dev/null +++ b/nimsuggest/tests/tsug_regression.nim @@ -0,0 +1,28 @@ +# test we only get suggestions, not error messages: + +import tables, sets, parsecfg + +type X = object + +proc main = + # bug #52 + var + set0 = initSet[int]() + set1 = initSet[X]() + set2 = initSet[ref int]() + + map0 = initTable[int, int]() + map1 = initOrderedTable[string, int]() + cfg = loadConfig("file") + map0.#[!]# + +discard """ +$nimsuggest --tester $file +>sug $1 +sug;;skProc;;tables.getOrDefault;;proc (t: Table[getOrDefault.A, getOrDefault.B], key: A): B;;$lib/pure/collections/tables.nim;;178;;5;;"";;100;;None +sug;;skProc;;tables.hasKey;;proc (t: Table[hasKey.A, hasKey.B], key: A): bool;;$lib/pure/collections/tables.nim;;233;;5;;"returns true iff `key` is in the table `t`.";;100;;None +sug;;skProc;;tables.add;;proc (t: var Table[add.A, add.B], key: A, val: B);;$lib/pure/collections/tables.nim;;297;;5;;"puts a new (key, value)-pair into `t` even if ``t[key]`` already exists.";;100;;None +sug;;skIterator;;tables.allValues;;iterator (t: Table[allValues.A, allValues.B], key: A): B{.inline.};;$lib/pure/collections/tables.nim;;225;;9;;"iterates over any value in the table `t` that belongs to the given `key`.";;100;;None +sug;;skProc;;tables.clear;;proc (t: var Table[clear.A, clear.B]);;$lib/pure/collections/tables.nim;;121;;5;;"Resets the table so that it is empty.";;100;;None +* +""" diff --git a/nimsuggest/tests/twithin_macro.nim b/nimsuggest/tests/twithin_macro.nim new file mode 100644 index 000000000..e0df03542 --- /dev/null +++ b/nimsuggest/tests/twithin_macro.nim @@ -0,0 +1,213 @@ + +import macros + +macro class*(head, body: untyped): untyped = + # The macro is immediate, since all its parameters are untyped. + # This means, it doesn't resolve identifiers passed to it. + + var typeName, baseName: NimNode + + # flag if object should be exported + var exported: bool + + if head.kind == nnkInfix and head[0].ident == !"of": + # `head` is expression `typeName of baseClass` + # echo head.treeRepr + # -------------------- + # Infix + # Ident !"of" + # Ident !"Animal" + # Ident !"RootObj" + typeName = head[1] + baseName = head[2] + + elif head.kind == nnkInfix and head[0].ident == !"*" and + head[2].kind == nnkPrefix and head[2][0].ident == !"of": + # `head` is expression `typeName* of baseClass` + # echo head.treeRepr + # -------------------- + # Infix + # Ident !"*" + # Ident !"Animal" + # Prefix + # Ident !"of" + # Ident !"RootObj" + typeName = head[1] + baseName = head[2][1] + exported = true + + else: + quit "Invalid node: " & head.lispRepr + + # The following prints out the AST structure: + # + # import macros + # dumptree: + # type X = ref object of Y + # z: int + # -------------------- + # StmtList + # TypeSection + # TypeDef + # Ident !"X" + # Empty + # RefTy + # ObjectTy + # Empty + # OfInherit + # Ident !"Y" + # RecList + # IdentDefs + # Ident !"z" + # Ident !"int" + # Empty + + # create a type section in the result + result = + if exported: + # mark `typeName` with an asterisk + quote do: + type `typeName`* = ref object of `baseName` + else: + quote do: + type `typeName` = ref object of `baseName` + + # echo treeRepr(body) + # -------------------- + # StmtList + # VarSection + # IdentDefs + # Ident !"name" + # Ident !"string" + # Empty + # IdentDefs + # Ident !"age" + # Ident !"int" + # Empty + # MethodDef + # Ident !"vocalize" + # Empty + # Empty + # FormalParams + # Ident !"string" + # Empty + # Empty + # StmtList + # StrLit ... + # MethodDef + # Ident !"age_human_yrs" + # Empty + # Empty + # FormalParams + # Ident !"int" + # Empty + # Empty + # StmtList + # DotExpr + # Ident !"this" + # Ident !"age" + + # var declarations will be turned into object fields + var recList = newNimNode(nnkRecList) + + # expected name of constructor + let ctorName = newIdentNode("new" & $typeName) + + # Iterate over the statements, adding `this: T` + # to the parameters of functions, unless the + # function is a constructor + for node in body.children: + case node.kind: + + of nnkMethodDef, nnkProcDef: + # check if it is the ctor proc + if node.name.kind != nnkAccQuoted and node.name.basename == ctorName: + # specify the return type of the ctor proc + node.params[0] = typeName + else: + # inject `self: T` into the arguments + node.params.insert(1, newIdentDefs(ident("self"), typeName)) + result.add(node) + + of nnkVarSection: + # variables get turned into fields of the type. + for n in node.children: + recList.add(n) + + else: + result.add(node) + + # Inspect the tree structure: + # + # echo result.treeRepr + # -------------------- + # StmtList + # TypeSection + # TypeDef + # Ident !"Animal" + # Empty + # RefTy + # ObjectTy + # Empty + # OfInherit + # Ident !"RootObj" + # Empty <= We want to replace this + # MethodDef + # ... + + result[0][0][2][0][2] = recList + + # Lets inspect the human-readable version of the output + #echo repr(result) + +# --- + +class Animal of RootObj: + var name: string + var age: int + method vocalize: string {.base.} = "..." # use `base` pragma to annonate base methods + method age_human_yrs: int {.base.} = self.age # `this` is injected + proc `$`: string = "animal:" & self.name & ":" & $self.age + +class Dog of Animal: + method vocalize: string = "woof" + method age_human_yrs: int = self.age * 7 + proc `$`: string = "dog:" & self.name & ":" & $self.age + +class Cat of Animal: + method vocalize: string = "meow" + proc `$`: string = "cat:" & self.name & ":" & $self.age + +class Rabbit of Animal: + proc newRabbit(name: string, age: int) = # the constructor doesn't need a return type + result = Rabbit(name: name, age: age) + method vocalize: string = "meep" + proc `$`: string = + self.#[!]# + result = "rabbit:" & self.name & ":" & $self.age + +# --- + +var animals: seq[Animal] = @[] +animals.add(Dog(name: "Sparky", age: 10)) +animals.add(Cat(name: "Mitten", age: 10)) + +for a in animals: + echo a.vocalize() + echo a.age_human_yrs() + +let r = newRabbit("Fluffy", 3) +echo r.vocalize() +echo r.age_human_yrs() +echo r + +discard """ +$nimsuggest --tester $file +>sug $1 +sug;;skField;;age;;int;;$file;;167;;6;;"";;100;;None +sug;;skField;;name;;string;;$file;;166;;6;;"";;100;;None +sug;;skMethod;;twithin_macro.age_human_yrs;;proc (self: Animal): int;;$file;;169;;9;;"";;100;;None +sug;;skMethod;;twithin_macro.vocalize;;proc (self: Animal): string;;$file;;168;;9;;"";;100;;None +sug;;skMethod;;twithin_macro.vocalize;;proc (self: Rabbit): string;;$file;;184;;9;;"";;100;;None +sug;;skMacro;;twithin_macro.class;;proc (head: untyped, body: untyped): untyped{.gcsafe, locks: <unknown>.};;$file;;4;;6;;"";;50;;None* +""" diff --git a/nimsuggest/tests/twithin_macro_prefix.nim b/nimsuggest/tests/twithin_macro_prefix.nim new file mode 100644 index 000000000..86e406c5d --- /dev/null +++ b/nimsuggest/tests/twithin_macro_prefix.nim @@ -0,0 +1,209 @@ + +import macros + +macro class*(head, body: untyped): untyped = + # The macro is immediate, since all its parameters are untyped. + # This means, it doesn't resolve identifiers passed to it. + + var typeName, baseName: NimNode + + # flag if object should be exported + var exported: bool + + if head.kind == nnkInfix and head[0].ident == !"of": + # `head` is expression `typeName of baseClass` + # echo head.treeRepr + # -------------------- + # Infix + # Ident !"of" + # Ident !"Animal" + # Ident !"RootObj" + typeName = head[1] + baseName = head[2] + + elif head.kind == nnkInfix and head[0].ident == !"*" and + head[2].kind == nnkPrefix and head[2][0].ident == !"of": + # `head` is expression `typeName* of baseClass` + # echo head.treeRepr + # -------------------- + # Infix + # Ident !"*" + # Ident !"Animal" + # Prefix + # Ident !"of" + # Ident !"RootObj" + typeName = head[1] + baseName = head[2][1] + exported = true + + else: + quit "Invalid node: " & head.lispRepr + + # The following prints out the AST structure: + # + # import macros + # dumptree: + # type X = ref object of Y + # z: int + # -------------------- + # StmtList + # TypeSection + # TypeDef + # Ident !"X" + # Empty + # RefTy + # ObjectTy + # Empty + # OfInherit + # Ident !"Y" + # RecList + # IdentDefs + # Ident !"z" + # Ident !"int" + # Empty + + # create a type section in the result + result = + if exported: + # mark `typeName` with an asterisk + quote do: + type `typeName`* = ref object of `baseName` + else: + quote do: + type `typeName` = ref object of `baseName` + + # echo treeRepr(body) + # -------------------- + # StmtList + # VarSection + # IdentDefs + # Ident !"name" + # Ident !"string" + # Empty + # IdentDefs + # Ident !"age" + # Ident !"int" + # Empty + # MethodDef + # Ident !"vocalize" + # Empty + # Empty + # FormalParams + # Ident !"string" + # Empty + # Empty + # StmtList + # StrLit ... + # MethodDef + # Ident !"age_human_yrs" + # Empty + # Empty + # FormalParams + # Ident !"int" + # Empty + # Empty + # StmtList + # DotExpr + # Ident !"this" + # Ident !"age" + + # var declarations will be turned into object fields + var recList = newNimNode(nnkRecList) + + # expected name of constructor + let ctorName = newIdentNode("new" & $typeName) + + # Iterate over the statements, adding `this: T` + # to the parameters of functions, unless the + # function is a constructor + for node in body.children: + case node.kind: + + of nnkMethodDef, nnkProcDef: + # check if it is the ctor proc + if node.name.kind != nnkAccQuoted and node.name.basename == ctorName: + # specify the return type of the ctor proc + node.params[0] = typeName + else: + # inject `self: T` into the arguments + node.params.insert(1, newIdentDefs(ident("self"), typeName)) + result.add(node) + + of nnkVarSection: + # variables get turned into fields of the type. + for n in node.children: + recList.add(n) + + else: + result.add(node) + + # Inspect the tree structure: + # + # echo result.treeRepr + # -------------------- + # StmtList + # TypeSection + # TypeDef + # Ident !"Animal" + # Empty + # RefTy + # ObjectTy + # Empty + # OfInherit + # Ident !"RootObj" + # Empty <= We want to replace this + # MethodDef + # ... + + result[0][0][2][0][2] = recList + + # Lets inspect the human-readable version of the output + #echo repr(result) + +# --- + +class Animal of RootObj: + var name: string + var age: int + method vocalize: string {.base.} = "..." # use `base` pragma to annonate base methods + method age_human_yrs: int {.base.} = self.age # `this` is injected + proc `$`: string = "animal:" & self.name & ":" & $self.age + +class Dog of Animal: + method vocalize: string = "woof" + method age_human_yrs: int = self.age * 7 + proc `$`: string = "dog:" & self.name & ":" & $self.age + +class Cat of Animal: + method vocalize: string = "meow" + proc `$`: string = "cat:" & self.name & ":" & $self.age + +class Rabbit of Animal: + proc newRabbit(name: string, age: int) = # the constructor doesn't need a return type + result = Rabbit(name: name, age: age) + method vocalize: string = "meep" + proc `$`: string = + self.ag#[!]# + result = "rabbit:" & self.name & ":" & $self.age + +# --- + +var animals: seq[Animal] = @[] +animals.add(Dog(name: "Sparky", age: 10)) +animals.add(Cat(name: "Mitten", age: 10)) + +for a in animals: + echo a.vocalize() + echo a.age_human_yrs() + +let r = newRabbit("Fluffy", 3) +echo r.vocalize() +echo r.age_human_yrs() +echo r + +discard """ +$nimsuggest --tester $file +>sug $1 +sug;;skField;;age;;int;;$file;;167;;6;;"";;100;;Prefix +sug;;skMethod;;twithin_macro_prefix.age_human_yrs;;proc (self: Animal): int;;$file;;169;;9;;"";;100;;Prefix +""" |