@@ -37,7 +37,6 @@ impl SemanticCheck for Transition<'_> {
37
37
38
38
// WARNING: don't insert anything since the insertion is already done in analyze_error >-down-to-> check_error
39
39
Ok ( self . at . as_ref ( ) . and_then ( |event| {
40
- // FIXME: not working on auto-transition
41
40
let has_same_event = t_cache
42
41
. keys ( )
43
42
. filter ( |& key| key != & Some ( event. into ( ) ) )
@@ -53,6 +52,7 @@ impl SemanticCheck for Transition<'_> {
53
52
}
54
53
}
55
54
55
+ // WARNING: not performant because of using concatenated String as a key which cause filtering
56
56
impl From < & Event < ' _ > > for String {
57
57
fn from ( event : & Event < ' _ > ) -> Self {
58
58
format ! ( "{}?{}" , event. name. unwrap_or( "" ) , event. guard. unwrap_or( "" ) )
@@ -83,12 +83,26 @@ trait EventKey<'i>: Into<Option<&'i String>> {
83
83
. filter ( |e| none_empty ( e. split ( '?' ) ) == guard)
84
84
. and_then ( |e| none_empty ( e. rsplit ( '?' ) ) )
85
85
}
86
+ fn as_expression ( self ) -> String {
87
+ self . into ( ) . map ( String :: as_str) . as_expression ( )
88
+ }
86
89
}
87
90
88
91
impl < ' o > Trigger < ' o > for & ' o Option < & ' o str > { }
89
92
trait Trigger < ' o > : Into < Option < & ' o & ' o str > > {
90
93
fn as_expression ( self ) -> String {
91
- self . into ( ) . map ( |s| " @ " . to_owned ( ) + & s) . unwrap_or_default ( )
94
+ self . into ( )
95
+ . map ( |s| {
96
+ format ! (
97
+ " @ {trigger}{guard}" ,
98
+ trigger = none_empty( s. rsplit( '?' ) ) . unwrap_or_default( ) ,
99
+ guard = none_empty( s. split( '?' ) )
100
+ . filter( |_| s. contains( '?' ) )
101
+ . map( |g| format!( "[{}]" , g) )
102
+ . unwrap_or_default( ) ,
103
+ )
104
+ } )
105
+ . unwrap_or_default ( )
92
106
}
93
107
fn as_key ( self , guard : & str ) -> Option < String > {
94
108
Some ( format ! ( "{}?{}" , self . into( ) . unwrap_or( & "" ) , guard) )
@@ -154,7 +168,7 @@ impl Transition<'_> {
154
168
trigger
155
169
) ,
156
170
None => format ! (
157
- "duplicate transient transition: {} -> {},{}" ,
171
+ "duplicate transient- transition: {} -> {},{}" ,
158
172
self . from. name,
159
173
self . to. as_ref( ) . unwrap_or( & self . from) . name,
160
174
prev_target
@@ -163,31 +177,33 @@ impl Transition<'_> {
163
177
}
164
178
165
179
fn warn_conflict ( & self , cache : & CacheMap ) -> String {
180
+ const REASON : & str = "never had a chance to trigger" ;
166
181
match & self . at {
167
- Some ( _) => {
168
- let prev_target = cache. get ( & None ) . expect ( "cache without trigger" ) ;
169
- format ! ( "conflict with: {} -> {}" , self . from. name, prev_target)
182
+ Some ( event) => {
183
+ let ( prev_target, trigger) = (
184
+ cache. get ( & None ) . expect ( "cache without trigger" ) ,
185
+ event. name . expect ( "not auto-transition" ) ,
186
+ ) ;
187
+ format ! ( "{} {} because: {} -> {}" , trigger, REASON , self . from. name, prev_target)
170
188
}
171
189
None => {
172
- let prev_targets : Vec < & str > = cache
173
- . iter ( )
174
- . filter_map ( | ( trigger , target ) | trigger . as_ref ( ) . and ( Some ( target . as_str ( ) ) ) )
175
- . collect ( ) ;
176
- let prev_triggers : Vec < String > = cache . keys ( ) . filter_map ( ToOwned :: to_owned ) . collect ( ) ;
177
- format ! (
178
- "conflict with: {} -> {} @ {}" ,
179
- self . from . name ,
180
- prev_targets . join ( "," ) ,
181
- prev_triggers . join( "," )
182
- )
190
+ let caches = cache. iter ( ) . filter ( | ( event , _ ) | event . has_trigger ( ) ) ;
191
+
192
+ let mut messages = format ! ( "conflict with {} {{ \n " , self . from . name ) ;
193
+ for ( event , target ) in caches . clone ( ) {
194
+ writeln ! ( & mut messages , " \t -> {}{}" , target , event . as_expression ( ) ) . expect ( "utf-8" ) ;
195
+ }
196
+ messages += " }" ;
197
+
198
+ let triggers = caches . filter_map ( | ( event , _ ) | event . get_trigger ( ) ) . collect :: < Vec < & str > > ( ) ;
199
+ write ! ( & mut messages , " \n because {} {}" , triggers . join( "," ) , REASON ) . expect ( "utf-8" ) ;
200
+ messages
183
201
}
184
202
}
185
203
}
186
204
187
- // WARNING: not performant because of using concatenated String as a key which cause to filter
188
205
fn warn_nondeterministic ( & self , cache : & CacheMap ) -> String {
189
206
let mut messages = String :: from ( "non-deterministic transition of " ) ;
190
- // (trigger, guard) = (rsplit('?'), split('?')) each call .last()
191
207
match & self . at {
192
208
Some ( event) => {
193
209
let guards = cache. keys ( ) . filter_map ( |k| k. guards_with_same_trigger ( event. name ) ) ;
0 commit comments