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:
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:

View File

@ -414,12 +414,7 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
}
}
.lsbr {
start_pos := p.tok.position()
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))
}
attrs := p.attributes(true)
return attrs[0]
}
.key_interface {
@ -626,11 +621,19 @@ fn (mut p Parser) expr_list() []ast.Expr {
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{}
p.check(.lsbr)
for p.tok.kind != .rsbr {
start_pos := p.tok.position()
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
if p.tok.kind != .semicolon {
expected := `;`
@ -642,11 +645,13 @@ fn (mut p Parser) attributes() []ast.Attr {
}
p.next()
}
if attrs.len == 0 {
p.error_with_pos('attributes cannot be empty', p.prev_tok.position().extend(p.tok.position()))
}
return attrs
}
fn (mut p Parser) parse_attr() ast.Attr {
start_pos := p.prev_tok.position()
mut is_if_attr := false
if p.tok.kind == .key_if {
p.next()
@ -663,10 +668,6 @@ fn (mut p Parser) parse_attr() ast.Attr {
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 {
p.attr_ctdefine = name
}

View File

@ -117,7 +117,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
*/
mut attrs := []string{}
if p.tok.kind == .lsbr {
parsed_attrs := p.attributes()
parsed_attrs := p.attributes(false)
for attr in parsed_attrs {
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]
2 | [inline]
| ~~~~~~~~
| ~~~~~~
3 | fn foo() {}
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]
| ~~~~~~~~~
| ~~~~~~
2 | fn foo() {}
3 |