[AL] add `--linters-validate-syntax-only` to check whether there are any syntax errors in AL files

Summary: In case of syntax errors in AL files, stdout will contain a JSON list with all files affected by the errors, including info like filename and line number.

Reviewed By: dulmarod, jvillard

Differential Revision: D5640272

fbshipit-source-id: 569b16d
master
Martino Luca 7 years ago committed by Facebook Github Bot
parent 3576f2f7cc
commit e8a0599850

@ -77,6 +77,12 @@ let setup_results_dir () =
-> assert_results_dir "please run an infer analysis first"
let () =
( if Config.linters_validate_syntax_only then
match CTLParserHelper.validate_al_files () with
| Ok ()
-> exit 0
| Error e
-> print_endline e ; exit 3 ) ;
if Config.print_builtins then Builtin.print_and_exit () ;
setup_results_dir () ;
if Config.debug_mode then L.progress "Logs in %s@." (Config.results_dir ^/ Config.log_file) ;

@ -1252,6 +1252,12 @@ and linters_ignore_clang_failures =
~in_help:CLOpt.([(Capture, manual_clang_linters)])
~default:false "Continue linting files even if some compilation fails."
and linters_validate_syntax_only =
CLOpt.mk_bool ~long:"linters-validate-syntax-only"
~in_help:CLOpt.([(Capture, manual_clang_linters)])
~default:false
"Validate syntax of AL files, then emit possible errors in JSON format to stdout"
and load_average =
CLOpt.mk_float_opt ~long:"load-average" ~short:'l'
~in_help:CLOpt.([(Capture, manual_generic)])
@ -2065,6 +2071,8 @@ and linters_developer_mode = !linters_developer_mode
and linters_ignore_clang_failures = !linters_ignore_clang_failures
and linters_validate_syntax_only = !linters_validate_syntax_only
and liveness = !liveness
and load_average =

@ -475,6 +475,8 @@ val linters_developer_mode : bool
val linters_ignore_clang_failures : bool
val linters_validate_syntax_only : bool
val liveness : bool
val load_analysis_results : string option

@ -20,6 +20,12 @@ let create_exc_info description lexbuf =
let pos = lexbuf.Lexing.lex_curr_p in
{description; filename= pos.pos_fname; line= pos.pos_lnum}
let json_of_exc_info exc_info =
`Assoc
[ ("description", `String exc_info.description)
; ("filename", `String exc_info.filename)
; ("line", `Int exc_info.line) ]
let () =
Caml.Printexc.register_printer (fun exc ->
match exc with

@ -21,3 +21,5 @@ val create_exc_info : string -> Lexing.lexbuf -> exc_info
val hum_string_of_exc_info : exc_info -> string
(** human-readable version of exc_info *)
val json_of_exc_info : exc_info -> Yojson.Basic.json

@ -0,0 +1,37 @@
(*
* Copyright (c) 2017 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
open Ctl_lexer
open Lexing
let parse_al_file fname channel =
let parse_with_error lexbuf =
try Some (Ctl_parser.al_file token lexbuf) with
| CTLExceptions.ALParserInvariantViolationException s
-> raise CTLExceptions.(ALFileException (create_exc_info s lexbuf))
| SyntaxError _ | Ctl_parser.Error
-> raise CTLExceptions.(ALFileException (create_exc_info "SYNTAX ERROR" lexbuf))
in
let lexbuf = Lexing.from_channel channel in
lexbuf.lex_curr_p <- {lexbuf.lex_curr_p with pos_fname= fname} ;
parse_with_error lexbuf
let validate_al_files () =
let validate_al_file fname =
try
Utils.with_file_in ~f:(parse_al_file fname) fname |> ignore ;
None
with CTLExceptions.ALFileException exc_info -> Some (CTLExceptions.json_of_exc_info exc_info)
in
match List.filter_map ~f:validate_al_file Config.linters_def_file with
| []
-> Ok ()
| _ as errors
-> Error (Yojson.Basic.to_string (`List errors))

@ -0,0 +1,14 @@
(*
* Copyright (c) 2017 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
val parse_al_file : string -> In_channel.t -> CTL.al_file option
val validate_al_files : unit -> (unit, string) Result.t

@ -8,29 +8,15 @@
*)
open! IStd
open Lexing
open Ctl_lexer
module L = Logging
let parse_al_file fname channel : CTL.al_file option =
let parse_with_error lexbuf =
try Some (Ctl_parser.al_file token lexbuf) with
| CTLExceptions.ALParserInvariantViolationException s
-> raise CTLExceptions.(ALFileException (create_exc_info s lexbuf))
| SyntaxError _ | Ctl_parser.Error
-> raise CTLExceptions.(ALFileException (create_exc_info "SYNTAX ERROR" lexbuf))
in
let lexbuf = Lexing.from_channel channel in
lexbuf.lex_curr_p <- {lexbuf.lex_curr_p with pos_fname= fname} ;
parse_with_error lexbuf
let already_imported_files = ref []
let rec parse_import_file import_file channel =
if List.mem ~equal:String.equal !already_imported_files import_file then
failwith ("Cyclic imports: file '" ^ import_file ^ "' was already imported.")
else
match parse_al_file import_file channel with
match CTLParserHelper.parse_al_file import_file channel with
| Some
{ import_files= imports
; global_macros= curr_file_macros
@ -63,7 +49,7 @@ and parse_imports imports_files =
List.fold_right ~f:parse_one_import_file ~init:([], []) imports_files
let parse_ctl_file linters_def_file channel : CFrontend_errors.linter list =
match parse_al_file linters_def_file channel with
match CTLParserHelper.parse_al_file linters_def_file channel with
| Some
{ import_files= imports
; global_macros= curr_file_macros

@ -0,0 +1,10 @@
(*
* Copyright (c) 2017 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
let validate_al_files () = prerr_endline "ERROR: infer was built without clang support." ; exit 1

@ -0,0 +1,12 @@
(*
* Copyright (c) 2016 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
val validate_al_files : unit -> (unit, string) Result.t
Loading…
Cancel
Save