From 97034103914f1a2a1b32041afdace0612fb9a15f Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 29 Aug 2022 15:30:50 +0300 Subject: [PATCH] vfmt: fix formatting of submodules with common prefixes (fix #15582) --- vlib/v/ast/str.v | 40 ++++++++++++++++--- .../shorten_longer_module_paths_first_keep.vv | 16 ++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 vlib/v/fmt/tests/shorten_longer_module_paths_first_keep.vv diff --git a/vlib/v/ast/str.v b/vlib/v/ast/str.v index 143e54ef0b..3434e14242 100644 --- a/vlib/v/ast/str.v +++ b/vlib/v/ast/str.v @@ -164,14 +164,44 @@ fn stringify_fn_after_name(node &FnDecl, mut f strings.Builder, t &Table, cur_mo } f.write_string(')') if node.return_type != void_type { - mut rs := util.no_cur_mod(t.type_to_str(node.return_type), cur_mod) - for mod, alias in m2a { - rs = rs.replace(mod, alias) - } - f.write_string(' ' + rs) + sreturn_type := util.no_cur_mod(t.type_to_str(node.return_type), cur_mod) + short_sreturn_type := shorten_full_name_based_on_aliases(sreturn_type, m2a) + f.write_string(' ' + short_sreturn_type) } } +struct StringifyModReplacement { + mod string + alias string + weight int +} + +fn shorten_full_name_based_on_aliases(input string, m2a map[string]string) string { + // Shorten the full names to their aliases, but replace the longer mods first, so that: + // `import user.project` + // `import user.project.routes` + // will lead to replacing `user.project.routes` first to `routes`, NOT `user.project.routes` to `project.routes`. + // Also take into account the nesting level, so `a.e.c.d` will be shortened before `a.xyz.b`, even though they are the same length. + mut replacements := []StringifyModReplacement{cap: m2a.len} + for mod, alias in m2a { + if input.contains(mod) { + replacements << StringifyModReplacement{ + mod: mod + alias: alias + weight: mod.count('.') * 100 + mod.len + } + } + } + mut res := input.clone() + if replacements.len > 0 { + replacements.sort(a.weight > b.weight) + for r in replacements { + res = res.replace(r.mod, r.alias) + } + } + return res +} + // Expressions in string interpolations may have to be put in braces if they // are non-trivial, if they would interfere with the next character or if a // format specification is given. In the latter case diff --git a/vlib/v/fmt/tests/shorten_longer_module_paths_first_keep.vv b/vlib/v/fmt/tests/shorten_longer_module_paths_first_keep.vv new file mode 100644 index 0000000000..b447b8ecae --- /dev/null +++ b/vlib/v/fmt/tests/shorten_longer_module_paths_first_keep.vv @@ -0,0 +1,16 @@ +module app + +import user.project +import user.project.routes + +pub fn new_app() ?project.Application { + return project.Application{ + data: get_router()!.route_name + } +} + +fn get_router() ?routes.Router { + return routes.Router{ + route_name: 'Root' + } +}