From 06c1b9e95edddf049c2da2a80c58a07292261c2b Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Fri, 17 Apr 2020 17:16:14 +0200 Subject: [PATCH] table/checker: verify private functions/methods --- vlib/v/checker/checker.v | 32 +++++++++++---- .../tests/inout/struct_unknown_field.out | 4 +- vlib/v/parser/fn.v | 2 + vlib/v/parser/parser.v | 5 ++- vlib/v/table/atypes.v | 15 ++++--- vlib/v/table/cflags.v | 18 ++++---- vlib/v/table/table.v | 41 +++++++++---------- 7 files changed, 66 insertions(+), 51 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 300bf2b95c..e7e5296233 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -35,6 +35,8 @@ mut: // checked_ident string // to avoid infinit checker loops var_decl_name string returns bool + mod string // current module name + is_builtin_mod bool // are we in `builtin`? } pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker { @@ -150,7 +152,7 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type { } } if !exists { - c.error('struct init: no such field `$field.name` for struct `$type_sym.name`', field.pos) + c.error('unknown field `$field.name` in struct literal of type `$type_sym.name`', field.pos) continue } if field_name in inited_fields { @@ -320,6 +322,12 @@ pub fn (c mut Checker) call_method(call_expr mut ast.CallExpr) table.Type { return info.elem_type } if method := c.table.type_find_method(left_type_sym, method_name) { + if !method.is_pub && !c.is_builtin_mod && left_type_sym.mod != c.mod && left_type_sym.mod != '' { // method.mod != c.mod { + // If a private method is called outside of the module + // its receiver type is defined in, show an error. + //println('warn $method_name lef.mod=$left_type_sym.mod c.mod=$c.mod') + c.error('method `${left_type_sym.name}.$method_name` is private', call_expr.pos) + } no_args := method.args.len - 1 min_required_args := method.args.len - if method.is_variadic && method.args.len > 1 { 2 } else { 1 } if call_expr.args.len < min_required_args { @@ -1012,6 +1020,11 @@ fn (c mut Checker) stmt(node ast.Stmt) { } // ast.HashStmt {} ast.Import {} + ast.Module { + c.mod = it.name + c.is_builtin_mod = it.name == 'builtin' + } + // ast.GlobalDecl {} ast.Return { c.returns = true @@ -1635,7 +1648,14 @@ fn (c mut Checker) warn_or_error(message string, pos token.Position, warn bool) // if c.pref.is_verbose { // print_backtrace() // } - if !warn { + if warn { + c.warnings << scanner.Warning{ + reporter: scanner.Reporter.checker + pos: pos + file_path: c.file.path + message: message + } + } else { c.nr_errors++ if !(pos.line_nr in c.error_lines) { c.errors << scanner.Error{ @@ -1646,16 +1666,10 @@ fn (c mut Checker) warn_or_error(message string, pos token.Position, warn bool) } c.error_lines << pos.line_nr } - } else { - c.warnings << scanner.Warning{ - reporter: scanner.Reporter.checker - pos: pos - file_path: c.file.path - message: message - } } } +// for debugging only fn (p Checker) fileis(s string) bool { return p.file.path.contains(s) } diff --git a/vlib/v/checker/tests/inout/struct_unknown_field.out b/vlib/v/checker/tests/inout/struct_unknown_field.out index 9f6f87ab24..68365cdccb 100644 --- a/vlib/v/checker/tests/inout/struct_unknown_field.out +++ b/vlib/v/checker/tests/inout/struct_unknown_field.out @@ -1,7 +1,7 @@ -vlib/v/checker/tests/inout/struct_unknown_field.v:8:9: error: struct init: no such field `bar` for struct `Test` +vlib/v/checker/tests/inout/struct_unknown_field.v:8:9: error: unknown field `bar` in struct literal `Test` 6| t := Test{ 7| foo: true 8| bar: false ^ 9| } - 10| } \ No newline at end of file + 10| } diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index f1ff03f5de..90e3a1d82d 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -180,6 +180,7 @@ fn (var p Parser) fn_decl() ast.FnDecl { return_type: return_type is_variadic: is_variadic is_generic: is_generic + is_pub: is_pub }) } else { if is_c { @@ -200,6 +201,7 @@ fn (var p Parser) fn_decl() ast.FnDecl { is_c: is_c is_js: is_js is_generic: is_generic + is_pub: is_pub }) } // Body diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index b22a240fe9..271f039b63 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -26,8 +26,8 @@ mut: inside_for bool inside_fn bool pref &pref.Preferences - builtin_mod bool - mod string + builtin_mod bool // are we in the `builtin` module? + mod string // current module name attr string expr_mod string scope &ast.Scope @@ -1690,6 +1690,7 @@ fn (var p Parser) struct_decl() ast.StructDecl { is_typedef: is_typedef is_union: is_union } + mod: p.mod } var ret := 0 if p.builtin_mod && t.name in table.builtin_type_names { diff --git a/vlib/v/table/atypes.v b/vlib/v/table/atypes.v index b52feff73a..6809b90c15 100644 --- a/vlib/v/table/atypes.v +++ b/vlib/v/table/atypes.v @@ -11,10 +11,8 @@ // idx: u16(type) & 0xffff module table -import ( - strings - v.ast -) +import strings +import v.ast pub type Type int @@ -28,6 +26,7 @@ mut: kind Kind name string methods []Fn + mod string } pub enum TypeFlag { @@ -310,7 +309,7 @@ pub fn (t TypeSymbol) str() string { return t.name } */ -pub fn (t mut Table) register_builtin_type_symbols() { +pub fn (var t Table) register_builtin_type_symbols() { // reserve index 0 so nothing can go there // save index check, 0 will mean not found t.register_type_symbol(TypeSymbol{ @@ -527,7 +526,7 @@ pub fn (k Kind) str() string { } pub fn (kinds []Kind) str() string { - mut kinds_str := '' + var kinds_str := '' for i, k in kinds { kinds_str += k.str() if i < kinds.len - 1 { @@ -594,7 +593,7 @@ pub: pub fn (table &Table) type_to_str(t Type) string { sym := table.get_type_symbol(t) if sym.kind == .multi_return { - mut res := '(' + var res := '(' mr_info := sym.info as MultiReturn for i, typ in mr_info.types { res += table.type_to_str(typ) @@ -605,7 +604,7 @@ pub fn (table &Table) type_to_str(t Type) string { res += ')' return res } - mut res := sym.name + var res := sym.name if sym.kind == .array { res = res.replace('array_', '[]') } else if sym.kind == .map { diff --git a/vlib/v/table/cflags.v b/vlib/v/table/cflags.v index d0f1a73a4e..380e3266ab 100644 --- a/vlib/v/table/cflags.v +++ b/vlib/v/table/cflags.v @@ -17,15 +17,15 @@ fn (table &Table) has_cflag(cflag builder.CFlag) bool { // parse the flags to (table.cflags) []CFlag // Note: clean up big time (joe-c) -fn (table mut Table) parse_cflag(cflag, mod string, ctimedefines []string) ?bool { +pub fn (var table Table) parse_cflag(cflag, mod string, ctimedefines []string) ?bool { allowed_flags := ['framework', 'library', 'Wa', 'Wl', 'Wp', 'I', 'l', 'L'] flag_orig := cflag.trim_space() - mut flag := flag_orig + var flag := flag_orig if flag == '' { return true } - mut fos := '' - mut allowed_os_overrides := ['linux', 'darwin', 'freebsd', 'windows', 'mingw', 'solaris'] + var fos := '' + var allowed_os_overrides := ['linux', 'darwin', 'freebsd', 'windows', 'mingw', 'solaris'] allowed_os_overrides << ctimedefines for os_override in allowed_os_overrides { if !flag.starts_with(os_override) { @@ -37,9 +37,9 @@ fn (table mut Table) parse_cflag(cflag, mod string, ctimedefines []string) ?bool fos = flag[..pos].trim_space() flag = flag[pos..].trim_space() } - for { - mut name := '' - mut value := '' + for { + var name := '' + var value := '' if flag[0] == `-` { for f in allowed_flags { i := 1 + f.len @@ -50,11 +50,11 @@ fn (table mut Table) parse_cflag(cflag, mod string, ctimedefines []string) ?bool } } } - mut index := flag.index(' -') or { + var index := flag.index(' -') or { -1 } for index > -1 { - mut has_next := false + var has_next := false for f in allowed_flags { i := index + 2 + f.len if i <= flag.len && f == flag[index + 2..i] { diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index a04e4b084b..3d8d0a30f4 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -3,10 +3,8 @@ // that can be found in the LICENSE file. module table -import ( - os - v.builder -) +import os +import v.builder pub struct Table { pub mut: @@ -25,8 +23,10 @@ pub: return_type Type is_variadic bool is_c bool - is_js bool + is_js bool is_generic bool + is_pub bool + mod string } pub struct Arg { @@ -45,14 +45,14 @@ mut: } pub fn new_table() &Table { - mut t := &Table{} + var t := &Table{} t.register_builtin_type_symbols() return t } // used to compare fn's & for naming anon fn's pub fn (f &Fn) signature() string { - mut sig := '' + var sig := '' for i, arg in f.args { // TODO: for now ignore mut/pts in sig for now typ := type_set_nr_muls(arg.typ, 0) @@ -85,12 +85,12 @@ pub fn (t &Table) known_fn(name string) bool { return true } -pub fn (t mut Table) register_fn(new_fn Fn) { +pub fn (var t Table) register_fn(new_fn Fn) { // println('reg fn $new_fn.name nr_args=$new_fn.args.len') t.fns[new_fn.name] = new_fn } -pub fn (t mut TypeSymbol) register_method(new_fn Fn) { +pub fn (var t TypeSymbol) register_method(new_fn Fn) { t.methods << new_fn } @@ -142,7 +142,7 @@ pub fn (t &Table) type_has_method(s &TypeSymbol, name string) bool { // search from current type up through each parent looking for method pub fn (t &Table) type_find_method(s &TypeSymbol, name string) ?Fn { // println('type_find_method($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx') - mut ts := s + var ts := s for { if method := ts.find_method(name) { return method @@ -166,7 +166,7 @@ pub fn (t &Table) struct_has_field(s &TypeSymbol, name string) bool { // search from current type up through each parent looking for field pub fn (t &Table) struct_find_field(s &TypeSymbol, name string) ?Field { // println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx') - mut ts := s + var ts := s for { if field := ts.find_field(name) { return field @@ -210,12 +210,11 @@ pub fn (t &Table) get_type_name(typ Type) string { return typ_sym.name } - // this will override or register builtin type // allows prexisitng types added in register_builtins // to be overriden with their real type info [inline] -pub fn (t mut Table) register_builtin_type_symbol(typ TypeSymbol) int { +pub fn (var t Table) register_builtin_type_symbol(typ TypeSymbol) int { existing_idx := t.type_idxs[typ.name] if existing_idx > 0 { if existing_idx >= string_type_idx { @@ -235,7 +234,7 @@ pub fn (t mut Table) register_builtin_type_symbol(typ TypeSymbol) int { } [inline] -pub fn (t mut Table) register_type_symbol(typ TypeSymbol) int { +pub fn (var t Table) register_type_symbol(typ TypeSymbol) int { // println('register_type_symbol( $typ.name )') existing_idx := t.type_idxs[typ.name] if existing_idx > 0 { @@ -309,7 +308,7 @@ pub fn (t &Table) map_name(key_type, value_type Type) string { // return 'map_${value_type_sym.name}' + suffix } -pub fn (t mut Table) find_or_register_map(key_type, value_type Type) int { +pub fn (var t Table) find_or_register_map(key_type, value_type Type) int { name := t.map_name(key_type, value_type) // existing existing_idx := t.type_idxs[name] @@ -329,7 +328,7 @@ pub fn (t mut Table) find_or_register_map(key_type, value_type Type) int { return t.register_type_symbol(map_typ) } -pub fn (t mut Table) find_or_register_array(elem_type Type, nr_dims int) int { +pub fn (var t Table) find_or_register_array(elem_type Type, nr_dims int) int { name := t.array_name(elem_type, nr_dims) // existing existing_idx := t.type_idxs[name] @@ -349,7 +348,7 @@ pub fn (t mut Table) find_or_register_array(elem_type Type, nr_dims int) int { return t.register_type_symbol(array_type) } -pub fn (t mut Table) find_or_register_array_fixed(elem_type Type, size, nr_dims int) int { +pub fn (var t Table) find_or_register_array_fixed(elem_type Type, size, nr_dims int) int { name := t.array_fixed_name(elem_type, size, nr_dims) // existing existing_idx := t.type_idxs[name] @@ -369,8 +368,8 @@ pub fn (t mut Table) find_or_register_array_fixed(elem_type Type, size, nr_dims return t.register_type_symbol(array_fixed_type) } -pub fn (t mut Table) find_or_register_multi_return(mr_typs []Type) int { - mut name := 'multi_return' +pub fn (var t Table) find_or_register_multi_return(mr_typs []Type) int { + var name := 'multi_return' for mr_typ in mr_typs { mr_type_sym := t.get_type_symbol(mr_typ) name += '_$mr_type_sym.name' @@ -391,7 +390,7 @@ pub fn (t mut Table) find_or_register_multi_return(mr_typs []Type) int { return t.register_type_symbol(mr_type) } -pub fn (t mut Table) find_or_register_fn_type(f Fn, has_decl bool) int { +pub fn (var t Table) find_or_register_fn_type(f Fn, has_decl bool) int { is_anon := f.name.len == 0 name := if is_anon { 'anon_fn_$f.signature()' } else { f.name } return t.register_type_symbol(TypeSymbol{ @@ -405,7 +404,7 @@ pub fn (t mut Table) find_or_register_fn_type(f Fn, has_decl bool) int { }) } -pub fn (t mut Table) add_placeholder_type(name string) int { +pub fn (var t Table) add_placeholder_type(name string) int { ph_type := TypeSymbol{ kind: .placeholder name: name