ast, parser: add additional pos info for FnDecl and InterfaceDecl nodes (#9603)

pull/9610/head
Ned Palacios 2021-04-05 23:14:21 +08:00 committed by GitHub
parent 6ed50e7678
commit 07b1dc66dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 31 additions and 18 deletions

View File

@ -259,6 +259,7 @@ pub:
pub struct InterfaceDecl { pub struct InterfaceDecl {
pub: pub:
name string name string
name_pos token.Position
field_names []string field_names []string
is_pub bool is_pub bool
methods []FnDecl methods []FnDecl
@ -365,7 +366,6 @@ pub:
language Language language Language
no_body bool // just a definition `fn C.malloc()` no_body bool // just a definition `fn C.malloc()`
is_builtin bool // this function is defined in builtin/strconv is_builtin bool // this function is defined in builtin/strconv
pos token.Position // function declaration position
body_pos token.Position // function bodys position body_pos token.Position // function bodys position
file string file string
generic_params []GenericParam generic_params []GenericParam
@ -373,15 +373,17 @@ pub:
attrs []Attr attrs []Attr
skip_gen bool // this function doesn't need to be generated (for example [if foo]) skip_gen bool // this function doesn't need to be generated (for example [if foo])
pub mut: pub mut:
stmts []Stmt stmts []Stmt
defer_stmts []DeferStmt defer_stmts []DeferStmt
return_type Type return_type Type
has_return bool return_type_pos token.Position // `string` in `fn (u User) name() string` position
comments []Comment // comments *after* the header, but *before* `{`; used for InterfaceDecl has_return bool
next_comments []Comment // coments that are one line after the decl; used for InterfaceDecl comments []Comment // comments *after* the header, but *before* `{`; used for InterfaceDecl
source_file &File = 0 next_comments []Comment // coments that are one line after the decl; used for InterfaceDecl
scope &Scope source_file &File = 0
label_names []string scope &Scope
label_names []string
pos token.Position // function declaration position
} }
pub struct GenericParam { pub struct GenericParam {
@ -1603,7 +1605,7 @@ pub fn (node Node) position() token.Position {
StructField { StructField {
return node.pos.extend(node.type_pos) return node.pos.extend(node.type_pos)
} }
MatchBranch, SelectBranch, EnumField, ConstField, StructInitField, GlobalField, Param { MatchBranch, SelectBranch, EnumField, ConstField, StructInitField, GlobalField, CallArg {
return node.pos return node.pos
} }
IfBranch { IfBranch {
@ -1625,6 +1627,9 @@ pub fn (node Node) position() token.Position {
} }
} }
} }
Param {
return node.pos.extend(node.type_pos)
}
File { File {
mut pos := token.Position{} mut pos := token.Position{}
if node.stmts.len > 0 { if node.stmts.len > 0 {
@ -1634,9 +1639,6 @@ pub fn (node Node) position() token.Position {
} }
return pos return pos
} }
CallArg {
return node.pos
}
} }
} }
@ -1719,7 +1721,8 @@ pub fn (node Node) children() []Node {
children << node.expr children << node.expr
} }
InterfaceDecl { InterfaceDecl {
return node.methods.map(Node(Stmt(it))) children << node.methods.map(Node(Stmt(it)))
children << node.fields.map(Node(it))
} }
AssignStmt { AssignStmt {
children << node.left.map(Node(it)) children << node.left.map(Node(it))

View File

@ -353,7 +353,7 @@ pub fn (mut c Checker) interface_decl(decl ast.InterfaceDecl) {
for method in decl.methods { for method in decl.methods {
c.check_valid_snake_case(method.name, 'method name', method.pos) c.check_valid_snake_case(method.name, 'method name', method.pos)
if method.return_type != ast.Type(0) { if method.return_type != ast.Type(0) {
c.ensure_type_exists(method.return_type, method.pos) or { return } c.ensure_type_exists(method.return_type, method.return_type_pos) or { return }
} }
for param in method.params { for param in method.params {
c.ensure_type_exists(param.typ, param.pos) or { return } c.ensure_type_exists(param.typ, param.pos) or { return }

View File

@ -1,8 +1,8 @@
vlib/v/checker/tests/interface_return_parameter_err.vv:2:5: error: unknown type `Baz`. vlib/v/checker/tests/interface_return_parameter_err.vv:2:17: error: unknown type `Baz`.
Did you mean `Foo`? Did you mean `Foo`?
1 | interface Foo { 1 | interface Foo {
2 | bar(string) []Baz 2 | bar(string) []Baz
| ~~~~~~~~~~~ | ~~~~~
3 | bar2(Bax) string 3 | bar2(Bax) string
4 | } 4 | }
vlib/v/checker/tests/interface_return_parameter_err.vv:3:10: error: unknown type `Bax`. vlib/v/checker/tests/interface_return_parameter_err.vv:3:10: error: unknown type `Bax`.

View File

@ -293,12 +293,14 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
} }
} }
// Return type // Return type
mut return_type_pos := p.tok.position()
mut return_type := ast.void_type mut return_type := ast.void_type
// don't confuse token on the next line: fn decl, [attribute] // don't confuse token on the next line: fn decl, [attribute]
same_line := p.tok.line_nr == p.prev_tok.line_nr same_line := p.tok.line_nr == p.prev_tok.line_nr
if (p.tok.kind.is_start_of_type() && (same_line || p.tok.kind != .lsbr)) if (p.tok.kind.is_start_of_type() && (same_line || p.tok.kind != .lsbr))
|| (same_line && p.tok.kind == .key_fn) { || (same_line && p.tok.kind == .key_fn) {
return_type = p.parse_type() return_type = p.parse_type()
return_type_pos = return_type_pos.extend(p.prev_tok.position())
} }
mut type_sym_method_idx := 0 mut type_sym_method_idx := 0
no_body := p.tok.kind != .lcbr no_body := p.tok.kind != .lcbr
@ -398,6 +400,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
mod: p.mod mod: p.mod
stmts: stmts stmts: stmts
return_type: return_type return_type: return_type
return_type_pos: return_type_pos
params: params params: params
is_manualfree: is_manualfree is_manualfree: is_manualfree
is_deprecated: is_deprecated is_deprecated: is_deprecated
@ -574,10 +577,12 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
} }
mut same_line := p.tok.line_nr == p.prev_tok.line_nr mut same_line := p.tok.line_nr == p.prev_tok.line_nr
mut return_type := ast.void_type mut return_type := ast.void_type
mut return_type_pos := p.tok.position()
// lpar: multiple return types // lpar: multiple return types
if same_line { if same_line {
if p.tok.kind.is_start_of_type() { if p.tok.kind.is_start_of_type() {
return_type = p.parse_type() return_type = p.parse_type()
return_type_pos = return_type_pos.extend(p.tok.position())
} else if p.tok.kind != .lcbr { } else if p.tok.kind != .lcbr {
p.error_with_pos('expected return type, not $p.tok for anonymous function', p.error_with_pos('expected return type, not $p.tok for anonymous function',
p.tok.position()) p.tok.position())
@ -618,6 +623,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
mod: p.mod mod: p.mod
stmts: stmts stmts: stmts
return_type: return_type return_type: return_type
return_type_pos: return_type_pos
params: args params: args
is_variadic: is_variadic is_variadic: is_variadic
is_method: false is_method: false

View File

@ -518,7 +518,10 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
scope: p.scope scope: p.scope
} }
if p.tok.kind.is_start_of_type() && p.tok.line_nr == line_nr { if p.tok.kind.is_start_of_type() && p.tok.line_nr == line_nr {
method.return_type_pos = p.tok.position()
method.return_type = p.parse_type() method.return_type = p.parse_type()
method.return_type_pos = method.return_type_pos.extend(p.tok.position())
method.pos = method.pos.extend(method.return_type_pos)
} }
mcomments := p.eat_comments(same_line: true) mcomments := p.eat_comments(same_line: true)
mnext_comments := p.eat_comments({}) mnext_comments := p.eat_comments({})
@ -577,5 +580,6 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
pos: pos pos: pos
pre_comments: pre_comments pre_comments: pre_comments
mut_pos: mut_pos mut_pos: mut_pos
name_pos: name_pos
} }
} }