diff options
-rw-r--r-- | lib/syntax/nested_strings.ml | 51 | ||||
-rw-r--r-- | lib/syntax/type_of.ml | 3 | ||||
-rw-r--r-- | lib/syntax/type_of.mli | 10 | ||||
-rw-r--r-- | readme.md | 4 | ||||
-rw-r--r-- | test/nested_string.ml | 33 |
5 files changed, 72 insertions, 29 deletions
diff --git a/lib/syntax/nested_strings.ml b/lib/syntax/nested_strings.ml index 16ec4ac..c7b0b83 100644 --- a/lib/syntax/nested_strings.ml +++ b/lib/syntax/nested_strings.ml @@ -5,10 +5,11 @@ let description = "Check for unnecessary use of expression encoded in string" let active = ref true module Expression : S.Expression with type t' = Report.t list = struct - type t = Report.t list - type t' = t + type t = Report.t list * Type_of.Expression.t + type t' = Report.t list - let v : t -> t' = Fun.id + let get_type t = Type_of.Expression.v t |> Type_of.get_type + let v : t -> t' = Stdlib.fst (** Identify the expressions reprented as string. That’s here that the report are added. @@ -16,28 +17,48 @@ module Expression : S.Expression with type t' = Report.t list = struct 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 -> + let type_of = + List.map content ~f:(function + | T.Text _ as text -> text + | T.Expression expr -> T.Expression (List.map ~f:snd expr)) + |> Type_of.Expression.literal pos + in + match content with - | [ T.Expression expr; T.Text "" ] -> - ignore expr; - let msg = Report.debug pos "This expression can be simplified" in - [ msg ] - | _ -> [] + | [ T.Expression [ (_, t') ]; T.Text "" ] -> ( + match get_type t' with + | Type_of.Helper.Integer -> ([], type_of) + | _ -> + let msg = Report.debug pos "This expression can be simplified" in + ([ msg ], type_of)) + | _ -> ([], type_of) 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 + match index with + | None -> + let type_ = Type_of.Expression.ident { pos; name; index = None } in + ([], type_) + | Some (v, t') -> + let type_ = Type_of.Expression.ident { pos; name; index = Some t' } in + (v, type_) - let integer : S.pos -> string -> t = fun _ _ -> [] + let integer : S.pos -> string -> t = + fun pos t -> ([], Type_of.Expression.integer pos t) let function_ : S.pos -> T.function_ -> t list -> t = - fun _ _ expressions -> List.concat expressions + fun pos f expressions -> + let r, t = List.split expressions in + + let type_of = Type_of.Expression.function_ pos f t in + (List.concat r, type_of) - let uoperator : S.pos -> T.uoperator -> t -> t = fun _ _ expr1 -> expr1 + let uoperator : S.pos -> T.uoperator -> t -> t = + fun pos op (r, expr1) -> (r, Type_of.Expression.uoperator pos op expr1) let boperator : S.pos -> T.boperator -> t -> t -> t = - fun _ _ expr1 expr2 -> expr1 @ expr2 + fun pos op (r1, expr1) (r2, expr2) -> + (r1 @ r2, Type_of.Expression.boperator pos op expr1 expr2) end module Instruction : diff --git a/lib/syntax/type_of.ml b/lib/syntax/type_of.ml index 223633c..15d6fe8 100644 --- a/lib/syntax/type_of.ml +++ b/lib/syntax/type_of.ml @@ -483,3 +483,6 @@ module Location = struct in report end + +let get_type : Expression.t' -> Helper.type_of = + fun t' -> match (fst t').result with Raw r -> r | Variable r -> r diff --git a/lib/syntax/type_of.mli b/lib/syntax/type_of.mli index 551f9ac..a009c48 100644 --- a/lib/syntax/type_of.mli +++ b/lib/syntax/type_of.mli @@ -1,3 +1,11 @@ +module Helper : sig + type type_of = + | Integer (** A numeric value *) + | Bool (** A boolean, not a real type *) + | String (** String value *) + | NumericString +end + include S.Analyzer (** The module [type_of] populate the report with differents inconsistency errors in the types. @@ -5,3 +13,5 @@ include S.Analyzer - Assigning a [string] value in an [integer] variable - Comparing a [string] with an [integer] - Giving the wrong type in the argument for a function and so one. *) + +val get_type : Expression.t' -> Helper.type_of @@ -77,4 +77,6 @@ instructions are given, which can lead to dead end in the code. The application will report text strings containing only one expression with a `debug` message. -For example `"<<$variable>>"` can be written directly: `$variable>`. +For example `"<<$variable>>"` can be written directly: `$variable>`. This test +will not report this usage when an integer converted into a string this way. + diff --git a/test/nested_string.ml b/test/nested_string.ml index b121667..3338fa3 100644 --- a/test/nested_string.ml +++ b/test/nested_string.ml @@ -5,23 +5,30 @@ 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 report = + [ + { + Qsp_syntax.Report.level = Debug; + Qsp_syntax.Report.loc = _position; + Qsp_syntax.Report.message = "This expression can be simplified"; + }; + ] -let simple_expression () = - _test_instruction {|"<<$variable>>"|} - [ - { - level = Debug; - loc = _position; - message = "This expression can be simplified"; - }; - ] +let nothing () = _test_instruction {|"value = <<$variable>>"|} [] +let string () = _test_instruction {|"<<'ABC'>>"|} report +let string_variable () = _test_instruction {|"<<$variable>>"|} report + +(** It’s OK to use this system to convert a numeric value into a string *) +let integer () = _test_instruction {|"<<123>>"|} [] + +let integer_variable () = _test_instruction {|"<<variable>>"|} [] let test = ( "Nested_strings checker", [ Alcotest.test_case "Ok" `Quick nothing; - Alcotest.test_case "Simple expression" `Quick simple_expression; + Alcotest.test_case "String variable" `Quick string_variable; + Alcotest.test_case "Integer" `Quick integer; + Alcotest.test_case "String" `Quick string; + Alcotest.test_case "Integer variable" `Quick integer_variable; ] ) |