From 982dd5cc5a65ee97be05b1e936c7acf0dbd7e5b4 Mon Sep 17 00:00:00 2001 From: Patrick Baudin <patrick.baudin@cea.fr> Date: Mon, 27 Feb 2023 11:01:40 +0100 Subject: [PATCH] [Lint] allows to overload ocp-indent commands as for the other known tools --- tools/lint/README.md | 83 ++++++++++++++++++++++++++++++++++++++++++++ tools/lint/lint.ml | 44 +++++++++++++++-------- 2 files changed, 112 insertions(+), 15 deletions(-) create mode 100644 tools/lint/README.md diff --git a/tools/lint/README.md b/tools/lint/README.md new file mode 100644 index 00000000000..b5ab4cfe030 --- /dev/null +++ b/tools/lint/README.md @@ -0,0 +1,83 @@ +## frama-c-lint tool + +## Usage + + +``` +> frama-c-lint -help +Usage: git ls-files -z | git check-attr --stdin -z -a | _build/install/default/bin/frama-c-lint [options] + +Checks or updates files in relation to lint constraints specified by these git attributes: + check-eoleof, check-syntax, check-utf8 and check-indent. + +Options: + --version Prints tool version + -c <json-config-file> Reads the JSON configuration file (allows to overload the default configuration) + -e Prints default JSON configuration + -s Considers warnings as errors for the exit value + -u Update ill-formed files (does not handle UTF8 update) + -v Verbose mode + -help Display this list of options + --help Display this list of options +``` + +## Managed Git Attributes + +The tool manage the following `git` attributes: +`check-eoleof`, `check-syntax`, `check-utf8`, `check-indent`. + +All of them can be `set` or `unset`, but a tool name can also be assignable to the `check-indent` attribute. + +The check/update commands related to `check-eoleof`, `check-syntax` and `check-utf8` attributes are not overloadable and cannot be parametrized. +Only the commands related to `check-indent` attribute can be parametrized. + +## The Parametrizable Configuration + +The command `frama-c-lint -e` pretty prints the JSON description equivalent to the default parametrizable configuration related to `check-indent` attribute. + +``` +> frama-c-lint -e +Default JSON configuration: +[ + { + "kind": "C", + "extensions": [ ".c", ".h" ], + "name": "clang-format", + "available_cmd": "clang-format --version > /dev/null 2> /dev/null", + "check_cmd": "clang-format --dry-run -Werror", + "update_cmd": "clang-format -i" + }, + { + "kind": "Python", + "extensions": [ ".py" ], + "name": "black", + "available_cmd": "black --version > /dev/null 2> /dev/null", + "check_cmd": "black --quiet --line-length 100 --check", + "update_cmd": "black --quiet --line-length 100" + } +] +``` + +This description defines `black` and `clang-format` as the assignable values of the `git` attribute `check-indent`. It also specifies the system command to use for checking the availability of the tool to use for checking/updating the indentation. The check and update commands are also specified. + +When the `check-indent` attribute is set without a value, the description specifies the tool to use from the extension of the file to check/update. + +There is also a built-in configuration for `.ml` and `.mli` files based of `ocp-indent` tool (from a directly use of `ocp-indent` library to improve the efficiency of the tool) that can be overloaded if necessary. +That means there is an implicit overloadable JSON description: +``` +[ + { + "kind": "OCaml", + "extensions": [ ".ml", ".mli" ], + "name": "ocp-indent", + "available_cmd": "...", + "check_cmd": "...", + "update_cmd": "..." + } +] +``` + +The option `-c <json-confi g-file>` allows to extend and/or overload the default configuration. + +When the `available_cmd` field is set to an empty string, that disable the check/update with the related tool. +An empty string can also be set to the field `check_cmd` (resp. `update_cmd`) when the related tool does not offer check (resp. update) command. diff --git a/tools/lint/lint.ml b/tools/lint/lint.ml index 919aadb4b4a..e08be5eb782 100644 --- a/tools/lint/lint.ml +++ b/tools/lint/lint.ml @@ -134,7 +134,7 @@ let parse_config config_file = in match config_tools with | Result.Ok external_tools -> updates_tbl external_tools | Result.Error txt -> - warn "Parse error:%s:%s" config_file txt + warn "Parse error:%s:%s@." config_file txt (************************) @@ -145,13 +145,15 @@ type indent_check = NoCheck | Check of indent_formatter option let parse_indent_formatter ~file ~attr ~value = match value with | "unset" -> NoCheck | "set" -> Check None (* use the default formatter *) - | "ocp-indent" -> Check (Some ml_indent_formatter) | _ -> match Hashtbl.find_opt external_tbl value with | None -> - warn "Unsupported indent formatter: %s %s=%s@." - file attr value; - NoCheck + if value = "ocp-indent" then + (* "ocp-indent" is not overloaded: using the built-in configuration *) + Check (Some ml_indent_formatter) + else (warn "Unsupported indent formatter: %s %s=%s@." + file attr value; + NoCheck) | res -> Check res (**************************************************************************) @@ -175,7 +177,7 @@ let add_attr ~file ~attr ~value checks = let is_set = function | "set" -> true | "unset" -> false - | _ -> warn "Invalid attribute value: %s %s=%s" file attr value ; false + | _ -> warn "Invalid attribute value: %s %s=%s@." file attr value ; false in match attr with | "check-eoleof" -> { checks with eoleof = is_set value } @@ -183,7 +185,7 @@ let add_attr ~file ~attr ~value checks = | "check-utf8" -> { checks with utf8 = is_set value } | "check-indent" -> { checks with indent = parse_indent_formatter ~file ~attr ~value } - | _ -> warn "Unknown attribute: %s %s=%s" file attr value; + | _ -> warn "Unknown attribute: %s %s=%s@." file attr value; checks let handled_attr s = @@ -344,11 +346,12 @@ let check_indent ~indent_formatter ~update file = let tool = match indent_formatter with | Some tool -> tool | None -> (* uses the default formatter *) - match Filename.extension file with - | ".ml" | ".mli" -> ml_indent_formatter - | extension -> match Hashtbl.find_opt default_tbl extension with - | None -> raise Bad_ext - | Some tool -> tool + let extension = Filename.extension file in + match Hashtbl.find_opt default_tbl extension with + | Some tool -> tool + | None -> match extension with + | ".ml" | ".mli" -> ml_indent_formatter + | _ -> raise Bad_ext in match tool with | Ocp_indent -> check_ml_indent ~update file | Tool indent_formatter -> @@ -419,6 +422,13 @@ let check ~verbose ~update file params = (* Options *) let exec_name = Sys.argv.(0) + +let version= "1.0" + +let version () = + Format.printf "%s version %s@." (Filename.basename exec_name) version; + exit 0 + let update = ref false let verbose = ref false let config_file = ref "" @@ -428,8 +438,9 @@ let argspec = [ "-u", Arg.Set update, " Update ill-formed files (does not handle UTF8 update)" ; "-v", Arg.Set verbose, " Verbose mode" ; "-s", Arg.Set strict, " Considers warnings as errors for the exit value" ; - "-c", Arg.String (fun s -> config_file := s), "<config-file> Reads the JSON configuration file (allows to overload the default configuration)" ; - "-e", Arg.Set extract_config, " Print default JSON configuration" ; + "-c", Arg.String (fun s -> config_file := s), "<json-config-file> Reads the JSON configuration file (allows to overload the default configuration)" ; + "-e", Arg.Set extract_config, " Prints default JSON configuration" ; + "--version", Arg.Unit version, " Prints tool version" ; ] let sort argspec = List.sort (fun (name1, _, _) (name2, _, _) -> String.compare name1 name2) @@ -442,7 +453,10 @@ let () = Arg.parse (Arg.align (sort argspec)) (fun s -> warn "Unknown argument: %s@." s) - ("Usage: git ls-files -z | git check-attr --stdin -z -a | " ^ exec_name ^ " [options]"); + ("Usage: git ls-files -z | git check-attr --stdin -z -a | " ^ exec_name ^ " [options]\n" + ^"\nChecks or updates files in relation to lint constraints specified by these git attributes:\n" + ^" check-eoleof, check-syntax, check-utf8 and check-indent.\n" + ^"\nOptions:"); if !extract_config then Format.printf "Default JSON configuration:@.%a@." (Yojson.Safe.pretty_print ~std:false) (tools_to_yojson external_formatters) -- GitLab