diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3d118f9f82..95cd9be432 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -471,7 +471,7 @@ Some tips: - The first sentence or line should show the function call with a very short summary. - Ideally, every function should have an `## Examples` section with **at least one** example. The examples are compiled to check that they are correct. Use `==` to generate tests from the examples. - Always use `@deprecated` when applicable. -- Always use `@throw` when applicable. +- Always use `@throws` when applicable. - Always provide a `See` section pointing to MDN for more information when available. ## Contribute to JSX `domProps` diff --git a/analysis/reanalyze/src/arnold.ml b/analysis/reanalyze/src/arnold.ml index 4221e00adc..3a8f2cd7ed 100644 --- a/analysis/reanalyze/src/arnold.ml +++ b/analysis/reanalyze/src/arnold.ml @@ -833,10 +833,10 @@ module Compile = struct | _ -> Stats.log_hygiene_named_arg_value ~label ~loc; raise ArgError - [@@raises ArgError] + [@@throws ArgError] in function_arg () - [@@raises ArgError] + [@@throws ArgError] in let function_args_opt = try Some (function_definition.kind |> List.map get_function_arg) diff --git a/analysis/reanalyze/src/exception.ml b/analysis/reanalyze/src/exception.ml index 13fdc5d4b7..1a3b88f1fd 100644 --- a/analysis/reanalyze/src/exception.ml +++ b/analysis/reanalyze/src/exception.ml @@ -313,13 +313,7 @@ let traverse_ast ~file ~values_builder ~checks_builder () = in let does_not_throw attributes = attributes - |> Annotation.get_attribute_payload (function - | "doesNotRaise" | "doesnotraise" | "DoesNoRaise" | "doesNotraise" - | "doNotRaise" | "donotraise" | "DoNoRaise" | "doNotraise" - | "doesNotThrow" | "doesnotthrow" | "DoesNoThrow" | "doesNotthrow" - | "doNotThrow" | "donotthrow" | "DoNoThrow" | "doNotthrow" -> - true - | _ -> false) + |> Annotation.get_attribute_payload (fun s -> s = "doesNotThrow") <> None in let expr ~(module_path : Module_path.t) (self : Tast_mapper.mapper) @@ -425,9 +419,7 @@ let traverse_ast ~file ~values_builder ~checks_builder () = in let get_exceptions_from_annotations attributes = let throws_annotation_payload = - attributes - |> Annotation.get_attribute_payload (fun s -> - s = "throws" || s = "throw" || s = "raises" || s = "raise") + attributes |> Annotation.get_attribute_payload (fun s -> s = "throws") in let rec get_exceptions payload = match payload with diff --git a/analysis/reanalyze/src/log_.ml b/analysis/reanalyze/src/log_.ml index 6a39772753..a7f48a2f63 100644 --- a/analysis/reanalyze/src/log_.ml +++ b/analysis/reanalyze/src/log_.ml @@ -95,7 +95,7 @@ let item x = Format.fprintf Format.std_formatter " "; Format.fprintf Format.std_formatter x -let missing_raise_info_to_text {Issue.missing_annotations; loc_full} = +let missing_throw_info_to_text {Issue.missing_annotations; loc_full} = let missing_txt = Format.asprintf "%a" (Exceptions.pp ~exn_table:None) missing_annotations in @@ -107,8 +107,8 @@ let missing_raise_info_to_text {Issue.missing_annotations; loc_full} = let log_additional_info ~(description : Issue.description) = match description with - | ExceptionAnalysisMissing missing_raise_info -> - missing_raise_info_to_text missing_raise_info + | ExceptionAnalysisMissing missing_throw_info -> + missing_throw_info_to_text missing_throw_info | _ -> "" let missing_throw_info_to_message @@ -130,8 +130,8 @@ let description_to_message (description : Issue.description) = | DeadWarning {path; message} -> Format.asprintf "@{%s@} %s" path message | ExceptionAnalysis {message} -> message - | ExceptionAnalysisMissing missing_raise_info -> - missing_throw_info_to_message missing_raise_info + | ExceptionAnalysisMissing missing_throw_info -> + missing_throw_info_to_message missing_throw_info | Termination {message} -> message let description_to_name (description : Issue.description) = diff --git a/analysis/reanalyze/src/reanalyze.ml b/analysis/reanalyze/src/reanalyze.ml index 62b18ad5f4..95be43f684 100644 --- a/analysis/reanalyze/src/reanalyze.ml +++ b/analysis/reanalyze/src/reanalyze.ml @@ -341,7 +341,7 @@ let parse_argv (argv : string array) : string option = let version_and_exit () = print_endline usage; exit 0 - [@@raises exit] + [@@throws exit] in let rec set_all cmt_root = Run_config.all (); @@ -478,7 +478,7 @@ let parse_argv (argv : string array) : string option = let cli () = let cmt_root = parse_argv Sys.argv in run_analysis_and_report ~cmt_root -[@@raises exit] +[@@throws exit] (* Re-export server module for external callers (e.g. tools/bin/main.ml). This keeps the wrapped-library layering intact: Reanalyze depends on internal diff --git a/analysis/src/completion_decorators.ml b/analysis/src/completion_decorators.ml index f6e8a696c7..7921e9fab1 100644 --- a/analysis/src/completion_decorators.ml +++ b/analysis/src/completion_decorators.ml @@ -38,18 +38,6 @@ Alternatively, use the `@@deprecated` decorator to add a deprecation warning to [Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#expression-deprecated-decorator).|}; ] ); - ( "doesNotRaise", - None, - [ - {|The `@doesNotRaise` decorator is deprecated. Please use `@doesNotThrow` instead. - -`@doesNotRaise` is uses to override the analysis and state that an expression does not throw any exceptions, -even though the analysis reports otherwise. This can happen for example in the case of array access where -the analysis does not perform range checks but takes a conservative stance that any access -could potentially throw. -[Read more and see examples in the documentation](https://github.com/rescript-association/reanalyze/blob/master/EXCEPTION.md). -> Hint: Did you know you can run an interactive code analysis in your project by running the command `> ReScript: Start Code Analyzer`? Try it!|}; - ] ); ( "doesNotThrow", None, [ @@ -151,17 +139,6 @@ The `@new` decorator is used whenever you need to bind to a JavaScript class con [Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#obj-decorator).|}; ] ); - ( "raises", - Some "raises(\"$0\")", - [ - {|The `@raises` decorator is deprecated. Please use `@throws` instead. - -`@raises` acknowledges that a function can throw exceptions that are not caught, and suppresses -a warning in that case. Callers of the functions are then subjected to the same rule. -Example `@raises(Exn)` or `@raises([E1, E2, E3])` for multiple exceptions. -[Read more and see examples in the documentation](https://github.com/rescript-association/reanalyze/blob/master/EXCEPTION.md). -> Hint: Did you know you can run an interactive code analysis in your project by running the command `> ReScript: Start Code Analyzer`? Try it!|}; - ] ); ( "throws", Some "throws(\"$0\")", [ diff --git a/analysis/src/process_cmt.ml b/analysis/src/process_cmt.ml index 18d854a524..84386fa8db 100644 --- a/analysis/src/process_cmt.ml +++ b/analysis/src/process_cmt.ml @@ -550,7 +550,7 @@ let rec for_structure_item ~(env : Shared_types.Env.t) ~(exported : Exported.t) {mb_id; mb_attributes; mb_loc; mb_name = name; mb_expr = {mod_desc}} when not (String.length name.txt >= 6 - && (String.sub name.txt 0 6 = "local_") [@doesNotRaise]) + && (String.sub name.txt 0 6 = "local_") [@doesNotThrow]) (* %%private generates a dummy module called local_... *) -> let item = for_module ~env mod_desc name.txt in let declared = diff --git a/changes/reanalyze-throws-only.breaking.md b/changes/reanalyze-throws-only.breaking.md new file mode 100644 index 0000000000..4f6aaa528f --- /dev/null +++ b/changes/reanalyze-throws-only.breaking.md @@ -0,0 +1 @@ +- Reanalyze no longer honors `@raises`, `@raise`, `@throw`, `@doesNotRaise` or the other `@doesNotThrow` variants: write `@throws` and `@doesNotThrow` instead. diff --git a/compiler/ext/ext_util.ml b/compiler/ext/ext_util.ml index 0467cd772e..11562e733d 100644 --- a/compiler/ext/ext_util.ml +++ b/compiler/ext/ext_util.ml @@ -34,7 +34,7 @@ let string_of_int_as_char (i : int) : string = | '\r' -> "\\r" | '\b' -> "\\b" | ' ' .. '~' as c -> - let s = (Bytes.create [@doesNotRaise]) 1 in + let s = (Bytes.create [@doesNotThrow]) 1 in Bytes.unsafe_set s 0 c; Bytes.unsafe_to_string s | _ when Uchar.is_valid i -> Ext_utf8.encode_codepoint i diff --git a/compiler/gentype/emit_js.ml b/compiler/gentype/emit_js.ml index e2fdb007a2..d486a741f1 100644 --- a/compiler/gentype/emit_js.ml +++ b/compiler/gentype/emit_js.ml @@ -455,7 +455,7 @@ let rec read_cmt_files_recursively ~config ~env |> create_export_type_map ~config ~from_cmt_read_recursively:true ~file: (cmt_file |> Filename.basename - |> (Filename.chop_extension [@doesNotRaise])) + |> (Filename.chop_extension [@doesNotThrow])) in let cmt_to_export_type_map = env.cmt_to_export_type_map diff --git a/compiler/gentype/generated_files.ml b/compiler/gentype/generated_files.ml index 3bafad47dd..f3e704a83c 100644 --- a/compiler/gentype/generated_files.ml +++ b/compiler/gentype/generated_files.ml @@ -27,7 +27,7 @@ let read_lines (file : string) : string list = done; [] with End_of_file -> - close_in chan [@doesNotRaise]; + close_in chan [@doesNotThrow]; !lines |> List.rev in finished_lines @@ -37,7 +37,7 @@ let read_file (file : string) : string = String.concat "\n" (read_lines file) let write_file (file_path : string) (contents : string) = let out_file = open_out file_path in output_string out_file contents; - close_out out_file [@doesNotRaise] + close_out out_file [@doesNotThrow] let write_file_if_required ~output_file ~file_contents = if Sys.file_exists output_file then diff --git a/compiler/gentype/gentype_common.ml b/compiler/gentype/gentype_common.ml index ff69b6c354..004ca71b2f 100644 --- a/compiler/gentype/gentype_common.ml +++ b/compiler/gentype/gentype_common.ml @@ -30,7 +30,7 @@ type case = {label_js: label_js} let is_js_safe_property_name name = name = "" - || (match name.[0] [@doesNotRaise] with + || (match name.[0] [@doesNotThrow] with | 'A' .. 'z' -> true | _ -> false) && name @@ -42,12 +42,12 @@ let is_number s = let len = String.length s in len > 0 && (match len > 1 with - | true -> (s.[0] [@doesNotRaise]) > '0' + | true -> (s.[0] [@doesNotThrow]) > '0' | false -> true) && let res = ref true in for i = 0 to len - 1 do - match s.[i] [@doesNotRaise] with + match s.[i] [@doesNotThrow] with | '0' .. '9' -> () | _ -> res := false done; @@ -222,7 +222,7 @@ module Node_filename = struct let concat dirname filename = let is_dir_sep s i = - let c = (s.[i] [@doesNotRaise]) in + let c = (s.[i] [@doesNotThrow]) in c = '/' || c = '\\' || c = ':' in let l = length dirname in diff --git a/compiler/gentype/gentype_main.ml b/compiler/gentype/gentype_main.ml index a9c0d91180..64f60f106e 100644 --- a/compiler/gentype/gentype_main.ml +++ b/compiler/gentype/gentype_main.ml @@ -108,7 +108,7 @@ let read_input_cmt is_interface cmt_file = in if is_interface then let cmt_file_impl = - (cmt_file |> (Filename.chop_extension [@doesNotRaise])) ^ ".cmt" + (cmt_file |> (Filename.chop_extension [@doesNotThrow])) ^ ".cmt" in let input_cmt_impl = read_cmt cmt_file_impl in let has_gentype_annotations_impl = diff --git a/compiler/gentype/module_name.ml b/compiler/gentype/module_name.ml index e143e6298c..2dc3bfb24c 100644 --- a/compiler/gentype/module_name.ml +++ b/compiler/gentype/module_name.ml @@ -12,7 +12,7 @@ let sanitize_id s = | c -> c) else s in - if s <> "" && (s.[0] [@doesNotRaise]) >= 'A' && (s.[0] [@doesNotRaise]) <= 'z' + if s <> "" && (s.[0] [@doesNotThrow]) >= 'A' && (s.[0] [@doesNotThrow]) <= 'z' then s else "_" ^ s diff --git a/compiler/gentype/paths.ml b/compiler/gentype/paths.ml index fc6c065bc5..7147344571 100644 --- a/compiler/gentype/paths.ml +++ b/compiler/gentype/paths.ml @@ -3,16 +3,16 @@ open Gentype_common let handle_namespace cmt = let cut_after_dash s = match String.index s '-' with - | n -> String.sub s 0 n [@doesNotRaise] + | n -> String.sub s 0 n [@doesNotThrow] | exception Not_found -> s in let no_dir = Filename.basename cmt = cmt in if no_dir then - cmt |> (Filename.chop_extension [@doesNotRaise]) |> cut_after_dash + cmt |> (Filename.chop_extension [@doesNotThrow]) |> cut_after_dash else let dir = cmt |> Filename.dirname in let base = - cmt |> Filename.basename |> (Filename.chop_extension [@doesNotRaise]) + cmt |> Filename.basename |> (Filename.chop_extension [@doesNotThrow]) |> cut_after_dash in Filename.concat dir base @@ -21,10 +21,10 @@ let find_name_space cmt = let keep_after_dash s = match String.index s '-' with | n -> - Some ((String.sub s (n + 1) [@doesNotRaise]) (String.length s - n - 1)) + Some ((String.sub s (n + 1) [@doesNotThrow]) (String.length s - n - 1)) | exception Not_found -> None in - cmt |> Filename.basename |> (Filename.chop_extension [@doesNotRaise]) + cmt |> Filename.basename |> (Filename.chop_extension [@doesNotThrow]) |> keep_after_dash let remove_path_prefix ~prefix path = @@ -33,10 +33,10 @@ let remove_path_prefix ~prefix path = let path_len = String.length path in let is_prefix = prefix_len <= path_len - && (String.sub path 0 prefix_len [@doesNotRaise]) = normalized_prefix + && (String.sub path 0 prefix_len [@doesNotThrow]) = normalized_prefix in if is_prefix then - String.sub path prefix_len (path_len - prefix_len) [@doesNotRaise] + String.sub path prefix_len (path_len - prefix_len) [@doesNotThrow] else path let append_suffix ~config source_path = @@ -70,10 +70,10 @@ let get_cmt_file cmt = Filename.concat dir_name (base_name |> String.uncapitalize_ascii) in let path_cmti = - (Filename.chop_extension path_cmt [@doesNotRaise]) ^ ".cmti" + (Filename.chop_extension path_cmt [@doesNotThrow]) ^ ".cmti" in let path_cmti_lower_case = - (Filename.chop_extension path_cmt_lower_case [@doesNotRaise]) ^ ".cmti" + (Filename.chop_extension path_cmt_lower_case [@doesNotThrow]) ^ ".cmti" in (* The compiler's spelling first: on a case-insensitive file system the lowercase one exists too, and the build file store, which holds diff --git a/compiler/gentype/translate_type_declarations.ml b/compiler/gentype/translate_type_declarations.ml index a766229b79..2304e2420b 100644 --- a/compiler/gentype/translate_type_declarations.ml +++ b/compiler/gentype/translate_type_declarations.ml @@ -211,7 +211,7 @@ let traslate_declaration_kind ~config ~loc ~output_file_relative ~resolver = (row_fields_variants.payloads |> List.length) then (List.combine variant.payloads row_fields_variants.payloads - [@doesNotRaise]) + [@doesNotThrow]) |> List.map (fun (payload, (label, attributes, _)) -> let case = create_polyvariant_case (label, attributes) in {payload with case}) diff --git a/compiler/gentype/translate_type_expr_from_types.ml b/compiler/gentype/translate_type_expr_from_types.ml index 33a2d33c95..fa8e1e3242 100644 --- a/compiler/gentype/translate_type_expr_from_types.ml +++ b/compiler/gentype/translate_type_expr_from_types.ml @@ -614,7 +614,7 @@ and translateTypeExprFromTypes_ ~config ~type_vars_gen ~type_env match type_env |> Type_env.lookup_module_type_signature ~path with | Some (signature, type_env) -> let type_equations_translation = - (List.combine ids types [@doesNotRaise]) + (List.combine ids types [@doesNotThrow]) |> List.map (fun (x, t) -> ( x, t |> translateTypeExprFromTypes_ ~config ~type_vars_gen ~type_env diff --git a/compiler/ml/ast_mapper_from0.ml b/compiler/ml/ast_mapper_from0.ml index 4f76e1e052..ae6294dd74 100644 --- a/compiler/ml/ast_mapper_from0.ml +++ b/compiler/ml/ast_mapper_from0.ml @@ -383,7 +383,7 @@ module T = struct when lid.txt = Lident "function$" -> ( let decode_arity_string arity_s = int_of_string - ((String.sub [@doesNotRaise]) arity_s 9 (String.length arity_s - 9)) + ((String.sub [@doesNotThrow]) arity_s 9 (String.length arity_s - 9)) in let arity_from_type (typ : Parsetree.core_type) = match typ.ptyp_desc with diff --git a/compiler/syntax/cli/res_cli.ml b/compiler/syntax/cli/res_cli.ml index f3dcdd5c7a..75f2b630d8 100644 --- a/compiler/syntax/cli/res_cli.ml +++ b/compiler/syntax/cli/res_cli.ml @@ -66,7 +66,7 @@ module Cli_arg_processor = struct let len = String.length filename in let process_interface = is_interface - || (len > 0 && (String.get [@doesNotRaise]) filename (len - 1) = 'i') + || (len > 0 && (String.get [@doesNotThrow]) filename (len - 1) = 'i') in let source = lazy (Ext_io.load_file filename) in let load_source () = Lazy.force source in @@ -150,7 +150,7 @@ module Cli_arg_processor = struct in (print_engine parse_result.newline).print_implementation ~width ~filename ~comments:parse_result.comments parsetree - [@@raises exit] + [@@throws exit] end let () = @@ -161,4 +161,4 @@ let () = ~target:!Res_clflags.print ~jsx_version:!Res_clflags.jsx_version ~jsx_module:!Res_clflags.jsx_module !Res_clflags.file ~test_ast_conversion:!Res_clflags.test_ast_conversion) -[@@raises exit] +[@@throws exit] diff --git a/compiler/syntax/src/jsx_v4.ml b/compiler/syntax/src/jsx_v4.ml index b23f24e32a..f386ace3b0 100644 --- a/compiler/syntax/src/jsx_v4.ml +++ b/compiler/syntax/src/jsx_v4.ml @@ -37,7 +37,7 @@ let unit_expr ~loc = let safe_type_from_value value_str = let value_str = get_label value_str in - if value_str = "" || (value_str.[0] [@doesNotRaise]) <> '_' then value_str + if value_str = "" || (value_str.[0] [@doesNotThrow]) <> '_' then value_str else "T" ^ value_str let ref_type_var loc = Typ.var ~loc "ref" @@ -107,7 +107,7 @@ let make_props_type_params_tvar named_type_list = let strip_option core_type = match core_type with | {ptyp_desc = Ptyp_constr ({txt = Lident "option"}, core_types)} -> - List.nth_opt core_types 0 [@doesNotRaise] + List.nth_opt core_types 0 [@doesNotThrow] | _ -> Some core_type let strip_nullable core_type = @@ -121,7 +121,7 @@ let strip_nullable core_type = Ptyp_constr ({txt = Ldot (Ldot (Lident "Stdlib", "Nullable"), "t")}, core_types); } -> - List.nth_opt core_types 0 [@doesNotRaise] + List.nth_opt core_types 0 [@doesNotThrow] | _ -> Some core_type (* Make type params of the props type *) diff --git a/compiler/syntax/src/res_comment.ml b/compiler/syntax/src/res_comment.ml index c4c2f0f82c..c197bf93d7 100644 --- a/compiler/syntax/src/res_comment.ml +++ b/compiler/syntax/src/res_comment.ml @@ -91,5 +91,5 @@ let trim_spaces s = while !j >= !i && String.unsafe_get s !j = ' ' do decr j done; - if !j >= !i then (String.sub [@doesNotRaise]) s !i (!j - !i + 1) else "") + if !j >= !i then (String.sub [@doesNotThrow]) s !i (!j - !i + 1) else "") else s diff --git a/compiler/syntax/src/res_core.ml b/compiler/syntax/src/res_core.ml index 63da4062e9..9e68773b8c 100644 --- a/compiler/syntax/src/res_core.ml +++ b/compiler/syntax/src/res_core.ml @@ -509,8 +509,8 @@ let make_infix_operator (p : Parser.t) token start_pos end_pos = Ast_helper.Exp.ident ~loc operator let negate_string s = - if String.length s > 0 && (s.[0] [@doesNotRaise]) = '-' then - (String.sub [@doesNotRaise]) s 1 (String.length s - 1) + if String.length s > 0 && (s.[0] [@doesNotThrow]) = '-' then + (String.sub [@doesNotThrow]) s 1 (String.length s - 1) else "-" ^ s let make_unary_expr start_pos token_end token operand = diff --git a/compiler/syntax/src/res_doc.ml b/compiler/syntax/src/res_doc.ml index 523237a132..7a025cb861 100644 --- a/compiler/syntax/src/res_doc.ml +++ b/compiler/syntax/src/res_doc.ml @@ -299,7 +299,7 @@ let to_string ?(newline = "\n") ~width doc = else ( Mini_buffer.flush_newline buffer ~newline; Mini_buffer.add_string buffer - (String.make ind ' ' [@doesNotRaise]); + (String.make ind ' ' [@doesNotThrow]); process ~pos:ind [] rest) | _docs -> process ~pos:ind [] diff --git a/compiler/syntax/src/res_driver.ml b/compiler/syntax/src/res_driver.ml index e139a5e5d2..dcf4399259 100644 --- a/compiler/syntax/src/res_driver.ml +++ b/compiler/syntax/src/res_driver.ml @@ -179,7 +179,7 @@ let parse_implementation ~ignore_parse_errors sourcefile = Res_diagnostics.print_report parse_result.diagnostics parse_result.source; if not ignore_parse_errors then raise_notrace Already_reported); parse_result.parsetree -[@@raises Already_reported] +[@@throws Already_reported] let parse_interface ~ignore_parse_errors sourcefile = Location.set_input_name sourcefile; @@ -188,11 +188,11 @@ let parse_interface ~ignore_parse_errors sourcefile = Res_diagnostics.print_report parse_result.diagnostics parse_result.source; if not ignore_parse_errors then raise_notrace Already_reported); parse_result.parsetree -[@@raises Already_reported] +[@@throws Already_reported] (* suppress unused optional arg *) let _ = fun s -> ( parse_implementation ~ignore_parse_errors:false s, parse_interface ~ignore_parse_errors:false s ) -[@@raises Already_reported] +[@@throws Already_reported] diff --git a/compiler/syntax/src/res_driver.mli b/compiler/syntax/src/res_driver.mli index 5e28ebb444..ec73d15537 100644 --- a/compiler/syntax/src/res_driver.mli +++ b/compiler/syntax/src/res_driver.mli @@ -61,8 +61,8 @@ exception Already_reported (* ReScript implementation parsing compatible with ocaml pparse driver. Used by the compiler. *) val parse_implementation : ignore_parse_errors:bool -> string -> Parsetree.structure -[@@live] [@@raises Location.Error Already_reported] +[@@live] [@@throws Location.Error Already_reported] (* ReScript interface parsing compatible with ocaml pparse driver. Used by the compiler *) val parse_interface : ignore_parse_errors:bool -> string -> Parsetree.signature -[@@live] [@@raises Location.Error Already_reported] +[@@live] [@@throws Location.Error Already_reported] diff --git a/compiler/syntax/src/res_minibuffer.ml b/compiler/syntax/src/res_minibuffer.ml index 8354bae014..d8766090b8 100644 --- a/compiler/syntax/src/res_minibuffer.ml +++ b/compiler/syntax/src/res_minibuffer.ml @@ -2,10 +2,10 @@ type t = {mutable buffer: bytes; mutable position: int; mutable length: int} let create n = let n = if n < 1 then 1 else n in - let s = (Bytes.create [@doesNotRaise]) n in + let s = (Bytes.create [@doesNotThrow]) n in {buffer = s; position = 0; length = n} -let contents b = (Bytes.sub_string [@doesNotRaise]) b.buffer 0 b.position +let contents b = (Bytes.sub_string [@doesNotThrow]) b.buffer 0 b.position (* Can't be called directly, don't add to the interface *) let resize_internal b more = @@ -17,10 +17,10 @@ let resize_internal b more = if !new_len > Sys.max_string_length then if b.position + more <= Sys.max_string_length then new_len := Sys.max_string_length; - let new_buffer = (Bytes.create [@doesNotRaise]) !new_len in + let new_buffer = (Bytes.create [@doesNotThrow]) !new_len in (* PR#6148: let's keep using [blit] rather than [unsafe_blit] in this tricky function that is slow anyway. *) - Bytes.blit b.buffer 0 new_buffer 0 b.position [@doesNotRaise]; + Bytes.blit b.buffer 0 new_buffer 0 b.position [@doesNotThrow]; b.buffer <- new_buffer; b.length <- !new_len @@ -34,7 +34,7 @@ let add_string b s = let len = String.length s in let new_position = b.position + len in if new_position > b.length then resize_internal b len; - Bytes.blit_string s 0 b.buffer b.position len [@doesNotRaise]; + Bytes.blit_string s 0 b.buffer b.position len [@doesNotThrow]; b.position <- new_position (* adds newline and trims all preceding whitespace *) diff --git a/compiler/syntax/src/res_multi_printer.ml b/compiler/syntax/src/res_multi_printer.ml index b4263eb160..e71b8413b5 100644 --- a/compiler/syntax/src/res_multi_printer.ml +++ b/compiler/syntax/src/res_multi_printer.ml @@ -21,7 +21,7 @@ let print_res ~ignore_parse_errors ~is_interface ~filename source = Res_printer.print_implementation ~width:Res_printer.default_print_width ~newline:parse_result.newline ~comments:parse_result.comments parse_result.parsetree -[@@raises Res_driver.Already_reported] +[@@throws Res_driver.Already_reported] (* print the given file named input to from "language" to res, general interface exposed by the compiler *) let print ?(ignore_parse_errors = false) input = @@ -33,8 +33,8 @@ let print ?(ignore_parse_errors = false) input = (* Keep a byte order mark, which the scanner skips *) Res_scanner.byte_order_mark source ^ print_res ~ignore_parse_errors ~is_interface ~filename:input source -[@@raises Res_driver.Already_reported] +[@@throws Res_driver.Already_reported] (* suppress unused optional arg *) let _ = fun s -> print ~ignore_parse_errors:false s -[@@raises Res_driver.Already_reported] +[@@throws Res_driver.Already_reported] diff --git a/compiler/syntax/src/res_outcome_printer.ml b/compiler/syntax/src/res_outcome_printer.ml index dfd50e7095..c3a85cfa99 100644 --- a/compiler/syntax/src/res_outcome_printer.ml +++ b/compiler/syntax/src/res_outcome_printer.ml @@ -163,7 +163,7 @@ let rec print_out_type_doc (out_type : Outcometree.out_type) = let i = ref 0 in let package = Doc.join ~sep:Doc.line - ((List.map2 [@doesNotRaise]) + ((List.map2 [@doesNotThrow]) (fun lbl typ -> let result = Doc.concat diff --git a/compiler/syntax/src/res_parens.ml b/compiler/syntax/src/res_parens.ml index fb07a6ff94..c3134991f2 100644 --- a/compiler/syntax/src/res_parens.ml +++ b/compiler/syntax/src/res_parens.ml @@ -237,7 +237,7 @@ let assert_or_await_expr_rhs ?(in_await = false) expr = let is_negative_constant constant = let is_neg txt = let len = String.length txt in - len > 0 && (String.get [@doesNotRaise]) txt 0 = '-' + len > 0 && (String.get [@doesNotThrow]) txt 0 = '-' in match constant with | (Parsetree.Pconst_integer (i, _) | Pconst_float (i, _)) when is_neg i -> @@ -307,7 +307,7 @@ let starts_with_minus txt = let len = String.length txt in if len == 0 then false else - let s = (String.get [@doesNotRaise]) txt 0 in + let s = (String.get [@doesNotThrow]) txt 0 in s = '-' let jsx_prop_expr expr = diff --git a/compiler/syntax/src/res_printer.ml b/compiler/syntax/src/res_printer.ml index b4fb201936..04800a18b7 100644 --- a/compiler/syntax/src/res_printer.ml +++ b/compiler/syntax/src/res_printer.ml @@ -187,7 +187,7 @@ let print_multiline_comment_content txt = while !len > 0 && String.unsafe_get first (!len - 1) = '\r' do decr len done; - String.sub first 0 !len [@doesNotRaise] + String.sub first 0 !len [@doesNotThrow] in let first_line = Comment.trim_spaces first in Doc.concat @@ -562,7 +562,7 @@ let print_poly_var_ident txt = let len = String.length txt in (* UppercaseExoticIdent follows the \"..." format, so removing the leading backslash is enough to transform it into polyvar style *) - Doc.text ((String.sub [@doesNotRaise]) txt 1 (len - 1)) + Doc.text ((String.sub [@doesNotThrow]) txt 1 (len - 1)) | ExoticIdent -> Doc.concat [Doc.text "\""; Doc.text txt; Doc.text "\""] | NormalIdent -> ( match txt with @@ -6233,7 +6233,7 @@ and print_mod_expr ~state mod_expr cmt_tbl = call_expr_doc; (if is_unit_sugar then print_mod_apply_arg ~state - (List.hd args [@doesNotRaise]) + (List.hd args [@doesNotThrow]) cmt_tbl else Doc.concat @@ -6241,7 +6241,7 @@ and print_mod_expr ~state mod_expr cmt_tbl = Doc.lparen; (if should_hug then print_mod_apply_arg ~state - (List.hd args [@doesNotRaise]) + (List.hd args [@doesNotThrow]) cmt_tbl else Doc.indent diff --git a/compiler/syntax/src/res_scanner.ml b/compiler/syntax/src/res_scanner.ml index ba5fe00fbf..f0e65299be 100644 --- a/compiler/syntax/src/res_scanner.ml +++ b/compiler/syntax/src/res_scanner.ml @@ -55,13 +55,13 @@ let position scanner = let _printDebug ~start_pos ~end_pos scanner token = let open Lexing in print_string scanner.src; - print_string ((String.make [@doesNotRaise]) start_pos.pos_cnum ' '); + print_string ((String.make [@doesNotThrow]) start_pos.pos_cnum ' '); print_char '^'; (match end_pos.pos_cnum - start_pos.pos_cnum with | 0 -> if token = Token.Eof then () else assert false | 1 -> () | n -> - print_string ((String.make [@doesNotRaise]) (n - 2) '-'); + print_string ((String.make [@doesNotThrow]) (n - 2) '-'); print_char '^'); print_char ' '; print_string (Res_token.to_string token); @@ -204,7 +204,7 @@ let scan_identifier scanner = in skip_good_chars scanner; let str = - (String.sub [@doesNotRaise]) scanner.src start_off + (String.sub [@doesNotThrow]) scanner.src start_off (scanner.offset - start_off) in match (scanner, str) with @@ -300,7 +300,7 @@ let scan_number scanner = | _ -> is_float in let literal = - (String.sub [@doesNotRaise]) scanner.src start_off + (String.sub [@doesNotThrow]) scanner.src start_off (scanner.offset - start_off) in @@ -341,7 +341,7 @@ let scan_exotic_identifier scanner = scan (); let ident = - (String.sub [@doesNotRaise]) scanner.src start_off + (String.sub [@doesNotThrow]) scanner.src start_off (scanner.offset - start_off) in let name = Ext_ident.unwrap_uppercase_exotic ident in @@ -460,7 +460,7 @@ let scan_string scanner = let bring_buf_up_to_date ~start_offset = let str_up_to_now = (String.sub scanner.src !last_offset_in_buf - (start_offset - !last_offset_in_buf) [@doesNotRaise]) + (start_offset - !last_offset_in_buf) [@doesNotThrow]) in Buffer.add_string buf str_up_to_now; last_offset_in_buf := start_offset @@ -468,7 +468,7 @@ let scan_string scanner = let result ~first_char_offset ~last_char_offset = if Buffer.length buf = 0 then - (String.sub [@doesNotRaise]) scanner.src first_char_offset + (String.sub [@doesNotThrow]) scanner.src first_char_offset (last_char_offset - first_char_offset) else ( bring_buf_up_to_date ~start_offset:last_char_offset; @@ -506,12 +506,12 @@ let scan_string scanner = let txt = scanner.src in let is_numeric_escape = len = 3 - && (is_digit txt.[start_offset] [@doesNotRaise]) - && (is_digit txt.[start_offset + 1] [@doesNotRaise]) - && (is_digit txt.[start_offset + 2] [@doesNotRaise]) + && (is_digit txt.[start_offset] [@doesNotThrow]) + && (is_digit txt.[start_offset + 1] [@doesNotThrow]) + && (is_digit txt.[start_offset + 2] [@doesNotThrow]) in if is_numeric_escape then ( - let str_decimal = (String.sub txt start_offset 3 [@doesNotRaise]) in + let str_decimal = (String.sub txt start_offset 3 [@doesNotThrow]) in bring_buf_up_to_date ~start_offset; let str_hex = Res_string.convert_decimal_to_hex ~str_decimal in last_offset_in_buf := start_offset + 3; @@ -584,7 +584,7 @@ let scan_escape scanner = Char.code ch in let contents = - (String.sub [@doesNotRaise]) scanner.src offset (scanner.offset - offset) + (String.sub [@doesNotThrow]) scanner.src offset (scanner.offset - offset) in next scanner; (* Consume \' *) @@ -605,7 +605,7 @@ let scan_regex ~start_pos:opening_pos ~prefix_length scanner = let bring_buf_up_to_date ~start_offset = let str_up_to_now = (String.sub scanner.src !last_offset_in_buf - (start_offset - !last_offset_in_buf) [@doesNotRaise]) + (start_offset - !last_offset_in_buf) [@doesNotThrow]) in Buffer.add_string buf str_up_to_now; last_offset_in_buf := start_offset @@ -613,7 +613,7 @@ let scan_regex ~start_pos:opening_pos ~prefix_length scanner = let result ~first_char_offset ~last_char_offset = if Buffer.length buf = 0 then - (String.sub [@doesNotRaise]) scanner.src first_char_offset + (String.sub [@doesNotThrow]) scanner.src first_char_offset (last_char_offset - first_char_offset) else ( bring_buf_up_to_date ~start_offset:last_char_offset; @@ -680,7 +680,7 @@ let scan_single_line_comment scanner = (Comment.make_single_line_comment ~loc: Location.{loc_start = start_pos; loc_end = end_pos; loc_ghost = false} - ((String.sub [@doesNotRaise]) scanner.src start_off + ((String.sub [@doesNotThrow]) scanner.src start_off (scanner.offset - start_off))) let scan_multi_line_comment scanner = @@ -725,7 +725,7 @@ let scan_multi_line_comment scanner = loc_end = position scanner; loc_ghost = false; } - ((String.sub [@doesNotRaise]) scanner.src content_start_off length)) + ((String.sub [@doesNotThrow]) scanner.src content_start_off length)) let scan_template_literal_token scanner = let start_off = scanner.offset in @@ -738,7 +738,7 @@ let scan_template_literal_token scanner = | '`' -> next scanner; let contents = - (String.sub [@doesNotRaise]) scanner.src start_off + (String.sub [@doesNotThrow]) scanner.src start_off (scanner.offset - 1 - start_off) in Token.TemplateTail (contents, last_pos) @@ -747,7 +747,7 @@ let scan_template_literal_token scanner = | '{' -> next2 scanner; let contents = - (String.sub [@doesNotRaise]) scanner.src start_off + (String.sub [@doesNotThrow]) scanner.src start_off (scanner.offset - 2 - start_off) in Token.TemplatePart (contents, last_pos) @@ -767,7 +767,7 @@ let scan_template_literal_token scanner = let end_pos = position scanner in scanner.err ~start_pos ~end_pos Diagnostics.unclosed_template; let contents = - (String.sub [@doesNotRaise]) scanner.src start_off + (String.sub [@doesNotThrow]) scanner.src start_off (max (scanner.offset - 1 - start_off) 0) in Token.TemplateTail (contents, last_pos) @@ -1007,7 +1007,7 @@ let rec scan scanner = Token.Codepoint { c = Char.code ch; - original = (String.sub [@doesNotRaise]) scanner.src offset 1; + original = (String.sub [@doesNotThrow]) scanner.src offset 1; } | ch, _ -> next scanner; @@ -1022,7 +1022,7 @@ let rec scan scanner = done; if scanner.ch = '\'' then ( let contents = - (String.sub [@doesNotRaise]) scanner.src offset length + (String.sub [@doesNotThrow]) scanner.src offset length in next scanner; Token.Codepoint {c = codepoint; original = contents}) diff --git a/compiler/syntax/src/res_token.ml b/compiler/syntax/src/res_token.ml index b8639efaed..d282743a2a 100644 --- a/compiler/syntax/src/res_token.ml +++ b/compiler/syntax/src/res_token.ml @@ -264,7 +264,7 @@ let keyword_table = function | "when" -> When | "while" -> While | _ -> raise Not_found -[@@raises Not_found] +[@@throws Not_found] let is_keyword = function | Await | Break | Continue | And | As | Assert | Constraint | Else | Exception @@ -277,7 +277,7 @@ let is_keyword = function let lookup_keyword str = try keyword_table str with Not_found -> ( - match str.[0] [@doesNotRaise] with + match str.[0] [@doesNotThrow] with | 'A' .. 'Z' -> Uident str | _ -> Lident str) diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/expected/exception.txt b/tests/analysis_tests/tests-reanalyze/deadcode/expected/exception.txt index 1c9b93d187..c6dd3c9024 100644 --- a/tests/analysis_tests/tests-reanalyze/deadcode/expected/exception.txt +++ b/tests/analysis_tests/tests-reanalyze/deadcode/expected/exception.txt @@ -120,8 +120,36 @@ ExnFinally.res:7:5-19 throwsInFinally might throw Not_found (ExnFinally.res:11:4) and is not annotated with @throws(Not_found) + Exception Analysis + ExnOldSpellings.res:5:5-23 + oldRaisesAnnotation might throw Not_found (ExnOldSpellings.res:5:32) and is not annotated with @throws(Not_found) + + Exception Analysis + ExnOldSpellings.res:8:5-22 + oldRaiseAnnotation might throw Not_found (ExnOldSpellings.res:8:31) and is not annotated with @throws(Not_found) + + Exception Analysis + ExnOldSpellings.res:11:5-27 + singularThrowAnnotation might throw Not_found (ExnOldSpellings.res:11:36) and is not annotated with @throws(Not_found) + + Exception Analysis + ExnOldSpellings.res:13:5-19 + oldDoesNotRaise might throw Assert_failure (ExnOldSpellings.res:13:42) and is not annotated with @throws(Assert_failure) + + Exception Analysis + ExnOldSpellings.res:15:5-17 + oldDoNotRaise might throw Assert_failure (ExnOldSpellings.res:15:38) and is not annotated with @throws(Assert_failure) + + Exception Analysis + ExnOldSpellings.res:17:5-21 + doNotThrowVariant might throw Assert_failure (ExnOldSpellings.res:17:42) and is not annotated with @throws(Assert_failure) + + Exception Analysis + ExnOldSpellings.res:19:5-25 + lowercaseDoesNotThrow might throw Assert_failure (ExnOldSpellings.res:19:48) and is not annotated with @throws(Assert_failure) + Exception Analysis ExternalTest.res:7:5-24 bigIntFromStringExn2 might throw JsExn (ExternalTest.res:7:35) and is not annotated with @throws(JsExn) - Analysis reported 31 issues (Exception Analysis:31) + Analysis reported 38 issues (Exception Analysis:38) diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/src/exception/ExnOldSpellings.res b/tests/analysis_tests/tests-reanalyze/deadcode/src/exception/ExnOldSpellings.res new file mode 100644 index 0000000000..a161471909 --- /dev/null +++ b/tests/analysis_tests/tests-reanalyze/deadcode/src/exception/ExnOldSpellings.res @@ -0,0 +1,19 @@ +// Only @throws and @doesNotThrow are honored; the other spellings are +// ordinary unknown attributes. + +@raises(Not_found) +let oldRaisesAnnotation = () => throw(Not_found) + +@raise(Not_found) +let oldRaiseAnnotation = () => throw(Not_found) + +@throw(Not_found) +let singularThrowAnnotation = () => throw(Not_found) + +let oldDoesNotRaise = () => @doesNotRaise Belt.Array.getExn([], 0) + +let oldDoNotRaise = () => @doNotRaise Belt.Array.getExn([], 0) + +let doNotThrowVariant = () => @doNotThrow Belt.Array.getExn([], 0) + +let lowercaseDoesNotThrow = () => @doesnotthrow Belt.Array.getExn([], 0)