parser: fix incorrect duplicate struct attr error

pull/5406/head
joe-conigliaro 2020-06-17 20:27:51 +10:00
parent 0052ab71e9
commit effa0061e8
No known key found for this signature in database
GPG Key ID: C12F7136C08206F1
5 changed files with 26 additions and 17 deletions

View File

@ -567,6 +567,14 @@ pub struct Attr {
pub: pub:
name string name string
} }
pub fn (attrs []Attr) contains(attr Attr) bool {
for a in attrs {
if attr.name == a.name {
return true
}
}
return false
}
pub struct EnumVal { pub struct EnumVal {
pub: pub:

View File

@ -414,12 +414,7 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
} }
} }
.lsbr { .lsbr {
start_pos := p.tok.position() attrs := p.attributes(true)
attrs := p.attributes()
if attrs.len == 0 {
end_pos := p.tok.position()
p.error_with_pos('attributes cannot be empty', start_pos.extend(end_pos))
}
return attrs[0] return attrs[0]
} }
.key_interface { .key_interface {
@ -626,11 +621,19 @@ fn (mut p Parser) expr_list() []ast.Expr {
return exprs return exprs
} }
fn (mut p Parser) attributes() []ast.Attr { // when is_top_stmt is true attrs are added to p.attrs
fn (mut p Parser) attributes(is_top_stmt bool) []ast.Attr {
mut attrs := []ast.Attr{} mut attrs := []ast.Attr{}
p.check(.lsbr) p.check(.lsbr)
for p.tok.kind != .rsbr { for p.tok.kind != .rsbr {
start_pos := p.tok.position()
attr := p.parse_attr() attr := p.parse_attr()
if attr in attrs || (is_top_stmt && attr.name in p.attrs) {
p.error_with_pos('duplicate attribute `$attr.name`', start_pos.extend(p.prev_tok.position()))
}
if is_top_stmt {
p.attrs << attr.name
}
attrs << attr attrs << attr
if p.tok.kind != .semicolon { if p.tok.kind != .semicolon {
expected := `;` expected := `;`
@ -642,11 +645,13 @@ fn (mut p Parser) attributes() []ast.Attr {
} }
p.next() p.next()
} }
if attrs.len == 0 {
p.error_with_pos('attributes cannot be empty', p.prev_tok.position().extend(p.tok.position()))
}
return attrs return attrs
} }
fn (mut p Parser) parse_attr() ast.Attr { fn (mut p Parser) parse_attr() ast.Attr {
start_pos := p.prev_tok.position()
mut is_if_attr := false mut is_if_attr := false
if p.tok.kind == .key_if { if p.tok.kind == .key_if {
p.next() p.next()
@ -663,10 +668,6 @@ fn (mut p Parser) parse_attr() ast.Attr {
p.next() p.next()
} }
} }
if name in p.attrs {
p.error_with_pos('duplicate attribute `$name`', start_pos.extend(p.tok.position()))
}
p.attrs << name
if is_if_attr { if is_if_attr {
p.attr_ctdefine = name p.attr_ctdefine = name
} }

View File

@ -117,7 +117,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
*/ */
mut attrs := []string{} mut attrs := []string{}
if p.tok.kind == .lsbr { if p.tok.kind == .lsbr {
parsed_attrs := p.attributes() parsed_attrs := p.attributes(false)
for attr in parsed_attrs { for attr in parsed_attrs {
attrs << attr.name attrs << attr.name
} }

View File

@ -1,6 +1,6 @@
vlib/v/parser/tests/fn_attributes_duplicate_multiple.v:2:1: error: duplicate attribute `inline` vlib/v/parser/tests/fn_attributes_duplicate_multiple.v:2:2: error: duplicate attribute `inline`
1 | [inline] 1 | [inline]
2 | [inline] 2 | [inline]
| ~~~~~~~~ | ~~~~~~
3 | fn foo() {} 3 | fn foo() {}
4 | 4 |

View File

@ -1,5 +1,5 @@
vlib/v/parser/tests/fn_attributes_duplicate_single.v:1:8: error: duplicate attribute `inline` vlib/v/parser/tests/fn_attributes_duplicate_single.v:1:10: error: duplicate attribute `inline`
1 | [inline; inline] 1 | [inline; inline]
| ~~~~~~~~~ | ~~~~~~
2 | fn foo() {} 2 | fn foo() {}
3 | 3 |