@@ -26,7 +26,10 @@ pub fn build_preamble(fs: &FeatureSet, command_line: &str) -> String {
2626 lines. push ( format ! ( " * {command_line}" ) ) ;
2727
2828 // ---- Extension provenance ----
29- if !fs. extensions . is_empty ( ) {
29+ if !fs. extensions . is_empty ( )
30+ || !fs. excluded_explicit . is_empty ( )
31+ || !fs. excluded_baseline . is_empty ( )
32+ {
3033 lines. push ( " *" . to_string ( ) ) ;
3134 lines. push ( format ! ( " * {}" , extension_summary( fs) ) ) ;
3235
@@ -47,6 +50,20 @@ pub fn build_preamble(fs: &FeatureSet, command_line: &str) -> String {
4750 lines. push ( format ! ( " * {}: {}" , label, names. join( ", " ) ) ) ;
4851 }
4952 }
53+
54+ // List excluded extensions.
55+ if !fs. excluded_baseline . is_empty ( ) {
56+ lines. push ( format ! (
57+ " * excluded by baseline: {} extensions" ,
58+ fs. excluded_baseline. len( )
59+ ) ) ;
60+ }
61+ if !fs. excluded_explicit . is_empty ( ) {
62+ lines. push ( format ! (
63+ " * excluded explicitly: {}" ,
64+ fs. excluded_explicit. join( ", " )
65+ ) ) ;
66+ }
5067 }
5168
5269 // ---- gloam license ----
@@ -81,11 +98,13 @@ pub fn build_preamble(fs: &FeatureSet, command_line: &str) -> String {
8198/// Build a one-line summary of extension selection.
8299///
83100/// Examples:
84- /// "Extensions: all (451 total )"
85- /// "Extensions: 5 explicit, 12 promoted , 3 predecessor (20 total )"
86- /// "Extensions: 2 mandatory, 5 explicit (7 total )"
101+ /// "Extensions: all (451 included )"
102+ /// "Extensions: all, 68 excluded by baseline , 3 excluded explicitly (380 included )"
103+ /// "Extensions: 5 explicit, 12 promoted, 3 predecessor (20 included )"
87104fn extension_summary ( fs : & FeatureSet ) -> String {
88105 let total = fs. extensions . len ( ) ;
106+ let n_baseline_excluded = fs. excluded_baseline . len ( ) ;
107+ let n_explicit_excluded = fs. excluded_explicit . len ( ) ;
89108
90109 let count = |reason : SelectionReason | -> usize {
91110 fs. extensions . iter ( ) . filter ( |e| e. reason == reason) . count ( )
@@ -98,29 +117,37 @@ fn extension_summary(fs: &FeatureSet) -> String {
98117 let n_promoted = count ( SelectionReason :: Promoted ) ;
99118 let n_predecessor = count ( SelectionReason :: Predecessor ) ;
100119
120+ let mut parts: Vec < String > = Vec :: new ( ) ;
121+
101122 // If everything came from "all extensions" (no filter), use the short form.
102123 if n_all + n_mandatory == total {
103- return format ! ( "Extensions: all ({total} total)" ) ;
124+ parts. push ( "all" . to_string ( ) ) ;
125+ } else {
126+ if n_explicit > 0 {
127+ parts. push ( format ! ( "{n_explicit} explicit" ) ) ;
128+ }
129+ if n_mandatory > 0 {
130+ parts. push ( format ! ( "{n_mandatory} mandatory" ) ) ;
131+ }
132+ if n_dependency > 0 {
133+ parts. push ( format ! ( "{n_dependency} dependency" ) ) ;
134+ }
135+ if n_promoted > 0 {
136+ parts. push ( format ! ( "{n_promoted} promoted" ) ) ;
137+ }
138+ if n_predecessor > 0 {
139+ parts. push ( format ! ( "{n_predecessor} predecessor" ) ) ;
140+ }
104141 }
105142
106- let mut parts: Vec < String > = Vec :: new ( ) ;
107- if n_explicit > 0 {
108- parts. push ( format ! ( "{n_explicit} explicit" ) ) ;
109- }
110- if n_mandatory > 0 {
111- parts. push ( format ! ( "{n_mandatory} mandatory" ) ) ;
112- }
113- if n_dependency > 0 {
114- parts. push ( format ! ( "{n_dependency} dependency" ) ) ;
143+ if n_baseline_excluded > 0 {
144+ parts. push ( format ! ( "{n_baseline_excluded} excluded by baseline" ) ) ;
115145 }
116- if n_promoted > 0 {
117- parts. push ( format ! ( "{n_promoted} promoted" ) ) ;
118- }
119- if n_predecessor > 0 {
120- parts. push ( format ! ( "{n_predecessor} predecessor" ) ) ;
146+ if n_explicit_excluded > 0 {
147+ parts. push ( format ! ( "{n_explicit_excluded} excluded explicitly" ) ) ;
121148 }
122149
123- format ! ( "Extensions: {} ({total} total )" , parts. join( ", " ) )
150+ format ! ( "Extensions: {} ({total} included )" , parts. join( ", " ) )
124151}
125152
126153/// Returns true if this feature set includes ANGLE extension supplementals.
@@ -155,6 +182,8 @@ mod tests {
155182 ext_subset_indices : Default :: default ( ) ,
156183 alias_pairs : vec ! [ ] ,
157184 required_headers : vec ! [ ] ,
185+ excluded_explicit : vec ! [ ] ,
186+ excluded_baseline : vec ! [ ] ,
158187 }
159188 }
160189
@@ -255,7 +284,7 @@ mod tests {
255284 stub_ext( "VK_KHR_swapchain" , SelectionReason :: AllExtensions ) ,
256285 stub_ext( "VK_KHR_surface" , SelectionReason :: AllExtensions ) ,
257286 ] ;
258- assert_eq ! ( extension_summary( & fs) , "Extensions: all (2 total )" ) ;
287+ assert_eq ! ( extension_summary( & fs) , "Extensions: all (2 included )" ) ;
259288 }
260289
261290 #[ test]
@@ -265,7 +294,7 @@ mod tests {
265294 stub_ext( "WGL_ARB_extensions_string" , SelectionReason :: Mandatory ) ,
266295 stub_ext( "WGL_ARB_pixel_format" , SelectionReason :: AllExtensions ) ,
267296 ] ;
268- assert_eq ! ( extension_summary( & fs) , "Extensions: all (2 total )" ) ;
297+ assert_eq ! ( extension_summary( & fs) , "Extensions: all (2 included )" ) ;
269298 }
270299
271300 #[ test]
@@ -275,7 +304,10 @@ mod tests {
275304 stub_ext( "VK_KHR_swapchain" , SelectionReason :: Explicit ) ,
276305 stub_ext( "VK_KHR_surface" , SelectionReason :: Explicit ) ,
277306 ] ;
278- assert_eq ! ( extension_summary( & fs) , "Extensions: 2 explicit (2 total)" ) ;
307+ assert_eq ! (
308+ extension_summary( & fs) ,
309+ "Extensions: 2 explicit (2 included)"
310+ ) ;
279311 }
280312
281313 #[ test]
@@ -292,7 +324,7 @@ mod tests {
292324 ] ;
293325 assert_eq ! (
294326 extension_summary( & fs) ,
295- "Extensions: 1 explicit, 2 promoted, 1 predecessor (4 total )"
327+ "Extensions: 1 explicit, 2 promoted, 1 predecessor (4 included )"
296328 ) ;
297329 }
298330
@@ -341,7 +373,7 @@ mod tests {
341373 ] ;
342374 assert_eq ! (
343375 extension_summary( & fs) ,
344- "Extensions: 1 explicit, 1 dependency (2 total )"
376+ "Extensions: 1 explicit, 1 dependency (2 included )"
345377 ) ;
346378 }
347379
@@ -351,4 +383,64 @@ mod tests {
351383 let p = build_preamble ( & fs, "gloam --api vk=1.3 c" ) ;
352384 assert ! ( !p. contains( "Extensions:" ) ) ;
353385 }
386+
387+ // ---- Exclusion display ----
388+
389+ #[ test]
390+ fn summary_with_baseline_exclusions ( ) {
391+ let mut fs = stub_fs ( "gl" ) ;
392+ fs. extensions = vec ! [ stub_ext( "GL_KHR_debug" , SelectionReason :: AllExtensions ) ] ;
393+ fs. excluded_baseline = vec ! [
394+ "GL_ARB_copy_buffer" . to_string( ) ,
395+ "GL_ARB_multitexture" . to_string( ) ,
396+ ] ;
397+ assert_eq ! (
398+ extension_summary( & fs) ,
399+ "Extensions: all, 2 excluded by baseline (1 included)"
400+ ) ;
401+ }
402+
403+ #[ test]
404+ fn summary_with_explicit_exclusions ( ) {
405+ let mut fs = stub_fs ( "gl" ) ;
406+ fs. extensions = vec ! [ stub_ext( "GL_KHR_debug" , SelectionReason :: AllExtensions ) ] ;
407+ fs. excluded_explicit = vec ! [ "GL_EXT_direct_state_access" . to_string( ) ] ;
408+ assert_eq ! (
409+ extension_summary( & fs) ,
410+ "Extensions: all, 1 excluded explicitly (1 included)"
411+ ) ;
412+ }
413+
414+ #[ test]
415+ fn summary_with_both_exclusion_types ( ) {
416+ let mut fs = stub_fs ( "gl" ) ;
417+ fs. extensions = vec ! [ stub_ext( "GL_KHR_debug" , SelectionReason :: AllExtensions ) ] ;
418+ fs. excluded_baseline = vec ! [ "GL_ARB_copy_buffer" . to_string( ) ] ;
419+ fs. excluded_explicit = vec ! [ "GL_EXT_direct_state_access" . to_string( ) ] ;
420+ assert_eq ! (
421+ extension_summary( & fs) ,
422+ "Extensions: all, 1 excluded by baseline, 1 excluded explicitly (1 included)"
423+ ) ;
424+ }
425+
426+ #[ test]
427+ fn preamble_shows_baseline_exclusion_count ( ) {
428+ let mut fs = stub_fs ( "gl" ) ;
429+ fs. extensions = vec ! [ stub_ext( "GL_KHR_debug" , SelectionReason :: AllExtensions ) ] ;
430+ fs. excluded_baseline = vec ! [
431+ "GL_ARB_copy_buffer" . to_string( ) ,
432+ "GL_ARB_multitexture" . to_string( ) ,
433+ ] ;
434+ let p = build_preamble ( & fs, "gloam --api gl:core c" ) ;
435+ assert ! ( p. contains( "excluded by baseline: 2 extensions" ) ) ;
436+ }
437+
438+ #[ test]
439+ fn preamble_shows_explicit_exclusion_names ( ) {
440+ let mut fs = stub_fs ( "gl" ) ;
441+ fs. extensions = vec ! [ stub_ext( "GL_KHR_debug" , SelectionReason :: AllExtensions ) ] ;
442+ fs. excluded_explicit = vec ! [ "GL_EXT_direct_state_access" . to_string( ) ] ;
443+ let p = build_preamble ( & fs, "gloam --api gl:core c" ) ;
444+ assert ! ( p. contains( "excluded explicitly: GL_EXT_direct_state_access" ) ) ;
445+ }
354446}
0 commit comments