import v.ast import v.ast.walker import v.parser import v.pref fn parse_text(text string) &ast.File { mut tbl := ast.new_table() prefs := pref.new_preferences() return parser.parse_text(text, '', mut tbl, .skip_comments, prefs) } struct NodeByOffset { pos int mut: node ast.Node } fn (mut n NodeByOffset) visit(node &ast.Node) ! { node_pos := node.pos() if n.pos >= node_pos.pos && n.pos <= node_pos.pos + node_pos.len && node !is ast.File { n.node = node return error('') } return } fn test_walk() { source := ' module main struct Foo { name string } ' file := parse_text(source) mut nbo := NodeByOffset{ pos: 13 } walker.walk(mut nbo, file) assert nbo.node is ast.Stmt stmt := nbo.node as ast.Stmt assert stmt is ast.StructDecl } fn test_inspect() { source := ' module main ' file := parse_text(source) walker.inspect(file, unsafe { nil }, fn (node &ast.Node, data voidptr) bool { // Second visit must be ast.Stmt if node is ast.Stmt { if node !is ast.Module { // Proceed to another node return false } assert node is ast.Module mod := node as ast.Module assert mod.name == 'main' return false } assert node is ast.File // True means that the inspector must now // inspect the ast.File's children return true }) }