checker: move struct name check from parser to checker

pull/4439/head
Daniel Däschle 2020-04-16 11:01:18 +02:00 committed by GitHub
parent 54a02996f2
commit 04db2d02b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 12 deletions

View File

@ -81,6 +81,21 @@ pub fn (c mut Checker) check_files(ast_files []ast.File) {
exit(1) 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 { 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 { // typ := c.table.find_type(struct_init.typ.typ.name) or {
// c.error('unknown struct: $struct_init.typ.typ.name', struct_init.pos) // 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 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') // println('check struct $typ_sym.name')
match typ_sym.kind { match type_sym.kind {
.placeholder { .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 // string & array are also structs but .kind of string/array
.struct_, .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 is_short_syntax := struct_init.fields.len == 0
if struct_init.exprs.len > info.fields.len { if struct_init.exprs.len > info.fields.len {
c.error('too many fields', struct_init.pos) 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 { 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) struct_init.pos)
continue continue
} }
@ -160,7 +176,7 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type {
continue continue
} }
if table.type_is_ptr(field.typ) { 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) struct_init.pos)
} }
} }
@ -991,7 +1007,9 @@ fn (c mut Checker) stmt(node ast.Stmt) {
c.returns = true c.returns = true
c.return_stmt(mut it) c.return_stmt(mut it)
} }
// ast.StructDecl {} ast.StructDecl {
c.struct_decl(it)
}
ast.UnsafeStmt { ast.UnsafeStmt {
c.stmts(it.stmts) c.stmts(it.stmts)
} }

View File

@ -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| }

View File

@ -0,0 +1,3 @@
struct abc {
}

View File

@ -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 x := p.call_expr(is_c, is_js, mod) // TODO `node,typ :=` should work
node = x node = x
} }
} else if p.peek_tok.kind == .lcbr && (p.tok.lit[0].is_capital() || is_c || is_js || (p.builtin_mod && } else if p.peek_tok.kind == .lcbr && !p.inside_match && !p.inside_match_case && !p.inside_if &&
p.tok.lit in table.builtin_type_names)) && !p.inside_match && !p.inside_match_case && !p.inside_if &&
!p.inside_for { !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 return p.struct_init(false) // short_syntax: false
} else if p.peek_tok.kind == .dot && (p.tok.lit[0].is_capital() && !known_var) { } else if p.peek_tok.kind == .dot && (p.tok.lit[0].is_capital() && !known_var) {
// `Color.green` // `Color.green`
@ -1546,6 +1543,7 @@ fn (p mut Parser) const_decl() ast.ConstDecl {
// structs and unions // structs and unions
fn (p mut Parser) struct_decl() ast.StructDecl { fn (p mut Parser) struct_decl() ast.StructDecl {
first_pos := p.tok.position()
is_pub := p.tok.kind == .key_pub is_pub := p.tok.kind == .key_pub
if is_pub { if is_pub {
p.next() p.next()
@ -1574,6 +1572,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
var mut_pos := -1 var mut_pos := -1
var pub_pos := -1 var pub_pos := -1
var pub_mut_pos := -1 var pub_mut_pos := -1
var last_pos := token.Position{}
if !no_body { if !no_body {
p.check(.lcbr) p.check(.lcbr)
for p.tok.kind != .rcbr { for p.tok.kind != .rcbr {
@ -1649,6 +1648,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
} }
// println('struct field $ti.name $field_name') // println('struct field $ti.name $field_name')
} }
last_pos = p.tok.position()
p.check(.rcbr) p.check(.rcbr)
} }
if is_c { 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.error('cannot register type `$name`, another type with this name exists')
} }
p.expr_mod = '' 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{ return ast.StructDecl{
name: name name: name
is_pub: is_pub is_pub: is_pub
fields: ast_fields fields: ast_fields
pos: p.tok.position() pos: pos
mut_pos: mut_pos mut_pos: mut_pos
pub_pos: pub_pos pub_pos: pub_pos
pub_mut_pos: pub_mut_pos pub_mut_pos: pub_mut_pos