@@ -24,9 +24,6 @@ use rayon::prelude::IntoParallelRefIterator;
2424use rayon:: prelude:: ParallelIterator ;
2525use reference:: Reference ;
2626use std:: collections:: HashMap ;
27- use std:: fmt;
28- use std:: fmt:: Display ;
29- use std:: fmt:: Formatter ;
3027use std:: { collections:: HashSet , path:: PathBuf } ;
3128use tracing:: debug;
3229
@@ -35,7 +32,7 @@ use super::reference_extractor::get_all_references;
3532
3633#[ derive( PartialEq , Clone , Eq , Hash , Debug ) ]
3734pub struct ViolationIdentifier {
38- pub violation_type : String ,
35+ pub violation_type : CheckerType ,
3936 pub strict : bool ,
4037 pub file : String ,
4138 pub constant_name : String ,
@@ -52,13 +49,15 @@ pub struct ViolationIdentifier {
5249/// - Keeping line/column out of the identity makes violations stable across
5350/// minor code movements that shift line numbers
5451///
55- /// `message` contains the violation description without the file location prefix.
56- /// Formatters are responsible for combining source_location with message as needed.
52+ /// Violations store only data - template expansion happens in formatters.
5753#[ derive( PartialEq , Clone , Eq , Hash , Debug ) ]
5854pub struct Violation {
59- pub message : String ,
6055 pub identifier : ViolationIdentifier ,
6156 pub source_location : SourceLocation ,
57+ // Additional data for template expansion:
58+ pub referencing_pack_relative_yml : String ,
59+ pub defining_layer : Option < String > ,
60+ pub referencing_layer : Option < String > ,
6261}
6362
6463pub ( crate ) trait CheckerInterface {
@@ -82,77 +81,12 @@ pub struct CheckAllResult {
8281 pub strict_mode_violations : HashSet < Violation > ,
8382}
8483
85- const REFERENCE_LOCATION_PLACEHOLDER : & str = "{{reference_location}}" ;
86-
8784impl CheckAllResult {
8885 pub fn has_violations ( & self ) -> bool {
8986 !self . reportable_violations . is_empty ( )
9087 || !self . stale_violations . is_empty ( )
9188 || !self . strict_mode_violations . is_empty ( )
9289 }
93-
94- /// Format a violation message, substituting `{{reference_location}}` if present.
95- fn format_violation_message ( violation : & Violation ) -> String {
96- let location = format ! (
97- "{}:{}:{}" ,
98- violation. identifier. file,
99- violation. source_location. line,
100- violation. source_location. column
101- ) ;
102-
103- if violation. message . contains ( REFERENCE_LOCATION_PLACEHOLDER ) {
104- // Custom template uses {{reference_location}} - substitute it
105- violation. message . replace (
106- REFERENCE_LOCATION_PLACEHOLDER ,
107- & format ! ( "{}\n " , location) ,
108- )
109- } else {
110- // Default template - prepend location
111- format ! ( "{}\n {}" , location, violation. message)
112- }
113- }
114-
115- fn write_violations ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
116- if !self . reportable_violations . is_empty ( ) {
117- let mut sorted_violations: Vec < & Violation > =
118- self . reportable_violations . iter ( ) . collect ( ) ;
119- sorted_violations. sort_by ( |a, b| a. message . cmp ( & b. message ) ) ;
120-
121- writeln ! ( f, "{} violation(s) detected:" , sorted_violations. len( ) ) ?;
122-
123- for violation in sorted_violations {
124- let formatted = Self :: format_violation_message ( violation) ;
125- writeln ! ( f, "{}\n " , formatted) ?;
126- }
127- }
128-
129- if !self . stale_violations . is_empty ( ) {
130- writeln ! (
131- f,
132- "There were stale violations found, please run `{} update`" ,
133- bin_locater:: packs_bin_name( ) ,
134- ) ?;
135- }
136-
137- if !self . strict_mode_violations . is_empty ( ) {
138- for v in self . strict_mode_violations . iter ( ) {
139- let error_message =
140- build_strict_violation_message ( & v. identifier ) ;
141- writeln ! ( f, "{}" , error_message) ?;
142- }
143- }
144- Ok ( ( ) )
145- }
146- }
147-
148- impl Display for CheckAllResult {
149- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
150- if self . has_violations ( ) {
151- self . write_violations ( f)
152- } else {
153- write ! ( f, "No violations detected!" )
154- }
155- }
15690}
15791struct CheckAllBuilder < ' a > {
15892 configuration : & ' a Configuration ,
@@ -543,57 +477,5 @@ fn remove_reference_to_dependency(
543477 write_pack_to_disk ( & updated_pack) ?;
544478 Ok ( ( ) )
545479}
546- #[ cfg( test) ]
547- mod tests {
548- use std:: collections:: HashSet ;
549-
550- use crate :: packs:: checker:: {
551- CheckAllResult , Violation , ViolationIdentifier ,
552- } ;
553- use crate :: packs:: SourceLocation ;
554-
555- #[ test]
556- fn test_write_violations ( ) {
557- let check_result = CheckAllResult {
558- reportable_violations : [ Violation {
559- message : "Privacy violation: `::Foo::PrivateClass` is private to `foo`, but referenced from `bar`" . to_string ( ) ,
560- identifier : ViolationIdentifier {
561- violation_type : "Privacy" . to_string ( ) ,
562- strict : false ,
563- file : "foo/bar/file1.rb" . to_string ( ) ,
564- constant_name : "::Foo::PrivateClass" . to_string ( ) ,
565- referencing_pack_name : "bar" . to_string ( ) ,
566- defining_pack_name : "foo" . to_string ( ) ,
567- } ,
568- source_location : SourceLocation { line : 10 , column : 5 } ,
569- } ,
570- Violation {
571- message : "Dependency violation: `::Foo::AnotherClass` is not allowed to depend on `::Bar::SomeClass`" . to_string ( ) ,
572- identifier : ViolationIdentifier {
573- violation_type : "Dependency" . to_string ( ) ,
574- strict : false ,
575- file : "foo/bar/file2.rb" . to_string ( ) ,
576- constant_name : "::Foo::AnotherClass" . to_string ( ) ,
577- referencing_pack_name : "foo" . to_string ( ) ,
578- defining_pack_name : "bar" . to_string ( ) ,
579- } ,
580- source_location : SourceLocation { line : 15 , column : 3 } ,
581- } ] . iter ( ) . cloned ( ) . collect ( ) ,
582- stale_violations : Vec :: new ( ) ,
583- strict_mode_violations : HashSet :: new ( ) ,
584- } ;
585-
586- let expected_output = "2 violation(s) detected:
587- foo/bar/file2.rb:15:3
588- Dependency violation: `::Foo::AnotherClass` is not allowed to depend on `::Bar::SomeClass`
589-
590- foo/bar/file1.rb:10:5
591- Privacy violation: `::Foo::PrivateClass` is private to `foo`, but referenced from `bar`
592-
593- " ;
594-
595- let actual = format ! ( "{}" , check_result) ;
596-
597- assert_eq ! ( actual, expected_output) ;
598- }
599- }
480+ // Note: Display impl was removed from CheckAllResult. Use write_text() directly with Configuration.
481+ // Tests for text formatting are in text.rs
0 commit comments