@@ -80,7 +80,7 @@ impl Application {
8080 let event_source = EventFileReader :: try_from ( input) ?;
8181 let semantic_recognition = SemanticRecognition :: try_from ( & config) ?;
8282 let semantic_transform = SemanticTransform :: from ( & config. output ) ;
83- let output_writer = OutputWriter :: configure ( & output, & config. output ) ;
83+ let output_writer = OutputWriter :: configure ( & output, & config. output ) ? ;
8484 let result = Application :: Semantic {
8585 event_source,
8686 semantic_recognition,
@@ -124,7 +124,7 @@ impl Application {
124124 let entries = event_source
125125 . generate ( )
126126 . flat_map ( |execution| semantic_recognition. apply ( execution) )
127- . map ( |semantic| semantic_transform. apply ( semantic) ) ;
127+ . flat_map ( |semantic| semantic_transform. apply ( semantic) ) ;
128128 // Consume the entries and write them to the output file.
129129 // The exit code is based on the result of the output writer.
130130 match output_writer. run ( entries) {
@@ -162,17 +162,16 @@ impl TryFrom<&config::Main> for SemanticRecognition {
162162 _ => vec ! [ ] ,
163163 } ;
164164 let compilers_to_exclude = match & config. output {
165- config:: Output :: Clang { filter , .. } => filter . compilers . with_paths . clone ( ) ,
166- _ => vec ! [ ] ,
167- } ;
168- let arguments_to_exclude = match & config . output {
169- config :: Output :: Clang { filter , .. } => filter . compilers . with_arguments . clone ( ) ,
165+ config:: Output :: Clang { compilers , .. } => compilers
166+ . into_iter ( )
167+ . filter ( |compiler| compiler . ignore == config :: Ignore :: Always )
168+ . map ( |compiler| compiler . path . clone ( ) )
169+ . collect ( ) ,
170170 _ => vec ! [ ] ,
171171 } ;
172172 let tool = semantic:: tools:: Builder :: new ( )
173173 . compilers_to_recognize ( compilers_to_include. as_slice ( ) )
174174 . compilers_to_exclude ( compilers_to_exclude. as_slice ( ) )
175- . compilers_to_exclude_by_arguments ( arguments_to_exclude. as_slice ( ) )
176175 . build ( ) ;
177176
178177 Ok ( SemanticRecognition {
@@ -218,24 +217,18 @@ impl SemanticRecognition {
218217/// Modifies the compiler flags based on the configuration. Ignores non-compiler calls.
219218enum SemanticTransform {
220219 NoTransform ,
221- Transform {
222- arguments_to_add : Vec < String > ,
223- arguments_to_remove : Vec < String > ,
224- } ,
220+ Transform { compilers : Vec < config:: Compiler > } ,
225221}
226222
227223impl From < & config:: Output > for SemanticTransform {
228224 fn from ( config : & config:: Output ) -> Self {
229225 match config {
230- config:: Output :: Clang { transform, .. } => {
231- if transform. arguments_to_add . is_empty ( ) && transform. arguments_to_remove . is_empty ( )
232- {
226+ config:: Output :: Clang { compilers, .. } => {
227+ if compilers. is_empty ( ) {
233228 SemanticTransform :: NoTransform
234229 } else {
235- SemanticTransform :: Transform {
236- arguments_to_add : transform. arguments_to_add . clone ( ) ,
237- arguments_to_remove : transform. arguments_to_remove . clone ( ) ,
238- }
230+ let compilers = compilers. clone ( ) ;
231+ SemanticTransform :: Transform { compilers }
239232 }
240233 }
241234 config:: Output :: Semantic { .. } => SemanticTransform :: NoTransform ,
@@ -244,53 +237,95 @@ impl From<&config::Output> for SemanticTransform {
244237}
245238
246239impl SemanticTransform {
247- fn apply ( & self , input : semantic:: Meaning ) -> semantic:: Meaning {
248- match input {
240+ fn apply ( & self , input : semantic:: Meaning ) -> Option < semantic:: Meaning > {
241+ match & input {
249242 semantic:: Meaning :: Compiler {
250243 compiler,
251- working_dir,
252244 passes,
253- } if matches ! ( self , SemanticTransform :: Transform { .. } ) => {
254- let passes_transformed = passes
255- . into_iter ( )
256- . map ( |pass| self . transform_pass ( pass) )
257- . collect ( ) ;
258-
259- semantic:: Meaning :: Compiler {
260- compiler,
261- working_dir,
262- passes : passes_transformed,
245+ working_dir,
246+ } => match self . lookup ( & compiler) {
247+ Some ( config:: Compiler {
248+ ignore : config:: Ignore :: Always ,
249+ ..
250+ } ) => None ,
251+ Some ( config:: Compiler {
252+ ignore : config:: Ignore :: Conditional ,
253+ arguments,
254+ ..
255+ } ) => {
256+ if Self :: filter ( arguments, passes) {
257+ None
258+ } else {
259+ Some ( input)
260+ }
261+ }
262+ Some ( config:: Compiler {
263+ ignore : config:: Ignore :: Never ,
264+ arguments,
265+ ..
266+ } ) => {
267+ let new_passes = SemanticTransform :: execute ( arguments, passes) ;
268+ Some ( semantic:: Meaning :: Compiler {
269+ compiler : compiler. clone ( ) ,
270+ working_dir : working_dir. clone ( ) ,
271+ passes : new_passes,
272+ } )
263273 }
274+ None => Some ( input) ,
275+ } ,
276+ _ => Some ( input) ,
277+ }
278+ }
279+
280+ // TODO: allow multiple matches for the same compiler
281+ fn lookup ( & self , compiler : & std:: path:: Path ) -> Option < & config:: Compiler > {
282+ match self {
283+ SemanticTransform :: Transform { compilers } => {
284+ compilers. iter ( ) . find ( |c| c. path == compiler)
264285 }
265- _ => input ,
286+ _ => None ,
266287 }
267288 }
268289
269- fn transform_pass ( & self , pass : semantic:: CompilerPass ) -> semantic:: CompilerPass {
270- match pass {
271- semantic:: CompilerPass :: Compile {
272- source,
273- output,
274- flags,
275- } => match self {
276- SemanticTransform :: Transform {
277- arguments_to_add,
278- arguments_to_remove,
290+ fn filter ( arguments : & config:: Arguments , passes : & [ semantic:: CompilerPass ] ) -> bool {
291+ let match_flags = arguments. match_ . as_slice ( ) ;
292+ passes. iter ( ) . any ( |pass| match pass {
293+ semantic:: CompilerPass :: Compile { flags, .. } => {
294+ flags. iter ( ) . any ( |flag| match_flags. contains ( flag) )
295+ }
296+ _ => false ,
297+ } )
298+ }
299+
300+ fn execute (
301+ arguments : & config:: Arguments ,
302+ passes : & [ semantic:: CompilerPass ] ,
303+ ) -> Vec < semantic:: CompilerPass > {
304+ let arguments_to_remove = arguments. remove . as_slice ( ) ;
305+ let arguments_to_add = arguments. add . as_slice ( ) ;
306+
307+ let mut new_passes = Vec :: with_capacity ( passes. len ( ) ) ;
308+ for pass in passes {
309+ match pass {
310+ semantic:: CompilerPass :: Compile {
311+ source,
312+ output,
313+ flags,
279314 } => {
280- let flags_transformed = flags
281- . into_iter ( )
282- . filter ( |flag| !arguments_to_remove. contains ( flag) )
283- . chain ( arguments_to_add. iter ( ) . cloned ( ) )
284- . collect ( ) ;
285- semantic:: CompilerPass :: Compile {
286- source,
287- output,
288- flags : flags_transformed,
289- }
315+ let mut new_flags = flags. clone ( ) ;
316+ new_flags. retain ( |flag| !arguments_to_remove. contains ( flag) ) ;
317+ new_flags. extend ( arguments_to_add. iter ( ) . cloned ( ) ) ;
318+ new_passes. push ( semantic:: CompilerPass :: Compile {
319+ source : source. clone ( ) ,
320+ output : output. clone ( ) ,
321+ flags : new_flags,
322+ } ) ;
290323 }
291- _ => panic ! ( "This is a bug! Please report it to the developers." ) ,
292- } ,
293- _ => pass,
324+ semantic:: CompilerPass :: Preprocess => {
325+ new_passes. push ( semantic:: CompilerPass :: Preprocess )
326+ }
327+ }
294328 }
329+ new_passes
295330 }
296331}
0 commit comments