aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChimrod <>2023-11-02 17:35:49 +0100
committerChimrod <>2023-11-02 19:39:33 +0100
commitfd02a44392304986a756e7d06f8142538b386529 (patch)
tree87fe05ab02eecee8b2c8cc89ed5fa2c8b83d9771
parent05f74bee05c0c56da593a5e89069711d5993e3b1 (diff)
Added a new checkers for unecessary use of strig containing an escaped expression
-rw-r--r--bin/qsp_parser.ml10
-rw-r--r--lib/syntax/nested_strings.ml109
-rw-r--r--lib/syntax/nested_strings.mli1
-rw-r--r--readme.md6
-rw-r--r--test/nested_string.ml27
-rw-r--r--test/qsp_parser_test.ml7
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
diff --git a/readme.md b/readme.md
index c5b60ef..b125676 100644
--- a/readme.md
+++ b/readme.md
@@ -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;
]