I've written very simple macro just for testing purposes. It's a copypaste from my nim package to figure out the problem. The problem is that I really don't understand the rules of lineinfoobj setting. If I loose the line info like in getNameAndBase proc and copy line info from head to the typeDef node, i've created - nimsuggest shows that the type is created within the module containing the macro declaration (tmacro.nim). BUT if I set the line info back to the ident node of the type name typName - nimsuggest shows that the type is properly created and line info is correctly set to it.
The file containing the macro tmacro.nim:
import std/macros
proc getNameAndBase(head: NimNode): (string, string) {.compiletime.} =
var classname: string
var basename: string
case head.kind
of nnkIdent:
classname = $head
of nnkInfix:
if eqIdent(head[0], "of"):
classname = $head[1]
case head[2].kind
of nnkIdent:
basename = $head[2]
else:
error("Error in class parents", head[2])
else:
classname = $head[1]
else:
error("Error in class header " & head.treeRepr, head)
result = (classname, basename)
macro createType*(head, body: untyped): untyped =
let (classname, basename) = getNameAndBase(head)
let typName = classname.ident
typName.setLineInfo(head.lineInfoObj)
var typ = nnkTypeDef.newTree(
nnkPostfix.newTree(
ident "*",
typName
),
newEmptyNode(),
nnkRefTy.newTree(
nnkObjectTy.newTree(
newEmptyNode(),
(
nnkOfInherit.newTree(
(if basename.len > 0: basename.ident else: ident "RootObj")
)
),
nnkRecList.newTree()
)
)
)
typ.setLineInfo(head.lineInfoObj)
var ts = nnkTypeSection.newTree(
typ
)
result = newStmtList(ts)
The file containing the test code:
import tmacro
createType MySecondType:
var y: float
Are there any rules on using the line info object when creating manually nim nodes?
The rule is: Write your macros so that they preserve line information.
However, these is a heuristic in Nim's VM that tries to get the line information right in the absense of well written macro code. Look for ` comesFromHeuristic` in compiler/vm.nim
The rule is: Write your macros so that they preserve line information.
this is not so easy because quote do and other macro-readability-increasing constructs eat line information - highly annoying, and the API for constructing macro line information is quite difficult to use / follow. Would be nice if line info was preserved more often but to properly solve this, one would have to keep separate line info for "expanded location" and "source location".