@@ -381,6 +381,8 @@ func (e *Executor) setExitCodeIfIssuesFound(issues []result.Issue) {
381381 }
382382}
383383
384+ const defaultFileMode = 0644
385+
384386func (e * Executor ) runAndPrint (ctx context.Context , args []string ) error {
385387 if err := e .goenv .Discover (ctx ); err != nil {
386388 e .log .Warnf ("Failed to discover go env: %s" , err )
@@ -400,44 +402,77 @@ func (e *Executor) runAndPrint(ctx context.Context, args []string) error {
400402 return err // XXX: don't loose type
401403 }
402404
403- p , err := e .createPrinter ()
404- if err != nil {
405- return err
405+ formats := strings .Split (e .cfg .Output .Format , "," )
406+ for _ , format := range formats {
407+ out := strings .SplitN (format , ":" , 2 )
408+ if len (out ) < 2 {
409+ out = append (out , "" )
410+ }
411+ w , shouldClose , err := e .createWriter (out [1 ])
412+ if err != nil {
413+ return fmt .Errorf ("can't create output for %s: %w" , out [1 ], err )
414+ }
415+
416+ p , err := e .createPrinter (out [0 ], w )
417+ if err != nil {
418+ if file , ok := w .(io.Closer ); shouldClose && ok {
419+ file .Close ()
420+ }
421+ return err
422+ }
423+ if err = p .Print (ctx , issues ); err != nil {
424+ if file , ok := w .(io.Closer ); shouldClose && ok {
425+ file .Close ()
426+ }
427+ return fmt .Errorf ("can't print %d issues: %s" , len (issues ), err )
428+ }
429+ if file , ok := w .(io.Closer ); shouldClose && ok {
430+ file .Close ()
431+ }
406432 }
407433
408434 e .setExitCodeIfIssuesFound (issues )
409435
410- if err = p .Print (ctx , issues ); err != nil {
411- return fmt .Errorf ("can't print %d issues: %s" , len (issues ), err )
412- }
413-
414436 e .fileCache .PrintStats (e .log )
415437
416438 return nil
417439}
418440
419- func (e * Executor ) createPrinter () (printers.Printer , error ) {
441+ func (e * Executor ) createWriter (path string ) (io.Writer , bool , error ) {
442+ if path == "stdout" {
443+ return logutils .StdOut , false , nil
444+ }
445+ if path == "stderr" {
446+ return logutils .StdErr , false , nil
447+ }
448+ f , err := os .OpenFile (path , os .O_CREATE | os .O_TRUNC | os .O_WRONLY , defaultFileMode )
449+ if err != nil {
450+ return nil , false , err
451+ }
452+ return f , true , nil
453+ }
454+
455+ func (e * Executor ) createPrinter (format string , w io.Writer ) (printers.Printer , error ) {
420456 var p printers.Printer
421- format := e .cfg .Output .Format
422457 switch format {
423458 case config .OutFormatJSON :
424- p = printers .NewJSON (& e .reportData )
459+ p = printers .NewJSON (& e .reportData , w )
425460 case config .OutFormatColoredLineNumber , config .OutFormatLineNumber :
426461 p = printers .NewText (e .cfg .Output .PrintIssuedLine ,
427462 format == config .OutFormatColoredLineNumber , e .cfg .Output .PrintLinterName ,
428- e .log .Child ("text_printer" ))
463+ e .log .Child ("text_printer" ), w )
429464 case config .OutFormatTab :
430- p = printers .NewTab (e .cfg .Output .PrintLinterName , e .log .Child ("tab_printer" ))
465+ p = printers .NewTab (e .cfg .Output .PrintLinterName , e .log .Child ("tab_printer" ), w )
431466 case config .OutFormatCheckstyle :
432- p = printers .NewCheckstyle ()
467+ p = printers .NewCheckstyle (w )
433468 case config .OutFormatCodeClimate :
434- p = printers .NewCodeClimate ()
469+ p = printers .NewCodeClimate (w )
435470 case config .OutFormatHTML :
436- p = printers .NewHTML ()
471+ p = printers .NewHTML (w )
437472 case config .OutFormatJunitXML :
438- p = printers .NewJunitXML ()
473+ p = printers .NewJunitXML (w )
439474 case config .OutFormatGithubActions :
440- p = printers .NewGithub ()
475+ p = printers .NewGithub (w )
441476 default :
442477 return nil , fmt .Errorf ("unknown output format %s" , format )
443478 }
0 commit comments