checker: remove duplicate const error; fmt: force full path to consts

pull/8265/head
Alexander Medvednikov 2021-01-24 10:01:10 +01:00
parent 69e6ba7a64
commit 8bcb6c10cc
4 changed files with 85 additions and 61 deletions

View File

@ -55,7 +55,7 @@ fn parse_iso8601_date(s string) ?(int, int, int) {
year, month, day, dummy := 0, 0, 0, byte(0) year, month, day, dummy := 0, 0, 0, byte(0)
count := unsafe { C.sscanf(charptr(s.str), '%4d-%2d-%2d%c', &year, &month, &day, &dummy) } count := unsafe { C.sscanf(charptr(s.str), '%4d-%2d-%2d%c', &year, &month, &day, &dummy) }
if count != 3 { if count != 3 {
return err_invalid_8601 return time.err_invalid_8601
} }
return year, month, day return year, month, day
} }
@ -81,12 +81,12 @@ fn parse_iso8601_time(s string) ?(int, int, int, int, i64, bool) {
count++ // Increment count because skipped microsecond count++ // Increment count because skipped microsecond
} }
if count < 4 { if count < 4 {
return err_invalid_8601 return time.err_invalid_8601
} }
is_local_time := plus_min_z == `a` && count == 4 is_local_time := plus_min_z == `a` && count == 4
is_utc := plus_min_z == `Z` && count == 5 is_utc := plus_min_z == `Z` && count == 5
if !(count == 7 || is_local_time || is_utc) { if !(count == 7 || is_local_time || is_utc) {
return err_invalid_8601 return time.err_invalid_8601
} }
if plus_min_z != `+` && plus_min_z != `-` && !is_utc && !is_local_time { if plus_min_z != `+` && plus_min_z != `-` && !is_utc && !is_local_time {
return error('Invalid 8601 format, expected `Z` or `+` or `-` as time separator') return error('Invalid 8601 format, expected `Z` or `+` or `-` as time separator')
@ -113,7 +113,7 @@ pub fn parse_iso8601(s string) ?Time {
t_i := s.index('T') or { -1 } t_i := s.index('T') or { -1 }
parts := if t_i != -1 { [s[..t_i], s[t_i + 1..]] } else { s.split(' ') } parts := if t_i != -1 { [s[..t_i], s[t_i + 1..]] } else { s.split(' ') }
if !(parts.len == 1 || parts.len == 2) { if !(parts.len == 1 || parts.len == 2) {
return err_invalid_8601 return time.err_invalid_8601
} }
year, month, day := parse_iso8601_date(parts[0]) ? year, month, day := parse_iso8601_date(parts[0]) ?
mut hour, mut minute, mut second, mut microsecond, mut unix_offset, mut is_local_time := 0, 0, 0, 0, i64(0), true mut hour, mut minute, mut second, mut microsecond, mut unix_offset, mut is_local_time := 0, 0, 0, 0, i64(0), true

View File

@ -13,9 +13,9 @@ const (
// but otherwise can be changed at will. // but otherwise can be changed at will.
absolute_zero_year = i64(-292277022399) // as i64 absolute_zero_year = i64(-292277022399) // as i64
seconds_per_minute = 60 seconds_per_minute = 60
seconds_per_hour = 60 * seconds_per_minute seconds_per_hour = 60 * time.seconds_per_minute
seconds_per_day = 24 * seconds_per_hour seconds_per_day = 24 * time.seconds_per_hour
seconds_per_week = 7 * seconds_per_day seconds_per_week = 7 * time.seconds_per_day
days_per_400_years = 365 * 400 + 97 days_per_400_years = 365 * 400 + 97
days_per_100_years = 365 * 100 + 24 days_per_100_years = 365 * 100 + 24
days_per_4_years = 365 * 4 + 1 days_per_4_years = 365 * 4 + 1
@ -141,7 +141,7 @@ pub fn (t Time) smonth() string {
return '---' return '---'
} }
i := t.month - 1 i := t.month - 1
return months_string[i * 3..(i + 1) * 3] return time.months_string[i * 3..(i + 1) * 3]
} }
// new_time returns a time struct with calculated Unix time. // new_time returns a time struct with calculated Unix time.
@ -186,12 +186,12 @@ pub fn (t Time) add(d Duration) Time {
// add_seconds returns a new time struct with an added number of seconds. // add_seconds returns a new time struct with an added number of seconds.
pub fn (t Time) add_seconds(seconds int) Time { pub fn (t Time) add_seconds(seconds int) Time {
return t.add(seconds * second) return t.add(seconds * time.second)
} }
// add_days returns a new time struct with an added number of days. // add_days returns a new time struct with an added number of days.
pub fn (t Time) add_days(days int) Time { pub fn (t Time) add_days(days int) Time {
return t.add(days * 24 * hour) return t.add(days * 24 * time.hour)
} }
// since returns a number of seconds elapsed since a given time. // since returns a number of seconds elapsed since a given time.
@ -300,13 +300,13 @@ pub fn (t Time) day_of_week() int {
// weekday_str returns the current day as a string. // weekday_str returns the current day as a string.
pub fn (t Time) weekday_str() string { pub fn (t Time) weekday_str() string {
i := t.day_of_week() - 1 i := t.day_of_week() - 1
return days_string[i * 3..(i + 1) * 3] return time.days_string[i * 3..(i + 1) * 3]
} }
// weekday_str returns the current day as a string. // weekday_str returns the current day as a string.
pub fn (t Time) long_weekday_str() string { pub fn (t Time) long_weekday_str() string {
i := t.day_of_week() - 1 i := t.day_of_week() - 1
return long_days[i] return time.long_days[i]
} }
// ticks returns a number of milliseconds elapsed since system start. // ticks returns a number of milliseconds elapsed since system start.
@ -362,7 +362,7 @@ pub fn days_in_month(month int, year int) ?int {
return error('Invalid month: $month') return error('Invalid month: $month')
} }
extra := if month == 2 && is_leap_year(year) { 1 } else { 0 } extra := if month == 2 && is_leap_year(year) { 1 } else { 0 }
res := month_days[month - 1] + extra res := time.month_days[month - 1] + extra
return res return res
} }
@ -382,7 +382,7 @@ fn convert_ctime(t C.tm, microsecond int) Time {
hour: t.tm_hour hour: t.tm_hour
minute: t.tm_min minute: t.tm_min
second: t.tm_sec second: t.tm_sec
microsecond: microsecond microsecond: time.microsecond
unix: u64(make_unix_time(t)) unix: u64(make_unix_time(t))
} }
} }
@ -392,11 +392,11 @@ pub type Duration = i64
pub const ( pub const (
nanosecond = Duration(1) nanosecond = Duration(1)
microsecond = Duration(1000 * nanosecond) microsecond = Duration(1000 * time.nanosecond)
millisecond = Duration(1000 * microsecond) millisecond = Duration(1000 * time.microsecond)
second = Duration(1000 * millisecond) second = Duration(1000 * time.millisecond)
minute = Duration(60 * second) minute = Duration(60 * time.second)
hour = Duration(60 * minute) hour = Duration(60 * time.minute)
infinite = Duration(-1) infinite = Duration(-1)
) )
@ -419,22 +419,22 @@ pub fn (d Duration) milliseconds() i64 {
// consider all of them in sub-one intervals // consider all of them in sub-one intervals
// seconds returns the duration as a floating point number of seconds. // seconds returns the duration as a floating point number of seconds.
pub fn (d Duration) seconds() f64 { pub fn (d Duration) seconds() f64 {
sec := d / second sec := d / time.second
nsec := d % second nsec := d % time.second
return f64(sec) + f64(nsec) / 1e9 return f64(sec) + f64(nsec) / 1e9
} }
// minutes returns the duration as a floating point number of minutes. // minutes returns the duration as a floating point number of minutes.
pub fn (d Duration) minutes() f64 { pub fn (d Duration) minutes() f64 {
min := d / minute min := d / time.minute
nsec := d % minute nsec := d % time.minute
return f64(min) + f64(nsec) / (60 * 1e9) return f64(min) + f64(nsec) / (60 * 1e9)
} }
// hours returns the duration as a floating point number of hours. // hours returns the duration as a floating point number of hours.
pub fn (d Duration) hours() f64 { pub fn (d Duration) hours() f64 {
hr := d / hour hr := d / time.hour
nsec := d % hour nsec := d % time.hour
return f64(hr) + f64(nsec) / (60 * 60 * 1e9) return f64(hr) + f64(nsec) / (60 * 60 * 1e9)
} }

View File

@ -215,7 +215,7 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
match stmt { match stmt {
ast.ConstDecl { ast.ConstDecl {
if stmt.is_pub { if stmt.is_pub {
c.warn('const $no_pub_in_main_warning', stmt.pos) c.warn('const $checker.no_pub_in_main_warning', stmt.pos)
} }
} }
/* /*
@ -228,7 +228,7 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
*/ */
ast.EnumDecl { ast.EnumDecl {
if stmt.is_pub { if stmt.is_pub {
c.warn('enum `$stmt.name` $no_pub_in_main_warning', stmt.pos) c.warn('enum `$stmt.name` $checker.no_pub_in_main_warning', stmt.pos)
} }
} }
ast.FnDecl { ast.FnDecl {
@ -257,7 +257,8 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
} }
} }
if stmt.is_pub && !stmt.is_method { if stmt.is_pub && !stmt.is_method {
c.warn('function `$stmt.name` $no_pub_in_main_warning', stmt.pos) c.warn('function `$stmt.name` $checker.no_pub_in_main_warning',
stmt.pos)
} }
} }
if stmt.return_type != table.void_type { if stmt.return_type != table.void_type {
@ -272,21 +273,24 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
} }
ast.StructDecl { ast.StructDecl {
if stmt.is_pub { if stmt.is_pub {
c.warn('struct `$stmt.name` $no_pub_in_main_warning', stmt.pos) c.warn('struct `$stmt.name` $checker.no_pub_in_main_warning', stmt.pos)
} }
} }
ast.TypeDecl { ast.TypeDecl {
if stmt is ast.AliasTypeDecl { if stmt is ast.AliasTypeDecl {
if stmt.is_pub { if stmt.is_pub {
c.warn('type alias `$stmt.name` $no_pub_in_main_warning', stmt.pos) c.warn('type alias `$stmt.name` $checker.no_pub_in_main_warning',
stmt.pos)
} }
} else if stmt is ast.SumTypeDecl { } else if stmt is ast.SumTypeDecl {
if stmt.is_pub { if stmt.is_pub {
c.warn('sum type `$stmt.name` $no_pub_in_main_warning', stmt.pos) c.warn('sum type `$stmt.name` $checker.no_pub_in_main_warning',
stmt.pos)
} }
} else if stmt is ast.FnTypeDecl { } else if stmt is ast.FnTypeDecl {
if stmt.is_pub { if stmt.is_pub {
c.warn('type alias `$stmt.name` $no_pub_in_main_warning', stmt.pos) c.warn('type alias `$stmt.name` $checker.no_pub_in_main_warning',
stmt.pos)
} }
} }
} }
@ -1084,7 +1088,7 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) (string, token.Position) {
pos = expr.pos pos = expr.pos
} }
} }
} else if expr.name in c.const_names { } else if expr.obj is ast.ConstField && expr.name in c.const_names {
c.error('cannot modify constant `$expr.name`', expr.pos) c.error('cannot modify constant `$expr.name`', expr.pos)
} }
} }
@ -1327,7 +1331,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
} }
// TODO: remove this for actual methods, use only for compiler magic // TODO: remove this for actual methods, use only for compiler magic
// FIXME: Argument count != 1 will break these // FIXME: Argument count != 1 will break these
if left_type_sym.kind == .array && method_name in array_builtin_methods { if left_type_sym.kind == .array && method_name in checker.array_builtin_methods {
mut elem_typ := table.void_type mut elem_typ := table.void_type
is_filter_map := method_name in ['filter', 'map'] is_filter_map := method_name in ['filter', 'map']
is_sort := method_name == 'sort' is_sort := method_name == 'sort'
@ -2348,7 +2352,7 @@ pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) {
match field.expr { match field.expr {
ast.IntegerLiteral { ast.IntegerLiteral {
val := field.expr.val.i64() val := field.expr.val.i64()
if val < int_min || val > int_max { if val < checker.int_min || val > checker.int_max {
c.error('enum value `$val` overflows int', field.expr.pos) c.error('enum value `$val` overflows int', field.expr.pos)
} else if !decl.is_multi_allowed && i64(val) in seen { } else if !decl.is_multi_allowed && i64(val) in seen {
c.error('enum value `$val` already exists', field.expr.pos) c.error('enum value `$val` already exists', field.expr.pos)
@ -2372,7 +2376,7 @@ pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) {
} else { } else {
if seen.len > 0 { if seen.len > 0 {
last := seen[seen.len - 1] last := seen[seen.len - 1]
if last == int_max { if last == checker.int_max {
c.error('enum value overflows', field.pos) c.error('enum value overflows', field.pos)
} }
seen << last + 1 seen << last + 1
@ -2453,7 +2457,8 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
mut is_large := false mut is_large := false
if expr.val.len > 8 { if expr.val.len > 8 {
val := expr.val.i64() val := expr.val.i64()
if (!negative && val > int_max) || (negative && -val < int_min) { if (!negative && val > checker.int_max)
|| (negative && -val < checker.int_min) {
is_large = true is_large = true
} }
} }
@ -2511,10 +2516,12 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
} }
*/ */
} }
if is_decl { if false && is_decl {
full_name := '${left.mod}.$left.name' full_name := '${left.mod}.$left.name'
if full_name in c.const_names { if obj := c.file.global_scope.find(full_name) {
c.error('duplicate of a const name `$left.name`', left.pos) if obj is ast.ConstField {
c.warn('duplicate of a const name `$full_name', left.pos)
}
} }
} }
} }
@ -4183,11 +4190,11 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym table.TypeS
mut err_details := 'match must be exhaustive' mut err_details := 'match must be exhaustive'
if unhandled.len > 0 { if unhandled.len > 0 {
err_details += ' (add match branches for: ' err_details += ' (add match branches for: '
if unhandled.len < match_exhaustive_cutoff_limit { if unhandled.len < checker.match_exhaustive_cutoff_limit {
err_details += unhandled.join(', ') err_details += unhandled.join(', ')
} else { } else {
remaining := unhandled.len - match_exhaustive_cutoff_limit remaining := unhandled.len - checker.match_exhaustive_cutoff_limit
err_details += unhandled[0..match_exhaustive_cutoff_limit].join(', ') err_details += unhandled[0..checker.match_exhaustive_cutoff_limit].join(', ')
err_details += ', and $remaining others ...' err_details += ', and $remaining others ...'
} }
err_details += ' or `else {}` at the end)' err_details += ' or `else {}` at the end)'
@ -4684,13 +4691,13 @@ fn (mut c Checker) comp_if_branch(cond ast.Expr, pos token.Position) bool {
} }
} }
ast.Ident { ast.Ident {
if cond.name in valid_comp_if_os { if cond.name in checker.valid_comp_if_os {
return cond.name != c.pref.os.str().to_lower() // TODO hack return cond.name != c.pref.os.str().to_lower() // TODO hack
} else if cond.name in valid_comp_if_compilers { } else if cond.name in checker.valid_comp_if_compilers {
return pref.cc_from_string(cond.name) != c.pref.ccompiler_type return pref.cc_from_string(cond.name) != c.pref.ccompiler_type
} else if cond.name in valid_comp_if_platforms { } else if cond.name in checker.valid_comp_if_platforms {
return false // TODO return false // TODO
} else if cond.name in valid_comp_if_other { } else if cond.name in checker.valid_comp_if_other {
// TODO: This should probably be moved // TODO: This should probably be moved
match cond.name { match cond.name {
'js' { return c.pref.backend != .js } 'js' { return c.pref.backend != .js }

View File

@ -107,8 +107,8 @@ pub fn (mut f Fmt) writeln(s string) {
} }
fn (mut f Fmt) write_indent() { fn (mut f Fmt) write_indent() {
if f.indent < tabs.len { if f.indent < fmt.tabs.len {
f.out.write(tabs[f.indent]) f.out.write(fmt.tabs[f.indent])
} else { } else {
// too many indents, do it the slow way: // too many indents, do it the slow way:
for _ in 0 .. f.indent { for _ in 0 .. f.indent {
@ -122,7 +122,7 @@ pub fn (mut f Fmt) wrap_long_line(penalty_idx int, add_indent bool) bool {
if f.buffering { if f.buffering {
return false return false
} }
if f.line_len <= max_len[penalty_idx] { if f.line_len <= fmt.max_len[penalty_idx] {
return false return false
} }
if f.out.buf[f.out.buf.len - 1] == ` ` { if f.out.buf[f.out.buf.len - 1] == ` ` {
@ -556,7 +556,7 @@ fn (mut list []CommentAndExprAlignInfo) add_info(attrs_len int, type_len int, li
return return
} }
d_len := abs(list[i].max_attrs_len - attrs_len) + abs(list[i].max_type_len - type_len) d_len := abs(list[i].max_attrs_len - attrs_len) + abs(list[i].max_type_len - type_len)
if !(d_len < threshold_to_align_struct) { if !(d_len < fmt.threshold_to_align_struct) {
list.add_new_info(attrs_len, type_len, line) list.add_new_info(attrs_len, type_len, line)
return return
} }
@ -980,7 +980,7 @@ pub fn (mut f Fmt) or_expr(or_block ast.OrExpr) {
// so, since this'll all be on one line, trim any possible whitespace // so, since this'll all be on one line, trim any possible whitespace
str := f.stmt_str(or_block.stmts[0]).trim_space() str := f.stmt_str(or_block.stmts[0]).trim_space()
single_line := ' or { $str }' single_line := ' or { $str }'
if single_line.len + f.line_len <= max_len.last() { if single_line.len + f.line_len <= fmt.max_len.last() {
f.write(single_line) f.write(single_line)
} else { } else {
// if the line would be too long, make it multiline // if the line would be too long, make it multiline
@ -1144,6 +1144,24 @@ pub fn (mut f Fmt) ident(node ast.Ident) {
} else if node.kind == .blank_ident { } else if node.kind == .blank_ident {
f.write('_') f.write('_')
} else { } else {
// Force usage of full path to const in the same module:
// `println(minute)` => `println(time.minute)`
// This allows using the variable `minute` inside time's functions
// and also makes it clear that a module const is being used
// (since V's conts are no longer ALL_CAP).
if !node.name.contains('.') {
full_name := f.cur_mod + '.' + node.name
if obj := f.file.global_scope.find(full_name) {
if obj is ast.ConstField {
// "v.fmt.foo" => "fmt.foo"
vals := full_name.split('.')
short := vals[vals.len - 2] + '.' + vals[vals.len - 1]
// f.write(f.short_module(full_name))
f.write(short)
return
}
}
}
name := f.short_module(node.name) name := f.short_module(node.name)
// f.write('<$it.name => $name>') // f.write('<$it.name => $name>')
f.write(name) f.write(name)
@ -1321,14 +1339,13 @@ pub fn (mut f Fmt) string_literal(node ast.StringLiteral) {
f.write("'$node.val'") f.write("'$node.val'")
} }
} else { } else {
unescaped_val := node.val.replace('$bs$bs', '\x01').replace_each(["$bs'", "'", '$bs"', unescaped_val := node.val.replace('$fmt.bs$fmt.bs', '\x01').replace_each(["$fmt.bs'", "'",
'"', '$fmt.bs"', '"'])
])
if use_double_quote { if use_double_quote {
s := unescaped_val.replace_each(['\x01', '$bs$bs', '"', '$bs"']) s := unescaped_val.replace_each(['\x01', '$fmt.bs$fmt.bs', '"', '$fmt.bs"'])
f.write('"$s"') f.write('"$s"')
} else { } else {
s := unescaped_val.replace_each(['\x01', '$bs$bs', "'", "$bs'"]) s := unescaped_val.replace_each(['\x01', '$fmt.bs$fmt.bs', "'", "$fmt.bs'"])
f.write("'$s'") f.write("'$s'")
} }
} }
@ -1454,7 +1471,7 @@ pub fn (mut f Fmt) infix_expr(node ast.InfixExpr) {
} }
if !buffering_save && f.buffering { if !buffering_save && f.buffering {
f.buffering = false f.buffering = false
if !f.single_line_if && f.line_len > max_len.last() { if !f.single_line_if && f.line_len > fmt.max_len.last() {
f.wrap_infix(infix_start, start_len) f.wrap_infix(infix_start, start_len)
} }
} }
@ -1506,7 +1523,7 @@ pub fn (mut f Fmt) wrap_infix(start_pos int, start_len int) {
} }
for i, c in conditions { for i, c in conditions {
cnd := c.trim_space() cnd := c.trim_space()
if f.line_len + cnd.len < max_len[penalties[i]] { if f.line_len + cnd.len < fmt.max_len[penalties[i]] {
if i > 0 && (!is_cond_infix || i < conditions.len - 1) { if i > 0 && (!is_cond_infix || i < conditions.len - 1) {
f.write(' ') f.write(' ')
} }
@ -1558,7 +1575,7 @@ pub fn (mut f Fmt) if_expr(it ast.IfExpr) {
} }
} }
// When a single line if is really long, write it again as multiline // When a single line if is really long, write it again as multiline
if single_line && f.line_len > max_len.last() { if single_line && f.line_len > fmt.max_len.last() {
single_line = false single_line = false
f.single_line_if = false f.single_line_if = false
f.out.go_back(f.line_len - if_start) f.out.go_back(f.line_len - if_start)
@ -2021,7 +2038,7 @@ pub fn (mut f Fmt) struct_init(it ast.StructInit) {
f.comments(field.next_comments, inline: false, has_nl: true, level: .keep) f.comments(field.next_comments, inline: false, has_nl: true, level: .keep)
if single_line_fields if single_line_fields
&& (field.comments.len > 0 || field.next_comments.len > 0 || !expr_is_single_line(field.expr) && (field.comments.len > 0 || field.next_comments.len > 0 || !expr_is_single_line(field.expr)
|| f.line_len > max_len.last()) { || f.line_len > fmt.max_len.last()) {
single_line_fields = false single_line_fields = false
f.out.go_back_to(fields_start) f.out.go_back_to(fields_start)
f.line_len = fields_start f.line_len = fields_start