From 04db2d02b8b7ee4a7fa0c1b1f88a0f0f53e24e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A4schle?= Date: Thu, 16 Apr 2020 11:01:18 +0200 Subject: [PATCH] checker: move struct name check from parser to checker --- vlib/v/checker/checker.v | 32 +++++++++++++++++----- vlib/v/checker/tests/inout/struct_name.out | 5 ++++ vlib/v/checker/tests/inout/struct_name.vv | 3 ++ vlib/v/parser/parser.v | 15 ++++++---- 4 files changed, 43 insertions(+), 12 deletions(-) create mode 100644 vlib/v/checker/tests/inout/struct_name.out create mode 100644 vlib/v/checker/tests/inout/struct_name.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 3258fa0433..b581c4b5e9 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -81,6 +81,21 @@ pub fn (c mut Checker) check_files(ast_files []ast.File) { exit(1) } +pub fn (c mut Checker) struct_decl(decl ast.StructDecl) { + splitted_full_name := decl.name.split('.') + is_builtin := splitted_full_name[0] == 'builtin' + name := splitted_full_name.last() + if !name[0].is_capital() && !decl.is_c && !is_builtin && name !in table.builtin_type_names { + pos := token.Position{ + line_nr: decl.pos.line_nr + pos: decl.pos.pos + 7 + len: name.len + } + c.error('struct name must begin with capital letter', pos) + } + // && (p.tok.lit[0].is_capital() || is_c || (p.builtin_mod && Sp.tok.lit in table.builtin_type_names)) +} + pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type { // typ := c.table.find_type(struct_init.typ.typ.name) or { // c.error('unknown struct: $struct_init.typ.typ.name', struct_init.pos) @@ -94,15 +109,16 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type { } struct_init.typ = c.expected_type } - typ_sym := c.table.get_type_symbol(struct_init.typ) + type_sym := c.table.get_type_symbol(struct_init.typ) + // println('check struct $typ_sym.name') - match typ_sym.kind { + match type_sym.kind { .placeholder { - c.error('unknown struct: $typ_sym.name', struct_init.pos) + c.error('unknown struct: $type_sym.name', struct_init.pos) } // string & array are also structs but .kind of string/array .struct_, .string, .array { - info := typ_sym.info as table.Struct + info := type_sym.info as table.Struct is_short_syntax := struct_init.fields.len == 0 if struct_init.exprs.len > info.fields.len { c.error('too many fields', struct_init.pos) @@ -138,7 +154,7 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type { } } if !found_field { - c.error('struct init: no such field `$field_name` for struct `$typ_sym.name`', + c.error('struct init: no such field `$field_name` for struct `$type_sym.name`', struct_init.pos) continue } @@ -160,7 +176,7 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type { continue } if table.type_is_ptr(field.typ) { - c.warn('reference field `${typ_sym.name}.${field.name}` must be initialized', + c.warn('reference field `${type_sym.name}.${field.name}` must be initialized', struct_init.pos) } } @@ -991,7 +1007,9 @@ fn (c mut Checker) stmt(node ast.Stmt) { c.returns = true c.return_stmt(mut it) } - // ast.StructDecl {} + ast.StructDecl { + c.struct_decl(it) + } ast.UnsafeStmt { c.stmts(it.stmts) } diff --git a/vlib/v/checker/tests/inout/struct_name.out b/vlib/v/checker/tests/inout/struct_name.out new file mode 100644 index 0000000000..9f14566f07 --- /dev/null +++ b/vlib/v/checker/tests/inout/struct_name.out @@ -0,0 +1,5 @@ +vlib/v/checker/tests/inout/struct_name.v:1:8: error: struct name must begin with capital letter + 1| struct abc { + ~~~ + 2| + 3| } \ No newline at end of file diff --git a/vlib/v/checker/tests/inout/struct_name.vv b/vlib/v/checker/tests/inout/struct_name.vv new file mode 100644 index 0000000000..ee903a2252 --- /dev/null +++ b/vlib/v/checker/tests/inout/struct_name.vv @@ -0,0 +1,3 @@ +struct abc { + +} diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 9a94ef9b9b..5d5f369d2a 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -696,11 +696,8 @@ pub fn (p mut Parser) name_expr() ast.Expr { x := p.call_expr(is_c, is_js, mod) // TODO `node,typ :=` should work node = x } - } else if p.peek_tok.kind == .lcbr && (p.tok.lit[0].is_capital() || is_c || is_js || (p.builtin_mod && - p.tok.lit in table.builtin_type_names)) && !p.inside_match && !p.inside_match_case && !p.inside_if && + } else if p.peek_tok.kind == .lcbr && !p.inside_match && !p.inside_match_case && !p.inside_if && !p.inside_for { - // (p.tok.lit.len in [1, 2] || !p.tok.lit[p.tok.lit.len - 1].is_capital()) && - // || p.table.known_type(p.tok.lit)) { return p.struct_init(false) // short_syntax: false } else if p.peek_tok.kind == .dot && (p.tok.lit[0].is_capital() && !known_var) { // `Color.green` @@ -1546,6 +1543,7 @@ fn (p mut Parser) const_decl() ast.ConstDecl { // structs and unions fn (p mut Parser) struct_decl() ast.StructDecl { + first_pos := p.tok.position() is_pub := p.tok.kind == .key_pub if is_pub { p.next() @@ -1574,6 +1572,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl { var mut_pos := -1 var pub_pos := -1 var pub_mut_pos := -1 + var last_pos := token.Position{} if !no_body { p.check(.lcbr) for p.tok.kind != .rcbr { @@ -1649,6 +1648,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl { } // println('struct field $ti.name $field_name') } + last_pos = p.tok.position() p.check(.rcbr) } if is_c { @@ -1679,11 +1679,16 @@ fn (p mut Parser) struct_decl() ast.StructDecl { p.error('cannot register type `$name`, another type with this name exists') } p.expr_mod = '' + pos := token.Position{ + line_nr: first_pos.line_nr + pos: first_pos.pos + len: last_pos.pos - first_pos.pos + last_pos.len + } return ast.StructDecl{ name: name is_pub: is_pub fields: ast_fields - pos: p.tok.position() + pos: pos mut_pos: mut_pos pub_pos: pub_pos pub_mut_pos: pub_mut_pos