@@ -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,76 +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
106- . message
107- . replace ( REFERENCE_LOCATION_PLACEHOLDER , & format ! ( "{}\n " , location) )
108- } else {
109- // Default template - prepend location
110- format ! ( "{}\n {}" , location, violation. message)
111- }
112- }
113-
114- fn write_violations ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
115- if !self . reportable_violations . is_empty ( ) {
116- let mut sorted_violations: Vec < & Violation > =
117- self . reportable_violations . iter ( ) . collect ( ) ;
118- sorted_violations. sort_by ( |a, b| a. message . cmp ( & b. message ) ) ;
119-
120- writeln ! ( f, "{} violation(s) detected:" , sorted_violations. len( ) ) ?;
121-
122- for violation in sorted_violations {
123- let formatted = Self :: format_violation_message ( violation) ;
124- writeln ! ( f, "{}\n " , formatted) ?;
125- }
126- }
127-
128- if !self . stale_violations . is_empty ( ) {
129- writeln ! (
130- f,
131- "There were stale violations found, please run `{} update`" ,
132- bin_locater:: packs_bin_name( ) ,
133- ) ?;
134- }
135-
136- if !self . strict_mode_violations . is_empty ( ) {
137- for v in self . strict_mode_violations . iter ( ) {
138- let error_message =
139- build_strict_violation_message ( & v. identifier ) ;
140- writeln ! ( f, "{}" , error_message) ?;
141- }
142- }
143- Ok ( ( ) )
144- }
145- }
146-
147- impl Display for CheckAllResult {
148- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
149- if self . has_violations ( ) {
150- self . write_violations ( f)
151- } else {
152- write ! ( f, "No violations detected!" )
153- }
154- }
15590}
15691struct CheckAllBuilder < ' a > {
15792 configuration : & ' a Configuration ,
@@ -542,57 +477,5 @@ fn remove_reference_to_dependency(
542477 write_pack_to_disk ( & updated_pack) ?;
543478 Ok ( ( ) )
544479}
545- #[ cfg( test) ]
546- mod tests {
547- use std:: collections:: HashSet ;
548-
549- use crate :: packs:: checker:: {
550- CheckAllResult , Violation , ViolationIdentifier ,
551- } ;
552- use crate :: packs:: SourceLocation ;
553-
554- #[ test]
555- fn test_write_violations ( ) {
556- let check_result = CheckAllResult {
557- reportable_violations : [ Violation {
558- message : "Privacy violation: `::Foo::PrivateClass` is private to `foo`, but referenced from `bar`" . to_string ( ) ,
559- identifier : ViolationIdentifier {
560- violation_type : "Privacy" . to_string ( ) ,
561- strict : false ,
562- file : "foo/bar/file1.rb" . to_string ( ) ,
563- constant_name : "::Foo::PrivateClass" . to_string ( ) ,
564- referencing_pack_name : "bar" . to_string ( ) ,
565- defining_pack_name : "foo" . to_string ( ) ,
566- } ,
567- source_location : SourceLocation { line : 10 , column : 5 } ,
568- } ,
569- Violation {
570- message : "Dependency violation: `::Foo::AnotherClass` is not allowed to depend on `::Bar::SomeClass`" . to_string ( ) ,
571- identifier : ViolationIdentifier {
572- violation_type : "Dependency" . to_string ( ) ,
573- strict : false ,
574- file : "foo/bar/file2.rb" . to_string ( ) ,
575- constant_name : "::Foo::AnotherClass" . to_string ( ) ,
576- referencing_pack_name : "foo" . to_string ( ) ,
577- defining_pack_name : "bar" . to_string ( ) ,
578- } ,
579- source_location : SourceLocation { line : 15 , column : 3 } ,
580- } ] . iter ( ) . cloned ( ) . collect ( ) ,
581- stale_violations : Vec :: new ( ) ,
582- strict_mode_violations : HashSet :: new ( ) ,
583- } ;
584-
585- let expected_output = "2 violation(s) detected:
586- foo/bar/file2.rb:15:3
587- Dependency violation: `::Foo::AnotherClass` is not allowed to depend on `::Bar::SomeClass`
588-
589- foo/bar/file1.rb:10:5
590- Privacy violation: `::Foo::PrivateClass` is private to `foo`, but referenced from `bar`
591-
592- " ;
593-
594- let actual = format ! ( "{}" , check_result) ;
595-
596- assert_eq ! ( actual, expected_output) ;
597- }
598- }
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