From c27430c87f4839afbd91df4329159c84b05a6d80 Mon Sep 17 00:00:00 2001 From: Xavier Mitault Date: Tue, 30 Jan 2024 21:13:57 +0100 Subject: [PATCH] First version not tested --- src/main.v | 13 +++-- src/output_d2.v | 100 ++++++++++++++++++++++++++++++++++++- src/process_file.v | 6 +-- src/process_file_haskell.v | 19 +++++-- 4 files changed, 125 insertions(+), 13 deletions(-) diff --git a/src/main.v b/src/main.v index 346684c..f8b2131 100644 --- a/src/main.v +++ b/src/main.v @@ -9,10 +9,13 @@ fn main() { fp.version("0.0.0") fp.description("output d2 dependency graph") fp.skip_executable() - a_string := fp.string_opt("language", `l`, "Language to use for the folders") or { + a_language := fp.string_opt("language", `l`, "Language to use for the folders") or { eprintln(fp.usage()) exit(1) } + a_output := fp.string_opt("output", `o`, "Output file") or { + "dependency_graph.d2" + } folders := fp.finalize() or { eprintln(err) eprintln(fp.usage()) @@ -21,13 +24,17 @@ fn main() { mut deps := []DependencyGraph{} for folder in folders { println('Processing ${folder} ...') - dep := process_folder(folder, a_string) or { + dep := process_folder(folder, a_language) or { eprintln(err) continue } deps << dep } - output_d2(deps) or { + lines := output_d2(deps, a_language) or { + eprintln(err) + exit(1) + } + os.write_file(a_output, lines.join('\n')) or { eprintln(err) exit(1) } diff --git a/src/output_d2.v b/src/output_d2.v index 252e084..e261fb6 100644 --- a/src/output_d2.v +++ b/src/output_d2.v @@ -1,5 +1,101 @@ module main -fn output_d2(deps []DependencyGraph) ![]string { - return []string{} +struct ImportTree { +pub mut: + name string + modules []ImportTree +} + +fn (tree ImportTree) print(increment int) { + println('->'.repeat(increment) + ' ${tree.name}') + for mod in tree.modules { + mod.print(increment + 1) + } +} + +fn (tree ImportTree) to_d2(increment int) []string { + mut res := []string{} + res << ' '.repeat(increment) + '${tree.name} {' + for mod in tree.modules { + res << mod.to_d2(increment + 1) + } + res << '}' + return res +} + +fn append_dep_to_tree(name []string, mut tree ImportTree) bool { + if name.len == 0 { + return false + } + if name[0] == tree.name { + if name.len == 1 { + for mod in tree.modules { + if mod.name == name[1] { + return true + } + } + tree.modules << ImportTree{ + name: name[1] + } + return true + } else { + return append_dep_to_tree(name[1..], mut tree) + } + } + return false +} + +fn rec_append_modules(mut treeRoot ImportTree, name []string) { + if name.len == 0 { + return + } + mut tree := ImportTree{ + name: name[0] + } + rec_append_modules(mut tree, name[1..]) + treeRoot.modules << tree +} + +fn append_dep_to_trees(dep DependencyGraph, mut trees []ImportTree) { + mut found := false + for mut tree in trees { + found = append_dep_to_tree(dep.name, mut tree) + if found { + break + } + } + if !found { + mut tree := ImportTree{ + name: dep.name[0] + } + rec_append_modules(mut tree, dep.name[1..]) + trees << tree + } +} + +fn output_d2(deps []DependencyGraph, language string) ![]string { + mut lines := []string{} + mut trees := []ImportTree{} + for dep in deps { + if dep.language != language { + continue + } + println(dep) + append_dep_to_trees(dep, mut trees) + } + for tree in trees { + lines << tree.to_d2(0) + } + lines << '' + for dep in deps { + if dep.language != language { + continue + } + lines << '' + for imp in dep.dependencies { + lines << '${dep.name.join(".")} -> ${imp.join(".")}' + } + } + println(lines) + return lines } diff --git a/src/process_file.v b/src/process_file.v index 55f28b9..5500c38 100644 --- a/src/process_file.v +++ b/src/process_file.v @@ -7,7 +7,7 @@ pub mut: language string file_path string name []string - dependencies []string + dependencies [][]string } fn process_file(file string, language string) !DependencyGraph { @@ -15,10 +15,10 @@ fn process_file(file string, language string) !DependencyGraph { return error("not a file ${file}") } mut dep := DependencyGraph{ - language: language, file_path: file, } - if is_haskell_file(file) { + if language == 'haskell' && is_haskell_file(file) { + dep.language = language process_file_haskell(mut dep)! } return dep diff --git a/src/process_file_haskell.v b/src/process_file_haskell.v index aaa50a5..86cbecf 100644 --- a/src/process_file_haskell.v +++ b/src/process_file_haskell.v @@ -9,18 +9,27 @@ fn is_haskell_file(file string) bool { fn process_file_haskell(mut dep &DependencyGraph) ! { mut name := dep.file_path.split(os.path_separator) + if name.len == 0 { + return error("not a file ${dep.file_path}") + } + if name[0] == '.' { + name.drop(1) + } if 'src' in name { name.drop(name.index('src')) } if 'app' in name { name.drop(name.index('app')) } - dep.name << name.join('.') - query := r'^import (qualified)? ([\w.]+)' + name[name.len - 1] = name.last().all_before_last(os.file_ext(name.last())) + dep.name << name + query := r'^import (qualified )? *([\w\.]+)' mut re := regex.regex_opt(query)! lines := os.read_file(dep.file_path)! - for imports in re.find_all_str(lines) { - dep_tmp := re.get_group_by_id(imports, 2) - dep.dependencies << dep_tmp + imports := re.find_all_str(lines) + for imp in imports { + re.match_string(imp) + dep_tmp := re.get_group_by_id(imp, 1) + dep.dependencies << dep_tmp.split('.') } }