diff --git a/docs/architecture/module.mmd b/docs/architecture/module.mmd index e0db7c4..979a2ad 100644 --- a/docs/architecture/module.mmd +++ b/docs/architecture/module.mmd @@ -3,8 +3,8 @@ graph TD Presentation[Presentation] Adapters[Adapters] Application[Application] - Presentation -->|1 dep| Application - Adapters -->|25 deps| Domain Presentation -->|1 dep| Domain + Adapters -->|26 deps| Domain Presentation -->|11 deps| Adapters - Application -->|4 deps| Domain \ No newline at end of file + Application -->|5 deps| Domain + Presentation -->|1 dep| Application \ No newline at end of file diff --git a/docs/architecture/project.mmd b/docs/architecture/project.mmd index eee7b3b..818fd1d 100644 --- a/docs/architecture/project.mmd +++ b/docs/architecture/project.mmd @@ -14,29 +14,35 @@ graph TD archlens_python_project[archlens-python-project] archlens_d2[archlens-d2] archlens_html[archlens-html] + archlens_rendering_primitives[archlens-rendering-primitives] end archlens_application --> archlens_domain - archlens --> archlens_application - archlens --> archlens_mermaid - archlens --> archlens_stdout_writer - archlens --> archlens_ascii - archlens --> archlens_domain - archlens --> archlens_file_writer - archlens --> archlens_python_project - archlens --> archlens_walkdir - archlens --> archlens_toml_config - archlens --> archlens_html - archlens --> archlens_cargo_workspace - archlens --> archlens_d2 archlens --> archlens_tree_sitter + archlens --> archlens_walkdir + archlens --> archlens_application + archlens --> archlens_stdout_writer + archlens --> archlens_html + archlens --> archlens_file_writer + archlens --> archlens_mermaid + archlens --> archlens_toml_config + archlens --> archlens_cargo_workspace + archlens --> archlens_python_project + archlens --> archlens_ascii + archlens --> archlens_d2 + archlens --> archlens_domain archlens_tree_sitter --> archlens_domain archlens_walkdir --> archlens_domain archlens_mermaid --> archlens_domain + archlens_mermaid --> archlens_rendering_primitives + archlens_ascii --> archlens_rendering_primitives archlens_ascii --> archlens_domain archlens_file_writer --> archlens_domain archlens_stdout_writer --> archlens_domain archlens_toml_config --> archlens_domain archlens_cargo_workspace --> archlens_domain archlens_python_project --> archlens_domain + archlens_d2 --> archlens_rendering_primitives archlens_d2 --> archlens_domain - archlens_html --> archlens_domain \ No newline at end of file + archlens_html --> archlens_rendering_primitives + archlens_html --> archlens_domain + archlens_rendering_primitives --> archlens_domain \ No newline at end of file diff --git a/docs/architecture/type/application.mmd b/docs/architecture/type/application.mmd index 1d2f110..d99a9c6 100644 --- a/docs/architecture/type/application.mmd +++ b/docs/architecture/type/application.mmd @@ -2,6 +2,8 @@ classDiagram namespace Application { class AnalyzeCodebase class AnalyzeCodebaseResult + class BuildCodeGraphResult + class BuildCodeGraph class DiffResult class DiffDiagram class CheckFreshness @@ -16,16 +18,22 @@ classDiagram AnalyzeCodebaseResult : warnings Vec AnalyzeCodebaseResult : +graph() -] NormalizedGraph AnalyzeCodebaseResult : +warnings() -] [AnalysisWarning] + BuildCodeGraphResult : graph NormalizedGraph + BuildCodeGraphResult : warnings Vec + BuildCodeGraph : discovery F + BuildCodeGraph : source_analyzer S + BuildCodeGraph : project_analyzer Option + BuildCodeGraph : +execute(root Path, config AnalysisConfig, level DiagramLevel) -] Result[BuildCodeGraphResult, DomainError] DiffResult : added Vec DiffResult : removed Vec DiffResult : +is_empty() -] bool DiffDiagram : graph a NormalizedGraph DiffDiagram : renderer a dyn DiagramRenderer - DiffDiagram : existing_path a std path Path + DiffDiagram : existing_content a str DiffDiagram : +execute() -] Result[DiffResult, DomainError] CheckFreshness : graph a NormalizedGraph CheckFreshness : renderer a dyn DiagramRenderer - CheckFreshness : existing_path a std path Path + CheckFreshness : existing_content a str CheckFreshness : +execute() -] Result[bool, DomainError] GenerateDiagramResult : violations Vec GenerateDiagramResult : output RenderOutput @@ -34,14 +42,11 @@ classDiagram GenerateDiagram : allow_rules Vec GenerateDiagram : deny_rules Vec GenerateDiagram : split_by_module bool - GenerateDiagram : format_ext String - GenerateDiagram : output_dir Option - GenerateDiagram : +execute() -] Result[(), DomainError] - GenerateDiagram : +check_violations_only() -] Vec[String] + GenerateDiagram : +execute() -] Result[GenerateDiagramResult, DomainError] class application_module["Application"] { <> } class domain_module["Domain"] { <> } - application_module --> domain_module : 3 deps \ No newline at end of file + application_module --> domain_module : 4 deps \ No newline at end of file diff --git a/docs/architecture/type/overview.mmd b/docs/architecture/type/overview.mmd index 932d91a..f7eae81 100644 --- a/docs/architecture/type/overview.mmd +++ b/docs/architecture/type/overview.mmd @@ -1,7 +1,34 @@ classDiagram - namespace Presentation { - class Cli - class Command + namespace Domain { + class OutputConfig + class DiagramLevel + class RenderOutput + class RenderedFile + class SourceFile + class ModuleName + class ModuleAssignment + class Language + class FilePath + class RelationshipKind + class Visibility + class CodeElementKind + class RuleKind + class RuleViolation + class BoundaryRule + class AnalysisConfig + class AnalysisResult + class AnalysisWarning + class Relationship + class CodeElement + class FileDiscovery + class ConfigLoader + class ProjectAnalyzer + class OutputWriter + class DiagramRenderer + class SourceAnalyzer + class NormalizedGraph + class CodeGraph + class DomainError } namespace Adapters { class MermaidRenderer @@ -36,158 +63,21 @@ classDiagram class MemberToml class PackageSection } - namespace Domain { - class OutputConfig - class DiagramLevel - class RenderOutput - class RenderedFile - class SourceFile - class ModuleName - class ModuleAssignment - class Language - class FilePath - class RelationshipKind - class Visibility - class CodeElementKind - class RuleKind - class RuleViolation - class BoundaryRule - class AnalysisConfig - class AnalysisResult - class AnalysisWarning - class Relationship - class CodeElement - class FileDiscovery - class ConfigLoader - class ProjectAnalyzer - class OutputWriter - class DiagramRenderer - class SourceAnalyzer - class NormalizedGraph - class CodeGraph - class DomainError + namespace Presentation { + class Cli + class Command } namespace Application { class AnalyzeCodebase class AnalyzeCodebaseResult + class BuildCodeGraphResult + class BuildCodeGraph class DiffResult class DiffDiagram class CheckFreshness class GenerateDiagramResult class GenerateDiagram } - Cli : command Option - Cli : path PathBuf - Cli : level String - Cli : format String - Cli : output Option - Cli : config Option - Cli : scope Option - Cli : exclude Vec - Cli : include_tests bool - Cli : no_weights bool - Cli : watch bool - Cli : since Option - Cli : split_by_module bool - Cli : strict bool - Cli : check bool - Cli : verbose u8 - MermaidRenderer : level DiagramLevel - MermaidRenderer : show_weights bool - MermaidRenderer : +new() -] Self - MermaidRenderer : +with_level(level DiagramLevel) -] Self - MermaidRenderer : +with_weights(show bool) -] Self - MermaidRenderer : -display_name(qualified str) -] str - MermaidRenderer : -format_element_name(element CodeElement) -] String - MermaidRenderer : -format_visibility(visibility Visibility) -] static str - MermaidRenderer : -render_class_diagram(graph CodeGraph) -] String - MermaidRenderer : -push_class_lines(lines mut Vec[String], deferred mut Vec[String], element CodeElement, indent str, in_namespace bool) - MermaidRenderer : -render_module_flowchart(graph CodeGraph) -] String - MermaidRenderer : -render_project_flowchart(graph CodeGraph) -] String - MermaidRenderer : -sanitize_id(name str) -] String - AsciiRenderer : +new() -] Self - AsciiRenderer : -format_kind(element CodeElement) -] static str - PythonProjectAnalyzer : +new() -] Self - <> ProjectSection - ProjectSection : name Option - ProjectSection : dependencies Vec - <> PoetrySection - PoetrySection : name Option - PoetrySection : dependencies HashMap - <> ToolSection - ToolSection : poetry PoetrySection - <> PyprojectToml - PyprojectToml : project Option - PyprojectToml : tool ToolSection - WalkdirDiscovery : +new() -] Self - WalkdirDiscovery : -detect_language(path Path) -] Option[Language] - WalkdirDiscovery : -is_excluded(path Path, root Path, excludes [String]) -] bool - ExtractionContext : elements Vec - ExtractionContext : relationships Vec - ExtractionContext : warnings Vec - ExtractionContext : local_types HashSet - ExtractionContext : file_path FilePath - ExtractionContext : +new(file_path FilePath) -] Self - ExtractionContext : +add_element(element CodeElement) - ExtractionContext : +add_relationship(rel Relationship) - ExtractionContext : +add_warning(file_path FilePath, line usize, message str) - ExtractionContext : +file_path() -] FilePath - ExtractionContext : +into_result() -] Result[AnalysisResult, DomainError] - TreeSitterAnalyzer : rust RustExtractor - TreeSitterAnalyzer : python PythonExtractor - TreeSitterAnalyzer : +new() -] Self - TreeSitterAnalyzer : -extractor_for(language Language) -] Option[dyn LanguageExtractor] - FileOutputWriter : output_path OutputPath - FileOutputWriter : +new(output_dir PathBuf) -] Self - FileOutputWriter : +single_file(path PathBuf) -] Self - <> OutputPath - StdoutOutputWriter : +new() -] Self - <> RawRules - RawRules : allow Vec - RawRules : deny Vec - <> RawConfig - RawConfig : analysis RawAnalysis - RawConfig : output RawOutput - RawConfig : modules HashMap - RawConfig : rules RawRules - <> RawAnalysis - RawAnalysis : exclude Vec - RawAnalysis : level Option - <> RawOutput - RawOutput : format Option - RawOutput : path Option - RawOutput : split_by_module bool - TomlConfigLoader : raw RawConfig - TomlConfigLoader : +from_path(path Path) -] Result[Self, DomainError] - TomlConfigLoader : -parse_level(level Option[String]) -] DiagramLevel - D2Renderer : level DiagramLevel - D2Renderer : +new() -] Self - D2Renderer : +with_level(level DiagramLevel) -] Self - HtmlRenderer : +new() -] Self - <> GraphData - GraphData : nodes Vec - GraphData : edges Vec - <> NodeData - NodeData : id String - NodeData : label String - NodeData : module String - NodeData : kind String - NodeData : fields Vec - NodeData : methods Vec - <> EdgeData - EdgeData : source String - EdgeData : target String - EdgeData : kind String - CargoWorkspaceAnalyzer : +new() -] Self - <> WorkspaceToml - WorkspaceToml : workspace Option - <> WorkspaceSection - WorkspaceSection : members Vec - <> MemberToml - MemberToml : package Option - MemberToml : dependencies HashMap - <> PackageSection - PackageSection : name String OutputConfig : split_by_module bool OutputConfig : output_path Option OutputConfig : +with_split_by_module(split bool) -] Self @@ -336,6 +226,118 @@ classDiagram CodeGraph : +subgraph_by_module(module ModuleName) -] CodeGraph CodeGraph : +merge_project_edges(project_graph CodeGraph) CodeGraph : +module_edges() -] HashMap[(String, String), usize] + MermaidRenderer : level DiagramLevel + MermaidRenderer : show_weights bool + MermaidRenderer : +new() -] Self + MermaidRenderer : +with_level(level DiagramLevel) -] Self + MermaidRenderer : +with_weights(show bool) -] Self + MermaidRenderer : -display_name(qualified str) -] str + MermaidRenderer : -format_element_name(element CodeElement) -] String + MermaidRenderer : -format_visibility(visibility Visibility) -] static str + MermaidRenderer : -render_class_diagram(graph CodeGraph) -] String + MermaidRenderer : -push_class_lines(lines mut Vec[String], deferred mut Vec[String], element CodeElement, indent str, in_namespace bool) + MermaidRenderer : -render_module_flowchart(graph CodeGraph) -] String + MermaidRenderer : -render_project_flowchart(graph CodeGraph) -] String + MermaidRenderer : -sanitize_id(name str) -] String + AsciiRenderer : +new() -] Self + AsciiRenderer : -format_kind(element CodeElement) -] static str + PythonProjectAnalyzer : +new() -] Self + <> ProjectSection + ProjectSection : name Option + ProjectSection : dependencies Vec + <> PoetrySection + PoetrySection : name Option + PoetrySection : dependencies HashMap + <> ToolSection + ToolSection : poetry PoetrySection + <> PyprojectToml + PyprojectToml : project Option + PyprojectToml : tool ToolSection + WalkdirDiscovery : +new() -] Self + WalkdirDiscovery : -detect_language(path Path) -] Option[Language] + WalkdirDiscovery : -is_excluded(path Path, root Path, excludes [String]) -] bool + ExtractionContext : elements Vec + ExtractionContext : relationships Vec + ExtractionContext : warnings Vec + ExtractionContext : local_types HashSet + ExtractionContext : file_path FilePath + ExtractionContext : +new(file_path FilePath) -] Self + ExtractionContext : +add_element(element CodeElement) + ExtractionContext : +add_relationship(rel Relationship) + ExtractionContext : +add_warning(file_path FilePath, line usize, message str) + ExtractionContext : +file_path() -] FilePath + ExtractionContext : +into_result() -] Result[AnalysisResult, DomainError] + TreeSitterAnalyzer : rust RustExtractor + TreeSitterAnalyzer : python PythonExtractor + TreeSitterAnalyzer : +new() -] Self + TreeSitterAnalyzer : -extractor_for(language Language) -] Option[dyn LanguageExtractor] + FileOutputWriter : output_path OutputPath + FileOutputWriter : +new(output_dir PathBuf) -] Self + FileOutputWriter : +single_file(path PathBuf) -] Self + <> OutputPath + StdoutOutputWriter : +new() -] Self + <> RawRules + RawRules : allow Vec + RawRules : deny Vec + <> RawConfig + RawConfig : analysis RawAnalysis + RawConfig : output RawOutput + RawConfig : modules HashMap + RawConfig : rules RawRules + <> RawAnalysis + RawAnalysis : exclude Vec + RawAnalysis : level Option + <> RawOutput + RawOutput : format Option + RawOutput : path Option + RawOutput : split_by_module bool + TomlConfigLoader : raw RawConfig + TomlConfigLoader : +from_path(path Path) -] Result[Self, DomainError] + TomlConfigLoader : -parse_level(level Option[String]) -] DiagramLevel + D2Renderer : level DiagramLevel + D2Renderer : +new() -] Self + D2Renderer : +with_level(level DiagramLevel) -] Self + HtmlRenderer : +new() -] Self + <> GraphData + GraphData : nodes Vec + GraphData : edges Vec + <> NodeData + NodeData : id String + NodeData : label String + NodeData : module String + NodeData : kind String + NodeData : fields Vec + NodeData : methods Vec + <> EdgeData + EdgeData : source String + EdgeData : target String + EdgeData : kind String + CargoWorkspaceAnalyzer : +new() -] Self + <> WorkspaceToml + WorkspaceToml : workspace Option + <> WorkspaceSection + WorkspaceSection : members Vec + <> MemberToml + MemberToml : package Option + MemberToml : dependencies HashMap + <> PackageSection + PackageSection : name String + Cli : command Option + Cli : path PathBuf + Cli : level String + Cli : format String + Cli : output Option + Cli : config Option + Cli : scope Option + Cli : exclude Vec + Cli : include_tests bool + Cli : no_weights bool + Cli : watch bool + Cli : since Option + Cli : split_by_module bool + Cli : strict bool + Cli : check bool + Cli : verbose u8 AnalyzeCodebase : file_discovery F AnalyzeCodebase : source_analyzer S AnalyzeCodebase : +new(file_discovery F, source_analyzer S) -] Self @@ -344,16 +346,22 @@ classDiagram AnalyzeCodebaseResult : warnings Vec AnalyzeCodebaseResult : +graph() -] NormalizedGraph AnalyzeCodebaseResult : +warnings() -] [AnalysisWarning] + BuildCodeGraphResult : graph NormalizedGraph + BuildCodeGraphResult : warnings Vec + BuildCodeGraph : discovery F + BuildCodeGraph : source_analyzer S + BuildCodeGraph : project_analyzer Option + BuildCodeGraph : +execute(root Path, config AnalysisConfig, level DiagramLevel) -] Result[BuildCodeGraphResult, DomainError] DiffResult : added Vec DiffResult : removed Vec DiffResult : +is_empty() -] bool DiffDiagram : graph a NormalizedGraph DiffDiagram : renderer a dyn DiagramRenderer - DiffDiagram : existing_path a std path Path + DiffDiagram : existing_content a str DiffDiagram : +execute() -] Result[DiffResult, DomainError] CheckFreshness : graph a NormalizedGraph CheckFreshness : renderer a dyn DiagramRenderer - CheckFreshness : existing_path a std path Path + CheckFreshness : existing_content a str CheckFreshness : +execute() -] Result[bool, DomainError] GenerateDiagramResult : violations Vec GenerateDiagramResult : output RenderOutput @@ -362,10 +370,7 @@ classDiagram GenerateDiagram : allow_rules Vec GenerateDiagram : deny_rules Vec GenerateDiagram : split_by_module bool - GenerateDiagram : format_ext String - GenerateDiagram : output_dir Option - GenerateDiagram : +execute() -] Result[(), DomainError] - GenerateDiagram : +check_violations_only() -] Vec[String] + GenerateDiagram : +execute() -] Result[GenerateDiagramResult, DomainError] SourceFile --> FilePath SourceFile --> Language RuleViolation --> RuleKind @@ -401,5 +406,6 @@ classDiagram HtmlRenderer <|-- DiagramRenderer CargoWorkspaceAnalyzer <|-- ProjectAnalyzer AnalyzeCodebaseResult --> NormalizedGraph + BuildCodeGraphResult --> NormalizedGraph GenerateDiagramResult --> RenderOutput GenerateDiagram --> NormalizedGraph \ No newline at end of file