all: support _test.vv files (to test _test.v errors/checks too)
parent
5564a2c1da
commit
760b4c37b9
|
@ -545,7 +545,7 @@ fn (mut v Builder) cc() {
|
|||
builtin_obj_path := v.rebuild_cached_module(vexe, 'vlib/builtin')
|
||||
libs << builtin_obj_path
|
||||
for ast_file in v.parsed_files {
|
||||
is_test := ast_file.path.ends_with('_test.v')
|
||||
is_test := ast_file.path.ends_with('_test.v') || ast_file.path.ends_with('_test.vv')
|
||||
if is_test && ast_file.mod.name != 'main' {
|
||||
imp_path := v.find_module_path(ast_file.mod.name, ast_file.path) or {
|
||||
verror('cannot import module "$ast_file.mod.name" (not found)')
|
||||
|
|
|
@ -245,7 +245,7 @@ pub fn (v &Builder) get_user_files() []string {
|
|||
if v.pref.is_prof {
|
||||
user_files << os.join_path(preludes_path, 'profiled_program.v')
|
||||
}
|
||||
is_test := dir.ends_with('_test.v')
|
||||
is_test := dir.ends_with('_test.v') || dir.ends_with('_test.vv')
|
||||
mut is_internal_module_test := false
|
||||
if is_test {
|
||||
tcontent := os.read_file(dir) or {
|
||||
|
|
|
@ -5392,7 +5392,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
|||
// TODO c.pref.is_vet
|
||||
if node.language == .v && !node.is_method && node.params.len == 0
|
||||
&& node.name.after('.').starts_with('test_') {
|
||||
if !c.file.path.ends_with('_test.v') {
|
||||
if !c.pref.is_test {
|
||||
// simple heuristic
|
||||
for st in node.stmts {
|
||||
if st is ast.AssertStmt {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
vlib/v/checker/tests/a_test_file_with_0_test_fns_test.vv:1:1: error: a _test.v file should have *at least* one `test_` function
|
||||
1 | fn abc() {}
|
||||
| ^
|
||||
Details: The name of a test function in V, should start with `test_`.
|
||||
The test function should take 0 parameters, and no return type. Example:
|
||||
fn test_xyz(){ assert 2 + 2 == 4 }
|
|
@ -0,0 +1 @@
|
|||
fn abc() {}
|
|
@ -215,10 +215,8 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
|||
}
|
||||
// println('\ncgen "$g.file.path" nr_stmts=$file.stmts.len')
|
||||
// building_v := true && (g.file.path.contains('/vlib/') || g.file.path.contains('cmd/v'))
|
||||
is_test := g.file.path.ends_with('.vv') || g.file.path.ends_with('_test.v')
|
||||
if g.file.path.ends_with('_test.v') {
|
||||
g.is_test = is_test
|
||||
}
|
||||
is_test := g.file.path.ends_with('_test.vv') || g.file.path.ends_with('_test.v')
|
||||
g.is_test = is_test
|
||||
if g.file.path == '' || !g.pref.autofree {
|
||||
// cgen test or building V
|
||||
// println('autofree=false')
|
||||
|
|
|
@ -11,10 +11,11 @@ import v.depgraph
|
|||
const (
|
||||
// https://ecma-international.org/ecma-262/#sec-reserved-words
|
||||
js_reserved = ['await', 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger',
|
||||
'default', 'delete', 'do', 'else', 'enum', 'export', 'extends', 'finally', 'for', 'function', 'if',
|
||||
'implements', 'import', 'in', 'instanceof', 'interface', 'let', 'new', 'package', 'private', 'protected',
|
||||
'public', 'return', 'static', 'super', 'switch', 'this', 'throw', 'try', 'typeof', 'var', 'void',
|
||||
'while', 'with', 'yield', 'Number', 'String', 'Boolean', 'Array', 'Map']
|
||||
'default', 'delete', 'do', 'else', 'enum', 'export', 'extends', 'finally', 'for', 'function',
|
||||
'if', 'implements', 'import', 'in', 'instanceof', 'interface', 'let', 'new', 'package',
|
||||
'private', 'protected', 'public', 'return', 'static', 'super', 'switch', 'this', 'throw',
|
||||
'try', 'typeof', 'var', 'void', 'while', 'with', 'yield', 'Number', 'String', 'Boolean',
|
||||
'Array', 'Map']
|
||||
// used to generate type structs
|
||||
v_types = ['i8', 'i16', 'int', 'i64', 'byte', 'u16', 'u32', 'u64', 'f32', 'f64', 'int_literal',
|
||||
'float_literal', 'size_t', 'bool', 'string', 'map', 'array']
|
||||
|
@ -23,7 +24,7 @@ const (
|
|||
)
|
||||
|
||||
struct Namespace {
|
||||
name string
|
||||
name string
|
||||
mut:
|
||||
out strings.Builder = strings.new_builder(128)
|
||||
pub_vars []string
|
||||
|
@ -33,8 +34,8 @@ mut:
|
|||
}
|
||||
|
||||
struct JsGen {
|
||||
table &table.Table
|
||||
pref &pref.Preferences
|
||||
table &table.Table
|
||||
pref &pref.Preferences
|
||||
mut:
|
||||
definitions strings.Builder
|
||||
ns &Namespace
|
||||
|
@ -53,7 +54,7 @@ mut:
|
|||
stmt_start_pos int
|
||||
defer_stmts []ast.DeferStmt
|
||||
fn_decl &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0
|
||||
str_types []string // types that need automatic str() generation
|
||||
str_types []string // types that need automatic str() generation
|
||||
method_fn_decls map[string][]ast.FnDecl
|
||||
builtin_fns []string // Functions defined in `builtin`
|
||||
empty_line bool
|
||||
|
@ -81,14 +82,14 @@ pub fn gen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
|||
for file in files {
|
||||
g.file = file
|
||||
g.enter_namespace(g.file.mod.name)
|
||||
g.is_test = g.file.path.ends_with('_test.v')
|
||||
g.is_test = g.file.path.ends_with('_test.v') || g.file.path.ends_with('_test.vv')
|
||||
g.find_class_methods(file.stmts)
|
||||
g.escape_namespace()
|
||||
}
|
||||
for file in files {
|
||||
g.file = file
|
||||
g.enter_namespace(g.file.mod.name)
|
||||
g.is_test = g.file.path.ends_with('_test.v')
|
||||
g.is_test = g.file.path.ends_with('_test.v') || g.file.path.ends_with('_test.vv')
|
||||
// store imports
|
||||
mut imports := []string{}
|
||||
for imp in g.file.imports {
|
||||
|
@ -132,7 +133,7 @@ pub fn gen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
|||
out += '\n\treturn {'
|
||||
// export builtin types
|
||||
if name == 'builtin' {
|
||||
for typ in v_types {
|
||||
for typ in js.v_types {
|
||||
out += '\n\t\t$typ,'
|
||||
}
|
||||
}
|
||||
|
@ -158,14 +159,14 @@ pub fn gen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
|||
if name == 'builtin' {
|
||||
out += '// builtin type casts\n'
|
||||
out += 'const ['
|
||||
for i, typ in v_types {
|
||||
for i, typ in js.v_types {
|
||||
if i > 0 {
|
||||
out += ', '
|
||||
}
|
||||
out += '$typ'
|
||||
}
|
||||
out += '] = ['
|
||||
for i, typ in v_types {
|
||||
for i, typ in js.v_types {
|
||||
if i > 0 {
|
||||
out += ','
|
||||
}
|
||||
|
@ -245,7 +246,7 @@ fn verror(msg string) {
|
|||
[inline]
|
||||
pub fn (mut g JsGen) gen_indent() {
|
||||
if g.ns.indent > 0 && g.empty_line {
|
||||
g.ns.out.write(tabs[g.ns.indent])
|
||||
g.ns.out.write(js.tabs[g.ns.indent])
|
||||
}
|
||||
g.empty_line = false
|
||||
}
|
||||
|
@ -323,7 +324,7 @@ fn (mut g JsGen) js_name(name_ string) string {
|
|||
mut parts := name.split('.')
|
||||
if !is_js {
|
||||
for i, p in parts {
|
||||
if p in js_reserved {
|
||||
if p in js.js_reserved {
|
||||
parts[i] = 'v_$p'
|
||||
}
|
||||
}
|
||||
|
@ -547,7 +548,7 @@ fn (mut g JsGen) expr(node ast.Expr) {
|
|||
g.gen_string_inter_literal(node)
|
||||
}
|
||||
ast.StringLiteral {
|
||||
text := node.val.replace("\'", "\\'")
|
||||
text := node.val.replace("'", "\\'")
|
||||
if g.file.mod.name == 'builtin' {
|
||||
g.write('new ')
|
||||
}
|
||||
|
@ -988,7 +989,7 @@ fn (mut g JsGen) gen_struct_decl(node ast.StructDecl) {
|
|||
if name.starts_with('JS.') {
|
||||
return
|
||||
}
|
||||
if name in v_types && g.ns.name == 'builtin' {
|
||||
if name in js.v_types && g.ns.name == 'builtin' {
|
||||
return
|
||||
}
|
||||
js_name := g.js_name(name)
|
||||
|
@ -1368,8 +1369,8 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
|||
g.write(')')
|
||||
}
|
||||
} else {
|
||||
both_are_int := int(it.left_type) in table.integer_type_idxs &&
|
||||
int(it.right_type) in table.integer_type_idxs
|
||||
both_are_int := int(it.left_type) in table.integer_type_idxs
|
||||
&& int(it.right_type) in table.integer_type_idxs
|
||||
is_arithmetic := it.op in [token.Kind.plus, .minus, .mul, .div, .mod]
|
||||
if is_arithmetic {
|
||||
g.write('${g.typ(g.greater_typ(it.left_type, it.right_type))}(')
|
||||
|
@ -1404,9 +1405,8 @@ fn (mut g JsGen) greater_typ(left table.Type, right table.Type) table.Type {
|
|||
if table.string_type_idx in lr {
|
||||
return table.Type(table.string_type_idx)
|
||||
}
|
||||
should_float := (l in table.integer_type_idxs &&
|
||||
r in table.float_type_idxs) ||
|
||||
(r in table.integer_type_idxs && l in table.float_type_idxs)
|
||||
should_float := (l in table.integer_type_idxs && r in table.float_type_idxs)
|
||||
|| (r in table.integer_type_idxs && l in table.float_type_idxs)
|
||||
if should_float {
|
||||
if table.f64_type_idx in lr {
|
||||
return table.Type(table.f64_type_idx)
|
||||
|
@ -1559,12 +1559,11 @@ fn (mut g JsGen) gen_typeof_expr(it ast.TypeOf) {
|
|||
}
|
||||
|
||||
fn (mut g JsGen) gen_type_cast_expr(it ast.CastExpr) {
|
||||
is_literal := ((it.expr is ast.IntegerLiteral &&
|
||||
it.typ in table.integer_type_idxs) ||
|
||||
(it.expr is ast.FloatLiteral && it.typ in table.float_type_idxs))
|
||||
is_literal := ((it.expr is ast.IntegerLiteral && it.typ in table.integer_type_idxs)
|
||||
|| (it.expr is ast.FloatLiteral && it.typ in table.float_type_idxs))
|
||||
typ := g.typ(it.typ)
|
||||
if !is_literal {
|
||||
if !(typ in v_types) || g.ns.name == 'builtin' {
|
||||
if !(typ in js.v_types) || g.ns.name == 'builtin' {
|
||||
g.write('new ')
|
||||
}
|
||||
g.write('${typ}(')
|
||||
|
|
|
@ -70,7 +70,7 @@ pub fn (mut p Preferences) fill_with_defaults() {
|
|||
}
|
||||
p.find_cc_if_cross_compiling()
|
||||
p.ccompiler_type = cc_from_string(p.ccompiler)
|
||||
p.is_test = p.path.ends_with('_test.v')
|
||||
p.is_test = p.path.ends_with('_test.v') || p.path.ends_with('_test.vv')
|
||||
p.is_vsh = p.path.ends_with('.vsh')
|
||||
p.is_script = p.is_vsh || p.path.ends_with('.v') || p.path.ends_with('.vv')
|
||||
if p.third_party_option == '' {
|
||||
|
|
Loading…
Reference in New Issue