fmt: fix and simplify align of struct fields (#21995)

This commit is contained in:
yuyi 2024-08-06 01:23:39 +08:00 committed by GitHub
parent 576a0abcc7
commit ddb6685d8a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
139 changed files with 553 additions and 519 deletions

View file

@ -155,18 +155,18 @@ jobs:
echo "Build v-analyzer release"
v build.vsh release
- name: Format vlang/v-analyzer
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: |
cd /tmp/v-analyzer
set +e
v fmt -c .
exit_code=$?
if [[ $exit_code -ne 0 && $exit_code -ne 5 ]]; then
# Don't fail if there are only internal errors (exit code 5).
v fmt -diff .
exit 1
fi
# - name: Format vlang/v-analyzer
# if: ${{ !cancelled() && steps.build.outcome == 'success' }}
# run: |
# cd /tmp/v-analyzer
# set +e
# v fmt -c .
# exit_code=$?
# if [[ $exit_code -ne 0 && $exit_code -ne 5 ]]; then
# # Don't fail if there are only internal errors (exit code 5).
# v fmt -diff .
# exit 1
# fi
- name: Build vlang/go2v
if: ${{ !cancelled() && steps.build.outcome == 'success' && matrix.os != 'macos-14' }}

View file

@ -3,47 +3,46 @@
// that can be found in the LICENSE file.
module fmt
import v.mathutil
struct AlignInfo {
mut:
line_nr int
max_len int
max_type_len int
}
@[params]
struct AddInfoConfig {
pub:
use_threshold bool
threshold int = 8
threshold int = 25
}
fn (mut infos []AlignInfo) add_new_info(len int, type_len int, line int) {
fn (mut infos []AlignInfo) add_new_info(len int, line int) {
infos << AlignInfo{
line_nr: line
max_len: len
max_type_len: type_len
}
}
@[direct_array_access]
fn (mut infos []AlignInfo) add_info(len int, type_len int, line int, cfg AddInfoConfig) {
fn (mut infos []AlignInfo) add_info(len int, line int, cfg AddInfoConfig) {
if infos.len == 0 {
infos.add_new_info(len, type_len, line)
infos.add_new_info(len, line)
return
}
i := infos.len - 1
if line - infos[i].line_nr > 1 {
infos.add_new_info(len, type_len, line)
infos.add_new_info(len, line)
return
}
if cfg.use_threshold {
len_diff := mathutil.abs(infos[i].max_len - len) +
mathutil.abs(infos[i].max_type_len - type_len)
len_diff := if infos[i].max_len >= len {
infos[i].max_len - len
} else {
len - infos[i].max_len
}
if len_diff >= cfg.threshold {
infos.add_new_info(len, type_len, line)
infos.add_new_info(len, line)
return
}
}
@ -51,7 +50,4 @@ fn (mut infos []AlignInfo) add_info(len int, type_len int, line int, cfg AddInfo
if len > infos[i].max_len {
infos[i].max_len = len
}
if type_len > infos[i].max_type_len {
infos[i].max_type_len = type_len
}
}

View file

@ -1374,22 +1374,23 @@ pub fn (mut f Fmt) interface_decl(node ast.InterfaceDecl) {
}
}
mut field_aligns := []AlignInfo{}
mut type_aligns := []AlignInfo{}
mut comment_aligns := []AlignInfo{}
mut default_expr_aligns := []AlignInfo{}
mut attr_aligns := []AlignInfo{}
mut field_types := []string{cap: node.fields.len}
// Calculate the alignments first
f.calculate_alignment(node.fields, mut field_aligns, mut comment_aligns, mut default_expr_aligns, mut
field_types)
f.calculate_alignment(node.fields, mut type_aligns, mut comment_aligns, mut default_expr_aligns, mut
attr_aligns, mut field_types)
mut field_align_i := 0
mut type_align_i := 0
// TODO: alignment, comments, etc.
for field in immut_fields {
if field_aligns[field_align_i].line_nr < field.pos.line_nr {
field_align_i++
if type_aligns[type_align_i].line_nr < field.pos.line_nr {
type_align_i++
}
f.interface_field(field, field_aligns[field_align_i])
f.interface_field(field, type_aligns[type_align_i])
}
for method in immut_methods {
f.interface_method(method)
@ -1397,10 +1398,10 @@ pub fn (mut f Fmt) interface_decl(node ast.InterfaceDecl) {
if mut_fields.len + mut_methods.len > 0 {
f.writeln('mut:')
for field in mut_fields {
if field_aligns[field_align_i].line_nr < field.pos.line_nr {
field_align_i++
if type_aligns[type_align_i].line_nr < field.pos.line_nr {
type_align_i++
}
f.interface_field(field, field_aligns[field_align_i])
f.interface_field(field, type_aligns[type_align_i])
}
for method in mut_methods {
f.interface_method(method)
@ -1409,31 +1410,69 @@ pub fn (mut f Fmt) interface_decl(node ast.InterfaceDecl) {
f.writeln('}\n')
}
pub fn (mut f Fmt) calculate_alignment(fields []ast.StructField, mut field_aligns []AlignInfo, mut comment_aligns []AlignInfo,
mut default_expr_aligns []AlignInfo, mut field_types []string) {
enum AlignState {
plain
has_attributes
has_default_expression
has_everything
}
pub fn (mut f Fmt) calculate_alignment(fields []ast.StructField, mut type_aligns []AlignInfo, mut comment_aligns []AlignInfo,
mut default_expr_aligns []AlignInfo, mut attr_aligns []AlignInfo, mut field_types []string) {
// Calculate the alignments first
for i, field in fields {
mut prev_state := AlignState.plain
for field in fields {
ft := f.no_cur_mod(f.table.type_to_str_using_aliases(field.typ, f.mod2alias))
// Handle anon structs recursively
field_types << ft
attrs_len := inline_attrs_len(field.attrs)
end_pos := field.pos.pos + field.pos.len
type_aligns.add_info(field.name.len, field.pos.line_nr)
if field.has_default_expr {
default_expr_aligns.add_info(ft.len, field.pos.line_nr,
use_threshold: true
)
}
if field.attrs.len > 0 {
attr_aligns.add_info(ft.len, field.pos.line_nr, use_threshold: true)
}
for comment in field.comments {
if comment.pos.pos >= end_pos {
if comment.pos.line_nr == field.pos.line_nr {
comment_aligns.add_info(attrs_len, field_types[i].len, comment.pos.line_nr,
if field.attrs.len > 0 {
if prev_state != AlignState.has_attributes {
comment_aligns.add_new_info(attrs_len, comment.pos.line_nr)
} else {
comment_aligns.add_info(attrs_len, comment.pos.line_nr,
use_threshold: true
)
}
prev_state = AlignState.has_attributes
} else if field.has_default_expr {
if prev_state != AlignState.has_default_expression {
comment_aligns.add_new_info(field.default_expr.str().len + 2,
comment.pos.line_nr)
} else {
comment_aligns.add_info(field.default_expr.str().len + 2,
comment.pos.line_nr,
use_threshold: true
)
}
prev_state = AlignState.has_default_expression
} else {
if prev_state != AlignState.has_everything {
comment_aligns.add_new_info(ft.len, comment.pos.line_nr)
} else {
comment_aligns.add_info(ft.len, comment.pos.line_nr,
use_threshold: true
)
}
prev_state = AlignState.has_everything
}
}
continue
}
}
field_aligns.add_info(field.name.len, ft.len, field.pos.line_nr)
if field.has_default_expr {
default_expr_aligns.add_info(attrs_len, field_types[i].len, field.pos.line_nr,
use_threshold: true
)
}
}
}

View file

@ -27,13 +27,14 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl, is_anon bool) {
f.writeln(' {}')
return
}
mut field_aligns := []AlignInfo{}
mut comment_aligns := []AlignInfo{}
mut type_aligns := []AlignInfo{}
mut default_expr_aligns := []AlignInfo{}
mut attr_aligns := []AlignInfo{}
mut comment_aligns := []AlignInfo{}
mut field_types := []string{cap: node.fields.len}
// Calculate the alignments first
f.calculate_alignment(node.fields, mut field_aligns, mut comment_aligns, mut default_expr_aligns, mut
field_types)
f.calculate_alignment(node.fields, mut type_aligns, mut comment_aligns, mut default_expr_aligns, mut
attr_aligns, mut field_types)
f.writeln(' {')
if node.pre_comments.len > 0 {
f.comments_before_field(node.pre_comments)
@ -54,9 +55,10 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl, is_anon bool) {
}
}
// Now handle each field
mut field_align_i := 0
mut type_align_i := 0
mut comment_align_i := 0
mut default_expr_align_i := 0
mut attr_align_i := 0
mut inc_indent := false // for correct indents with multi line default exprs
for i, field in node.fields {
match true {
@ -112,32 +114,23 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl, is_anon bool) {
f.comments_before_field(pre_cmts)
volatile_prefix := if field.is_volatile { 'volatile ' } else { '' }
f.write('\t${volatile_prefix}${field.name} ')
if field_aligns[field_align_i].line_nr < field.pos.line_nr {
field_align_i++
if type_aligns[type_align_i].line_nr < field.pos.line_nr {
type_align_i++
}
field_align := field_aligns[field_align_i]
f.write(strings.repeat(` `, field_align.max_len - field.name.len))
type_align := type_aligns[type_align_i]
f.write(strings.repeat(` `, type_align.max_len - field.name.len))
// Handle anon structs recursively
if !f.write_anon_struct_field_decl(field.typ, field.anon_struct_decl) {
f.write(field_types[i])
}
f.mark_types_import_as_used(field.typ)
attrs_len := inline_attrs_len(field.attrs)
has_attrs := field.attrs.len > 0
// has_at := if has_attrs { field.attrs[0].has_at } else { false }
has_at := true
// TODO: this will get removed in next stage
if has_attrs && !has_at {
f.write(strings.repeat(` `, field_align.max_type_len - field_types[i].len))
f.single_line_attrs(field.attrs, same_line: true)
}
if field.has_default_expr {
if default_expr_aligns[default_expr_align_i].line_nr < field.pos.line_nr {
default_expr_align_i++
}
align := default_expr_aligns[default_expr_align_i]
pad_len := align.max_len - attrs_len + align.max_type_len - field_types[i].len
f.write(strings.repeat(` `, pad_len))
f.write(strings.repeat(` `, align.max_len - field_types[i].len))
f.write(' = ')
if !expr_is_single_line(field.default_expr) {
f.indent++
@ -149,19 +142,26 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl, is_anon bool) {
inc_indent = false
}
}
if has_attrs && has_at {
f.write(strings.repeat(` `, field_align.max_type_len - field_types[i].len))
if field.attrs.len > 0 {
if attr_aligns[attr_align_i].line_nr < field.pos.line_nr {
attr_align_i++
}
align := attr_aligns[attr_align_i]
f.write(strings.repeat(` `, align.max_len - field_types[i].len))
f.single_line_attrs(field.attrs, same_line: true)
}
// Handle comments at the end of the line
if end_cmts.len > 0 {
if !field.has_default_expr {
if comment_aligns[comment_align_i].line_nr < field.pos.line_nr {
comment_align_i++
}
align := comment_aligns[comment_align_i]
pad_len := align.max_len - attrs_len + align.max_type_len - field_types[i].len
f.write(strings.repeat(` `, pad_len))
if field.has_default_expr {
f.write(strings.repeat(` `, align.max_len - field.default_expr.str().len - 2))
} else if field.attrs.len > 0 {
f.write(strings.repeat(` `, align.max_len - attrs_len))
} else {
f.write(strings.repeat(` `, align.max_len - field_types[i].len))
}
f.write(' ')
f.comments(end_cmts, level: .indent)

View file

@ -98,4 +98,3 @@ algorithm and multiple iterations.
See also:
- [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)