vvet: move to own subdir, prepare richer suggestions (#7989)
parent
7545ed4121
commit
8f315d226b
|
@ -11,7 +11,7 @@ import v.util
|
||||||
// should be compiled (v folder).
|
// should be compiled (v folder).
|
||||||
// To implement that, these folders are initially skipped, then added
|
// To implement that, these folders are initially skipped, then added
|
||||||
// as a whole *after the testing.prepare_test_session call*.
|
// as a whole *after the testing.prepare_test_session call*.
|
||||||
const tools_in_subfolders = ['vdoc']
|
const tools_in_subfolders = ['vdoc', 'vvet']
|
||||||
|
|
||||||
// non_packaged_tools are tools that should not be packaged with
|
// non_packaged_tools are tools that should not be packaged with
|
||||||
// prebuild versions of V, to keep the size smaller.
|
// prebuild versions of V, to keep the size smaller.
|
||||||
|
|
|
@ -20,6 +20,7 @@ const (
|
||||||
vfmt_verify_list = [
|
vfmt_verify_list = [
|
||||||
'cmd/v/v.v',
|
'cmd/v/v.v',
|
||||||
'cmd/tools/vdoc/',
|
'cmd/tools/vdoc/',
|
||||||
|
'cmd/tools/vvet/',
|
||||||
'vlib/arrays/',
|
'vlib/arrays/',
|
||||||
'vlib/benchmark/',
|
'vlib/benchmark/',
|
||||||
'vlib/bitfield/',
|
'vlib/bitfield/',
|
||||||
|
@ -92,7 +93,7 @@ fn tsession(vargs string, tool_source string, tool_cmd string, tool_args string,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn v_test_vetting(vargs string) {
|
fn v_test_vetting(vargs string) {
|
||||||
vet_session := tsession(vargs, 'vvet.v', 'v vet', 'vet', vet_folders, vet_known_failing_exceptions)
|
vet_session := tsession(vargs, 'vvet', 'v vet', 'vet', vet_folders, vet_known_failing_exceptions)
|
||||||
verify_session := tsession(vargs, 'vfmt.v', 'v fmt -verify', 'fmt -verify', vfmt_verify_list,
|
verify_session := tsession(vargs, 'vfmt.v', 'v fmt -verify', 'fmt -verify', vfmt_verify_list,
|
||||||
verify_known_failing_exceptions)
|
verify_known_failing_exceptions)
|
||||||
//
|
//
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
cmd/tools/vvet/tests/array_init_one_val.vv:2: Use `var == value` instead of `var in [value]`
|
||||||
|
NB: You can run `v fmt -w file.v` to fix these automatically
|
|
@ -0,0 +1,2 @@
|
||||||
|
cmd/tools/vvet/tests/indent_with_space.vv:2: Looks like you are using spaces for indentation.
|
||||||
|
NB: You can run `v fmt -w file.v` to fix these automatically
|
|
@ -0,0 +1,2 @@
|
||||||
|
cmd/tools/vvet/tests/parens_space_a.vv:1: Looks like you are adding a space after `(`
|
||||||
|
NB: You can run `v fmt -w file.v` to fix these automatically
|
|
@ -0,0 +1,2 @@
|
||||||
|
cmd/tools/vvet/tests/parens_space_b.vv:1: Looks like you are adding a space before `)`
|
||||||
|
NB: You can run `v fmt -w file.v` to fix these automatically
|
|
@ -6,7 +6,7 @@ fn test_vet() {
|
||||||
vexe := os.getenv('VEXE')
|
vexe := os.getenv('VEXE')
|
||||||
vroot := os.dir(vexe)
|
vroot := os.dir(vexe)
|
||||||
os.chdir(vroot)
|
os.chdir(vroot)
|
||||||
test_dir := 'vlib/v/vet/tests'
|
test_dir := 'cmd/tools/vvet/tests'
|
||||||
tests := get_tests_in_dir(test_dir)
|
tests := get_tests_in_dir(test_dir)
|
||||||
fails := check_path(vexe, test_dir, tests)
|
fails := check_path(vexe, test_dir, tests)
|
||||||
assert fails == 0
|
assert fails == 0
|
|
@ -13,7 +13,7 @@ import os.cmdline
|
||||||
struct VetOptions {
|
struct VetOptions {
|
||||||
is_verbose bool
|
is_verbose bool
|
||||||
mut:
|
mut:
|
||||||
errors []string
|
errors []vet.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (vet_options &VetOptions) vprintln(s string) {
|
fn (vet_options &VetOptions) vprintln(s string) {
|
||||||
|
@ -34,7 +34,8 @@ fn main() {
|
||||||
eprintln('File/folder $path does not exist')
|
eprintln('File/folder $path does not exist')
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if path.ends_with('_test.v') || (path.contains('/tests/') && !path.contains('vlib/v/vet/')) {
|
if path.ends_with('_test.v') ||
|
||||||
|
(path.contains('/tests/') && !path.contains('cmd/tools/vvet/tests/')) {
|
||||||
eprintln('skipping $path')
|
eprintln('skipping $path')
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -56,10 +57,15 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if vet_options.errors.len > 0 {
|
if vet_options.errors.len > 0 {
|
||||||
for err in vet_options.errors {
|
for err in vet_options.errors.filter(it.kind == .error) {
|
||||||
eprintln(err)
|
eprintln('$err.file_path:$err.pos.line_nr: $err.message')
|
||||||
}
|
}
|
||||||
eprintln('NB: You can run `v fmt -w file.v` to fix these automatically')
|
eprintln('NB: You can run `v fmt -w file.v` to fix these automatically')
|
||||||
|
/*
|
||||||
|
for err in vet_options.errors.filter(it.kind == .warning) {
|
||||||
|
eprintln('$err.file_path:$err.pos.line_nr: err.message')
|
||||||
|
}
|
||||||
|
*/
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,6 +76,6 @@ fn (mut vet_options VetOptions) vet_file(path string) {
|
||||||
table := table.new_table()
|
table := table.new_table()
|
||||||
vet_options.vprintln("vetting file '$path'...")
|
vet_options.vprintln("vetting file '$path'...")
|
||||||
file_ast, errors := parser.parse_vet_file(path, table, prefs)
|
file_ast, errors := parser.parse_vet_file(path, table, prefs)
|
||||||
|
// Transfer errors from scanner and parser
|
||||||
vet_options.errors << errors
|
vet_options.errors << errors
|
||||||
vet.vet(file_ast, table, true)
|
|
||||||
}
|
}
|
|
@ -9,6 +9,7 @@ import v.token
|
||||||
import v.table
|
import v.table
|
||||||
import v.pref
|
import v.pref
|
||||||
import v.util
|
import v.util
|
||||||
|
import v.vet
|
||||||
import v.errors
|
import v.errors
|
||||||
import os
|
import os
|
||||||
import runtime
|
import runtime
|
||||||
|
@ -66,7 +67,7 @@ mut:
|
||||||
expecting_type bool // `is Type`, expecting type
|
expecting_type bool // `is Type`, expecting type
|
||||||
errors []errors.Error
|
errors []errors.Error
|
||||||
warnings []errors.Warning
|
warnings []errors.Warning
|
||||||
vet_errors []string
|
vet_errors []vet.Error
|
||||||
cur_fn_name string
|
cur_fn_name string
|
||||||
in_generic_params bool // indicates if parsing between `<` and `>` of a method/function
|
in_generic_params bool // indicates if parsing between `<` and `>` of a method/function
|
||||||
name_error bool // indicates if the token is not a name or the name is on another line
|
name_error bool // indicates if the token is not a name or the name is on another line
|
||||||
|
@ -160,7 +161,7 @@ pub fn parse_file(path string, table &table.Table, comments_mode scanner.Comment
|
||||||
return p.parse()
|
return p.parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_vet_file(path string, table_ &table.Table, pref &pref.Preferences) (ast.File, []string) {
|
pub fn parse_vet_file(path string, table_ &table.Table, pref &pref.Preferences) (ast.File, []vet.Error) {
|
||||||
global_scope := &ast.Scope{
|
global_scope := &ast.Scope{
|
||||||
parent: 0
|
parent: 0
|
||||||
}
|
}
|
||||||
|
@ -182,7 +183,8 @@ pub fn parse_vet_file(path string, table_ &table.Table, pref &pref.Preferences)
|
||||||
source_lines := os.read_lines(path) or { []string{} }
|
source_lines := os.read_lines(path) or { []string{} }
|
||||||
for lnumber, line in source_lines {
|
for lnumber, line in source_lines {
|
||||||
if line.starts_with(' ') {
|
if line.starts_with(' ') {
|
||||||
p.vet_error('Looks like you are using spaces for indentation.', lnumber)
|
p.vet_error('Looks like you are using spaces for indentation.', lnumber,
|
||||||
|
.vfmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -953,8 +955,17 @@ pub fn (mut p Parser) warn_with_pos(s string, pos token.Position) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut p Parser) vet_error(s string, line int) {
|
pub fn (mut p Parser) vet_error(msg string, line int, fix vet.FixKind) {
|
||||||
p.vet_errors << '$p.scanner.file_path:${line + 1}: $s'
|
pos := token.Position{
|
||||||
|
line_nr: line + 1
|
||||||
|
}
|
||||||
|
p.vet_errors << vet.Error{
|
||||||
|
message: msg
|
||||||
|
file_path: p.scanner.file_path
|
||||||
|
pos: pos
|
||||||
|
kind: .error
|
||||||
|
fix: fix
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt {
|
fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
module parser
|
module parser
|
||||||
|
|
||||||
import v.ast
|
import v.ast
|
||||||
|
import v.vet
|
||||||
import v.table
|
import v.table
|
||||||
import v.token
|
import v.token
|
||||||
|
|
||||||
|
@ -381,7 +382,7 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
|
||||||
p.expecting_type = prev_expecting_type
|
p.expecting_type = prev_expecting_type
|
||||||
if p.pref.is_vet && op in [.key_in, .not_in] && right is ast.ArrayInit && (right as ast.ArrayInit).exprs.len ==
|
if p.pref.is_vet && op in [.key_in, .not_in] && right is ast.ArrayInit && (right as ast.ArrayInit).exprs.len ==
|
||||||
1 {
|
1 {
|
||||||
p.vet_error('Use `var == value` instead of `var in [value]`', pos.line_nr)
|
p.vet_error('Use `var == value` instead of `var in [value]`', pos.line_nr, vet.FixKind.vfmt)
|
||||||
}
|
}
|
||||||
mut or_stmts := []ast.Stmt{}
|
mut or_stmts := []ast.Stmt{}
|
||||||
mut or_kind := ast.OrKind.absent
|
mut or_kind := ast.OrKind.absent
|
||||||
|
|
|
@ -7,6 +7,7 @@ import os
|
||||||
import v.token
|
import v.token
|
||||||
import v.pref
|
import v.pref
|
||||||
import v.util
|
import v.util
|
||||||
|
import v.vet
|
||||||
import v.errors
|
import v.errors
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -46,9 +47,9 @@ pub mut:
|
||||||
tidx int
|
tidx int
|
||||||
eofs int
|
eofs int
|
||||||
pref &pref.Preferences
|
pref &pref.Preferences
|
||||||
vet_errors []string
|
|
||||||
errors []errors.Error
|
errors []errors.Error
|
||||||
warnings []errors.Warning
|
warnings []errors.Warning
|
||||||
|
vet_errors []vet.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -690,14 +691,14 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
`(` {
|
`(` {
|
||||||
// TODO `$if vet {` for performance
|
// TODO `$if vet {` for performance
|
||||||
if s.pref.is_vet && s.text[s.pos + 1] == ` ` {
|
if s.pref.is_vet && s.text[s.pos + 1] == ` ` {
|
||||||
s.vet_error('Looks like you are adding a space after `(`')
|
s.vet_error('Looks like you are adding a space after `(`', .vfmt)
|
||||||
}
|
}
|
||||||
return s.new_token(.lpar, '', 1)
|
return s.new_token(.lpar, '', 1)
|
||||||
}
|
}
|
||||||
`)` {
|
`)` {
|
||||||
// TODO `$if vet {` for performance
|
// TODO `$if vet {` for performance
|
||||||
if s.pref.is_vet && s.text[s.pos - 1] == ` ` {
|
if s.pref.is_vet && s.text[s.pos - 1] == ` ` {
|
||||||
s.vet_error('Looks like you are adding a space before `)`')
|
s.vet_error('Looks like you are adding a space before `)`', .vfmt)
|
||||||
}
|
}
|
||||||
return s.new_token(.rpar, '', 1)
|
return s.new_token(.rpar, '', 1)
|
||||||
}
|
}
|
||||||
|
@ -1259,8 +1260,17 @@ pub fn (mut s Scanner) error(msg string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut s Scanner) vet_error(msg string) {
|
fn (mut s Scanner) vet_error(msg string, fix vet.FixKind) {
|
||||||
s.vet_errors << '$s.file_path:$s.line_nr: $msg'
|
ve := vet.Error{
|
||||||
|
message: msg
|
||||||
|
file_path: s.file_path
|
||||||
|
pos: token.Position{
|
||||||
|
line_nr: s.line_nr
|
||||||
|
}
|
||||||
|
kind: .error
|
||||||
|
fix: fix
|
||||||
|
}
|
||||||
|
s.vet_errors << ve
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verror(s string) {
|
pub fn verror(s string) {
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
vlib/v/vet/tests/array_init_one_val.vv:2: Use `var == value` instead of `var in [value]`
|
|
||||||
NB: You can run `v fmt -w file.v` to fix these automatically
|
|
|
@ -1,2 +0,0 @@
|
||||||
vlib/v/vet/tests/indent_with_space.vv:2: Looks like you are using spaces for indentation.
|
|
||||||
NB: You can run `v fmt -w file.v` to fix these automatically
|
|
|
@ -1,2 +0,0 @@
|
||||||
vlib/v/vet/tests/parens_space_a.vv:1: Looks like you are adding a space after `(`
|
|
||||||
NB: You can run `v fmt -w file.v` to fix these automatically
|
|
|
@ -1,2 +0,0 @@
|
||||||
vlib/v/vet/tests/parens_space_b.vv:1: Looks like you are adding a space before `)`
|
|
||||||
NB: You can run `v fmt -w file.v` to fix these automatically
|
|
|
@ -2,8 +2,25 @@
|
||||||
// Use of this source code is governed by an MIT license that can be found in the LICENSE file.
|
// Use of this source code is governed by an MIT license that can be found in the LICENSE file.
|
||||||
module vet
|
module vet
|
||||||
|
|
||||||
import v.ast
|
import v.token
|
||||||
import v.table
|
|
||||||
|
|
||||||
pub fn vet(file ast.File, table &table.Table, is_debug bool) {
|
pub enum ErrorKind {
|
||||||
|
error
|
||||||
|
warning
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum FixKind {
|
||||||
|
unknown
|
||||||
|
vfmt
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Error {
|
||||||
|
pub:
|
||||||
|
// General message
|
||||||
|
message string [required]
|
||||||
|
details string // Details about how to resolve or fix the situation
|
||||||
|
file_path string // file where the error have origin
|
||||||
|
pos token.Position // position in the file
|
||||||
|
kind ErrorKind [required]
|
||||||
|
fix FixKind [required]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue