@@ -4,24 +4,87 @@ import (
44 "fmt"
55 "time"
66
7- "github.com/dotcommander/cclint/internal/config"
87 "github.com/dotcommander/cclint/internal/cli"
8+ "github.com/dotcommander/cclint/internal/config"
99 "github.com/dotcommander/cclint/internal/output"
1010)
1111
12- // Outputter handles output formatting
12+ // =============================================================================
13+ // Dependency Inversion: Formatter interface for output formatters
14+ // =============================================================================
15+
16+ // Formatter defines the interface for output formatters.
17+ // This allows the Outputter to depend on an abstraction rather than
18+ // concrete formatter implementations (DIP compliance).
19+ type Formatter interface {
20+ // Format formats the lint summary and outputs it
21+ Format (summary * cli.LintSummary ) error
22+ }
23+
24+ // FormatterFactory creates formatters based on format type.
25+ // This follows the Factory pattern for DIP compliance.
26+ type FormatterFactory interface {
27+ // CreateFormatter creates a formatter for the given format type
28+ CreateFormatter (format string ) (Formatter , error )
29+ }
30+
31+ // =============================================================================
32+ // Default FormatterFactory implementation
33+ // =============================================================================
34+
35+ // DefaultFormatterFactory creates formatters using the output package.
36+ type DefaultFormatterFactory struct {
37+ cfg * config.Config
38+ }
39+
40+ // NewDefaultFormatterFactory creates a new DefaultFormatterFactory.
41+ func NewDefaultFormatterFactory (cfg * config.Config ) * DefaultFormatterFactory {
42+ return & DefaultFormatterFactory {cfg : cfg }
43+ }
44+
45+ // CreateFormatter implements FormatterFactory interface.
46+ func (f * DefaultFormatterFactory ) CreateFormatter (format string ) (Formatter , error ) {
47+ switch format {
48+ case "console" :
49+ return output .NewConsoleFormatter (f .cfg .Quiet , f .cfg .Verbose , f .cfg .ShowScores , f .cfg .ShowImprovements ), nil
50+ case "json" :
51+ return output .NewJSONFormatter (f .cfg .Quiet , true , f .cfg .Output ), nil
52+ case "markdown" :
53+ return output .NewMarkdownFormatter (f .cfg .Quiet , f .cfg .Verbose , f .cfg .Output ), nil
54+ default :
55+ return nil , fmt .Errorf ("unsupported format: %s" , format )
56+ }
57+ }
58+
59+ // =============================================================================
60+ // Outputter with DIP-compliant design
61+ // =============================================================================
62+
63+ // Outputter handles output formatting using injected formatter factory.
64+ // It depends on the FormatterFactory abstraction, not concrete formatters.
1365type Outputter struct {
14- config * config.Config
66+ config * config.Config
67+ factory FormatterFactory
1568}
1669
17- // NewOutputter creates a new Outputter
70+ // NewOutputter creates a new Outputter with the default formatter factory.
1871func NewOutputter (config * config.Config ) * Outputter {
1972 return & Outputter {
20- config : config ,
73+ config : config ,
74+ factory : NewDefaultFormatterFactory (config ),
2175 }
2276}
2377
24- // Format formats the lint summary using the configured format
78+ // NewOutputterWithFactory creates a new Outputter with a custom formatter factory.
79+ // This allows for dependency injection and easier testing.
80+ func NewOutputterWithFactory (config * config.Config , factory FormatterFactory ) * Outputter {
81+ return & Outputter {
82+ config : config ,
83+ factory : factory ,
84+ }
85+ }
86+
87+ // Format formats the lint summary using the configured format.
2588func (o * Outputter ) Format (summary * cli.LintSummary , format string ) error {
2689 // Set start time if not set
2790 if summary .StartTime .IsZero () {
@@ -31,18 +94,11 @@ func (o *Outputter) Format(summary *cli.LintSummary, format string) error {
3194 // Set project root in summary for display
3295 summary .ProjectRoot = o .config .Root
3396
34- // Create appropriate formatter based on format
35- switch format {
36- case "console" :
37- formatter := output .NewConsoleFormatter (o .config .Quiet , o .config .Verbose , o .config .ShowScores , o .config .ShowImprovements )
38- return formatter .Format (summary )
39- case "json" :
40- formatter := output .NewJSONFormatter (o .config .Quiet , true , o .config .Output )
41- return formatter .Format (summary )
42- case "markdown" :
43- formatter := output .NewMarkdownFormatter (o .config .Quiet , o .config .Verbose , o .config .Output )
44- return formatter .Format (summary )
45- default :
46- return fmt .Errorf ("unsupported format: %s" , format )
97+ // Create formatter via factory (DIP compliance)
98+ formatter , err := o .factory .CreateFormatter (format )
99+ if err != nil {
100+ return err
47101 }
102+
103+ return formatter .Format (summary )
48104}
0 commit comments