1- use log:: { debug, error, info} ;
1+ use anyhow:: Context as _;
2+ use log:: { debug, info} ;
23use std:: process:: Command ;
34use structopt:: StructOpt ;
45use util:: cmd:: { CommandExt , Runner } ;
@@ -38,48 +39,33 @@ fn shellcheck(runner: &Runner) {
3839 }
3940}
4041
41- fn pvs ( runner : & Runner ) {
42- Command :: new ( "pvs-studio-analyzer" )
43- . current_dir ( "./jtl-cpp/cmake-build-debug" )
44- . arg ( "analyze" )
45- . args ( & [ "--exclude-path" , "./jtl-cpp/deps" ] )
46- . args ( & [ "-j" , "4" ] )
47- . run_on ( runner) ;
48-
49- let diagnostics_important = "GA:1,2;64:1,2;OP:1,2,3" ;
50- let diagnostics_additional = "GA:3;64:3" ;
51-
52- let output_type = "errorfile" ;
42+ fn static_analysis ( ) -> anyhow:: Result < ( ) > {
43+ std:: fs:: remove_dir_all ( "jtl-cpp/cmake-build-analysis" ) . ok ( ) ;
44+ std:: fs:: create_dir_all ( "jtl-cpp/cmake-build-analysis" ) ?;
45+ Command :: new ( "scan-build" )
46+ . arg ( cmake_bin ( ) )
47+ . current_dir ( "./jtl-cpp/cmake-build-analysis" )
48+ . arg ( ".." )
49+ . try_exec ( ) ?;
5350
54- let do_convert = |diag_spec : & str , name : & str | {
55- let report_path = format ! ( "./jtl-cpp/cmake-build-debug/pvs-{}" , name) ;
56- std:: fs:: remove_dir_all ( & report_path) . ok ( ) ;
51+ let analysis_output_dir = tempfile:: TempDir :: new ( ) . context ( "failed to get temp dir" ) ?;
5752
58- Command :: new ( "plog-converter" )
59- . current_dir ( "./jtl-cpp/cmake-build-debug" )
60- . args ( & [ "--analyzer" , diag_spec] )
61- . args ( & [ "--renderTypes" , output_type] )
62- . arg ( "PVS-Studio.log" )
63- . args ( & [ "--output" , & format ! ( "pvs-{}" , name) ] )
64- . run_on ( runner) ;
65- println ! ( "---info: PVS report {}---" , name) ;
66- let report_text = std:: fs:: read_to_string ( & report_path)
67- . unwrap_or_else ( |err| format ! ( "failed to read report: {}" , err) ) ;
68- // skip first line which is reference to help
69- let report_text = report_text
70- . splitn ( 2 , '\n' )
71- . nth ( 1 )
72- . map ( str:: to_string)
73- . unwrap_or_default ( ) ;
74- println ! ( "{}\n ---" , report_text) ;
75- !report_text. chars ( ) . any ( |c| !c. is_whitespace ( ) )
76- } ;
53+ Command :: new ( "scan-build" )
54+ . current_dir ( "./jtl-cpp/cmake-build-analysis" )
55+ . arg ( "-o" )
56+ . arg ( & analysis_output_dir. path ( ) )
57+ . arg ( "make" )
58+ . args ( & [ "-j" , "4" ] )
59+ . try_exec ( ) ?;
7760
78- if !do_convert ( diagnostics_important, "high" ) {
79- error ! ( "PVS found some errors" ) ;
80- runner. error ( ) ;
61+ let dir_items = std:: fs:: read_dir ( analysis_output_dir. path ( ) ) ?. count ( ) ;
62+ if dir_items != 0 {
63+ // make sure dir is saved
64+ analysis_output_dir. into_path ( ) ;
65+ anyhow:: bail!( "Analyzer found bugs" ) ;
8166 }
82- do_convert ( diagnostics_additional, "low" ) ;
67+
68+ Ok ( ( ) )
8369}
8470
8571fn check_testlib ( runner : & Runner ) {
@@ -108,9 +94,9 @@ pub struct CheckOpts {
10894 /// Build testlib
10995 #[ structopt( long) ]
11096 testlib : bool ,
111- /// Use PVS-Studio to analyze testlib
97+ /// Analyze testlib
11298 #[ structopt( long) ]
113- pvs : bool ,
99+ clang_analyzer : bool ,
114100 /// Do not run default checks
115101 #[ structopt( long) ]
116102 no_default : bool ,
@@ -119,15 +105,7 @@ pub struct CheckOpts {
119105 pub ( crate ) fail_fast : bool ,
120106}
121107
122- fn secrets_enabled ( ) -> bool {
123- let val = match std:: env:: var ( "SECRET_ENABLED" ) {
124- Ok ( val) => val,
125- Err ( _) => return false , // definitely not a CI
126- } ;
127- !val. trim ( ) . is_empty ( )
128- }
129-
130- pub fn check ( opts : & CheckOpts , runner : & Runner ) {
108+ pub fn check ( opts : & CheckOpts , runner : & Runner ) -> anyhow:: Result < ( ) > {
131109 if opts. autopep8 || !opts. no_default {
132110 autopep8 ( runner) ;
133111 }
@@ -137,9 +115,8 @@ pub fn check(opts: &CheckOpts, runner: &Runner) {
137115 if opts. testlib || !opts. no_default {
138116 check_testlib ( runner) ;
139117 }
140- let force_pvs = std:: env:: var ( "CI" ) . is_ok ( ) && secrets_enabled ( ) ;
141- let force_not_pvs = std:: env:: var ( "CI" ) . is_ok ( ) && !secrets_enabled ( ) ;
142- if ( opts. pvs || force_pvs) && !force_not_pvs {
143- pvs ( runner) ;
118+ if opts. clang_analyzer {
119+ static_analysis ( ) . context ( "static analysis failed" ) ?;
144120 }
121+ Ok ( ( ) )
145122}
0 commit comments