diff options
author | Chimrod <> | 2023-11-02 17:35:49 +0100 |
---|---|---|
committer | Chimrod <> | 2023-11-02 19:39:33 +0100 |
commit | fd02a44392304986a756e7d06f8142538b386529 (patch) | |
tree | 87fe05ab02eecee8b2c8cc89ed5fa2c8b83d9771 | |
parent | 05f74bee05c0c56da593a5e89069711d5993e3b1 (diff) |
Added a new checkers for unecessary use of strig containing an escaped expression
-rw-r--r-- | bin/qsp_parser.ml | 10 | ||||
-rw-r--r-- | lib/syntax/nested_strings.ml | 109 | ||||
-rw-r--r-- | lib/syntax/nested_strings.mli | 1 | ||||
-rw-r--r-- | readme.md | 6 | ||||
-rw-r--r-- | test/nested_string.ml | 27 | ||||
-rw-r--r-- | test/qsp_parser_test.ml | 7 |
6 files changed, 155 insertions, 5 deletions
diff --git a/bin/qsp_parser.ml b/bin/qsp_parser.ml index cf64fed..397b5a9 100644 --- a/bin/qsp_parser.ml +++ b/bin/qsp_parser.ml @@ -17,11 +17,13 @@ type ctx = { error_nb : int; warn_nb : int; debug_nb : int } (* List all the controls to apply *) -let _, e1 = Qsp_syntax.Check.build (module Qsp_syntax.Type_of) -let _, e2 = Qsp_syntax.Check.build (module Qsp_syntax.Dead_end) - module Check = Qsp_syntax.Check.Make (struct - let t = [| e1; e2 |] + let t = + [| + snd @@ Qsp_syntax.Check.build (module Qsp_syntax.Type_of); + snd @@ Qsp_syntax.Check.build (module Qsp_syntax.Dead_end); + snd @@ Qsp_syntax.Check.build (module Qsp_syntax.Nested_strings); + |] end) (** Read the source file until getting a report (the whole location has been diff --git a/lib/syntax/nested_strings.ml b/lib/syntax/nested_strings.ml new file mode 100644 index 0000000..fb056d6 --- /dev/null +++ b/lib/syntax/nested_strings.ml @@ -0,0 +1,109 @@ +open StdLabels + +module Expression : S.Expression with type t' = Report.t list = struct + type t = Report.t list + type t' = t + + let v : t -> t' = Fun.id + + (** Identify the expressions reprented as string. That’s here that the report + are added. + + All the rest of the module only push thoses warning to the top level. *) + let literal : S.pos -> t T.literal list -> t = + fun pos content -> + match content with + | [ T.Expression expr; T.Text "" ] -> + ignore expr; + let msg = Report.debug pos "This expression can be simplified" in + [ msg ] + | _ -> [] + + let ident : (S.pos, t) S.variable -> t = + fun { pos; name : string; index : t option } -> + ignore pos; + ignore name; + match index with None -> [] | Some v -> v + + let integer : S.pos -> string -> t = fun _ _ -> [] + + let function_ : S.pos -> T.function_ -> t list -> t = + fun _ _ expressions -> List.concat expressions + + let uoperator : S.pos -> T.uoperator -> t -> t = fun _ _ expr1 -> expr1 + + let boperator : S.pos -> T.boperator -> t -> t -> t = + fun _ _ expr1 expr2 -> expr1 @ expr2 +end + +module Instruction : + S.Instruction with type t' = Report.t list and type expression = Expression.t' = +struct + type t = Report.t list + (** Internal type used in the evaluation *) + + type t' = t + + let v : t -> t' = Fun.id + + type expression = Expression.t' + + let call : S.pos -> T.keywords -> expression list -> t = + fun pos k exprs -> + ignore pos; + ignore k; + List.concat exprs + + let location : S.pos -> string -> t = fun _ _ -> [] + let comment : S.pos -> t = fun _ -> [] + let expression : expression -> t = Fun.id + + let act : S.pos -> label:expression -> t list -> t = + fun pos ~label instructions -> + ignore pos; + List.concat (label :: instructions) + + let fold_clause : (expression, t) S.clause -> t = + fun (_pos1, expression, ts) -> List.concat (expression :: ts) + + let if_ : + S.pos -> + (expression, t) S.clause -> + elifs:(expression, t) S.clause list -> + else_:(S.pos * t list) option -> + t = + fun pos clause ~elifs ~else_ -> + ignore pos; + + let init = + match else_ with + | None -> fold_clause clause + | Some (_, ts) -> List.rev_append (fold_clause clause) (List.concat ts) + in + + List.fold_left elifs ~init ~f:(fun t clause -> + List.rev_append (fold_clause clause) t) + + let assign : + S.pos -> + (S.pos, expression) S.variable -> + T.assignation_operator -> + expression -> + t = + fun pos variable op expression -> + ignore pos; + ignore op; + match variable.index with + | None -> expression + | Some v -> List.rev_append v expression +end + +module Location = struct + type t = unit + type instruction = Instruction.t' + + let location : S.pos -> instruction list -> t * Report.t list = + fun pos intructions -> + ignore pos; + ((), List.concat intructions) +end diff --git a/lib/syntax/nested_strings.mli b/lib/syntax/nested_strings.mli new file mode 100644 index 0000000..38e3a1b --- /dev/null +++ b/lib/syntax/nested_strings.mli @@ -0,0 +1 @@ +include S.Analyzer @@ -70,3 +70,9 @@ can easily spot when a string value is used instead of a numeric. By analysing the branchs, the application can spot the block where no `gt` instructions are given, which can lead to dead end in the code. +### Nested string + +The application will report text strings containing only one expression with a +`debug` message. + +For example `"<<$variable>>"` can be written directly: `$variable>`. diff --git a/test/nested_string.ml b/test/nested_string.ml new file mode 100644 index 0000000..b121667 --- /dev/null +++ b/test/nested_string.ml @@ -0,0 +1,27 @@ +module Check = Make_checkTest.M (Qsp_syntax.Nested_strings) + +let _position = (Lexing.dummy_pos, Lexing.dummy_pos) + +let _test_instruction : string -> Qsp_syntax.Report.t list -> unit = + Check._test_instruction + +let nothing () = _test_instruction {| +"value = <<$variable>>" + |} [] + +let simple_expression () = + _test_instruction {|"<<$variable>>"|} + [ + { + level = Debug; + loc = _position; + message = "This expression can be simplified"; + }; + ] + +let test = + ( "Nested_strings checker", + [ + Alcotest.test_case "Ok" `Quick nothing; + Alcotest.test_case "Simple expression" `Quick simple_expression; + ] ) diff --git a/test/qsp_parser_test.ml b/test/qsp_parser_test.ml index 7fd5b52..a86df13 100644 --- a/test/qsp_parser_test.ml +++ b/test/qsp_parser_test.ml @@ -1,5 +1,10 @@ let () = Alcotest.run "qsp_parser" [ - Syntax.test; Literals.test; Syntax_error.test; Type_of.test; Dead_end.test; + Syntax.test; + Literals.test; + Syntax_error.test; + Type_of.test; + Dead_end.test; + Nested_string.test; ] |