fmt: make linebreak smarter by algorithm based on penalty

pull/5432/head
Uwe Krüger 2020-06-19 19:54:26 +02:00 committed by GitHub
parent a609ff4659
commit 0338d4153a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 121 additions and 20 deletions

View File

@ -11,7 +11,8 @@ const (
tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t',
'\t\t\t\t\t\t\t\t'
]
max_len = 90
// when to break a line dependant on penalty
max_len = [0, 30, 85, 100]
)
pub struct Fmt {
@ -439,7 +440,7 @@ pub fn (mut f Fmt) type_decl(node ast.TypeDecl) {
if i < sum_type_names.len - 1 {
f.write(' | ')
}
f.wrap_long_line()
f.wrap_long_line(2, true)
}
// f.write(sum_type_names.join(' | '))
}
@ -629,7 +630,14 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
f.write('$node.op.str()')
} else {
f.write(' $node.op.str() ')
f.wrap_long_line()
mut penalty := 3
if node.left is ast.InfixExpr || node.left is ast.ParExpr {
penalty--
}
if node.right is ast.InfixExpr || node.right is ast.ParExpr {
penalty--
}
f.wrap_long_line(penalty, true)
}
f.expr(node.right)
}
@ -788,14 +796,14 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
}
}
pub fn (mut f Fmt) wrap_long_line() bool {
if f.line_len <= max_len {
pub fn (mut f Fmt) wrap_long_line(penalty int, add_indent bool) bool {
if f.line_len <= max_len[penalty] {
return false
}
if f.out.buf[f.out.buf.len - 1] == ` ` {
f.out.go_back(1)
}
f.write('\n' + tabs[f.indent + 1])
f.write('\n' + tabs[f.indent + if add_indent { 1 } else { 0 }])
f.line_len = 0
return true
}
@ -806,7 +814,7 @@ pub fn (mut f Fmt) call_args(args []ast.CallArg) {
f.write('mut ')
}
if i > 0 {
f.wrap_long_line()
f.wrap_long_line(2, true)
}
f.expr(arg.expr)
if i < args.len - 1 {
@ -1193,15 +1201,24 @@ pub fn (mut f Fmt) array_init(it ast.ArrayInit) {
mut inc_indent := false
mut last_line_nr := it.pos.line_nr // to have the same newlines between array elements
for i, expr in it.exprs {
mut penalty := 3
line_nr := expr.position().line_nr
if last_line_nr < line_nr {
if !inc_indent {
f.indent++
inc_indent = true
}
f.writeln('')
penalty--
}
if i == 0 || it.exprs[i-1] is ast.ArrayInit || it.exprs[i-1] is ast.StructInit ||
it.exprs[i-1] is ast.MapInit || it.exprs[i-1] is ast.CallExpr {
penalty--
}
if expr is ast.ArrayInit || expr is ast.StructInit ||
expr is ast.MapInit || expr is ast.CallExpr {
penalty--
}
is_new_line := f.wrap_long_line(penalty, !inc_indent)
if is_new_line && !inc_indent {
f.indent++
inc_indent = true
}
is_new_line := last_line_nr < line_nr || f.wrap_long_line()
if !is_new_line && i > 0 {
f.write(' ')
}

View File

@ -6,13 +6,9 @@ const (
eulers = 2.7182
supported_platforms = ['windows', 'mac', 'macos', 'darwin', 'linux', 'freebsd', 'openbsd',
'netbsd', 'dragonfly', 'android', 'js', 'solaris', 'haiku', 'linux_or_macos']
one_line_supported = ['windows', 'mac', 'macos', 'darwin', 'linux', 'freebsd', 'openbsd',
'netbsd', 'dragonfly', 'android', 'js', 'solaris', 'haiku', 'linux_or_macos']
another_const = [
'a', 'b',
'c', 'd', 'e',
'f'
]
one_line_supported = ['windows', 'mac', 'macos', 'darwin', 'linux', 'freebsd', 'openbsd', 'netbsd',
'dragonfly', 'android', 'js', 'solaris', 'haiku', 'linux_or_macos']
another_const = ['a', 'b', 'c', 'd', 'e', 'f']
)
const (

View File

@ -0,0 +1,41 @@
import v.checker
import v.ast
import v.table
pub fn string_inter_lit(mut c checker.Checker, mut node ast.StringInterLiteral) table.Type {
for i, expr in node.exprs {
ftyp := c.expr(expr)
node.expr_types << ftyp
typ := c.table.unalias_num_type(ftyp)
mut fmt := node.fmts[i]
// analyze and validate format specifier
if fmt !in [`E`, `F`, `G`, `e`, `f`, `g`, `d`, `u`, `x`, `X`, `o`, `c`, `s`, `p`, `_`] {
c.error('unknown format specifier `${fmt:c}`', node.fmt_poss[i])
}
if node.precisions[i] != 0 && !typ.is_float() {
c.error('precision specification only valid for float types', node.fmt_poss[i])
}
if node.pluss[i] && !typ.is_number() {
c.error('plus prefix only allowd for numbers', node.fmt_poss[i])
}
if (typ.is_unsigned() && fmt !in [`u`, `x`, `X`, `o`, `c`]) ||
(typ.is_signed() && fmt !in [`d`, `x`, `X`, `o`, `c`]) ||
(typ.is_any_int() && fmt !in [`d`, `c`, `x`, `X`, `o`, `u`, `x`, `X`, `o`]) ||
(typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`]) ||
(typ.is_pointer() && fmt !in [`p`, `x`, `X`]) ||
(typ.is_string() && fmt != `s`) ||
(typ.idx() in [table.i64_type_idx, table.f64_type_idx] &&
fmt == `c`) {
c.error('illegal format specifier `${fmt:c}` for type `${c.table.get_type_name(ftyp)}`',
node.fmt_poss[i])
}
node.need_fmts[i] = fmt != c.get_default_fmt(ftyp, typ)
}
return table.string_type
}
fn get_some_val(a_test, b_test, c_test, d_test, e_test, f_test f64) {
return a_test * b_test * c_test * d_test +
e_test * f_test * a_test * d_test +
a_test * b_test * c_test
}

View File

@ -0,0 +1,47 @@
import v.checker
import v.ast
import v.table
pub fn string_inter_lit(mut c checker.Checker, mut node ast.StringInterLiteral) table.Type {
for i, expr in node.exprs {
ftyp := c.expr(expr)
node.expr_types << ftyp
typ := c.table.unalias_num_type(ftyp)
mut fmt := node.fmts[i]
// analyze and validate format specifier
if fmt !in [`E`, `F`, `G`, `e`, `f`, `g`,
`d`, `u`, `x`, `X`, `o`, `c`, `s`, `p`, `_`] {
c.error('unknown format specifier `${fmt:c}`',
node.fmt_poss[i])
}
if node.precisions[i] != 0 &&
!typ.is_float() {
c.error('precision specification only valid for float types',
node.fmt_poss[i])
}
if node.pluss[i] && !typ.is_number() {
c.error('plus prefix only allowd for numbers', node.fmt_poss[i])
}
if (typ.is_unsigned() && fmt !in [`u`, `x`, `X`, `o`, `c`]) || (typ.is_signed() &&
fmt !in [`d`, `x`, `X`, `o`, `c`]) || (typ.is_any_int()
&& fmt !in [`d`, `c`, `x`, `X`, `o`,
`u`, `x`, `X`, `o`]) || (typ.is_float() && fmt !in [`E`, `F`,
`G`, `e`, `f`, `g`]) || (typ.is_pointer() &&
fmt !in [`p`, `x`, `X`]) || (typ.is_string() && fmt != `s`)
|| (typ.idx() in [table.i64_type_idx,
table.f64_type_idx
] && fmt == `c`) {
c.error('illegal format specifier `${fmt:c}` for type `${c.table.get_type_name(ftyp)}`',
node.fmt_poss[i])
}
node.need_fmts[i] = fmt != c.get_default_fmt(ftyp, typ)
}
return table.string_type
}
fn get_some_val(a_test, b_test, c_test, d_test, e_test, f_test f64) {
return a_test*b_test*c_test*
d_test+e_test*f_test*a_test*d_test+a_test*
b_test*c_test
}