|
15 | 15 |
|
16 | 16 | open Asttypes
|
17 | 17 | open Parsetree
|
| 18 | +open Ast_helper |
| 19 | + |
| 20 | + |
| 21 | +module Attribute_table = Hashtbl.Make (struct |
| 22 | + type t = string with_loc |
| 23 | + |
| 24 | + let hash : t -> int = Hashtbl.hash |
| 25 | + let equal : t -> t -> bool = (=) |
| 26 | +end) |
| 27 | +let unused_attrs = Attribute_table.create 128 |
| 28 | +let mark_used t = Attribute_table.remove unused_attrs t |
| 29 | + |
| 30 | +(* [attr_order] is used to issue unused attribute warnings in the order the |
| 31 | + attributes occur in the file rather than the random order of the hash table |
| 32 | +*) |
| 33 | +let attr_order a1 a2 = |
| 34 | + match String.compare a1.loc.loc_start.pos_fname a2.loc.loc_start.pos_fname |
| 35 | + with |
| 36 | + | 0 -> Int.compare a1.loc.loc_start.pos_cnum a2.loc.loc_start.pos_cnum |
| 37 | + | n -> n |
| 38 | + |
| 39 | +let warn_unused () = |
| 40 | + let keys = List.of_seq (Attribute_table.to_seq_keys unused_attrs) in |
| 41 | + let keys = List.sort attr_order keys in |
| 42 | + List.iter (fun sloc -> |
| 43 | + Location.prerr_warning sloc.loc (Warnings.Misplaced_attribute sloc.txt)) |
| 44 | + keys |
| 45 | + |
| 46 | +(* These are the attributes that are tracked in the builtin_attrs table for |
| 47 | + misplaced attribute warnings. *) |
| 48 | +let builtin_attrs = |
| 49 | + [ (* "alert"; "ocaml.alert" *) |
| 50 | + (* ; "boxed"; "ocaml.boxed" *) |
| 51 | + (* ; "deprecated"; "ocaml.deprecated" *) |
| 52 | + (* ; "deprecated_mutable"; "ocaml.deprecated_mutable" *) |
| 53 | + (* ; "explicit_arity"; "ocaml.explicit_arity" *) |
| 54 | + (* ; "immediate"; "ocaml.immediate" *) |
| 55 | + (* ; "immediate64"; "ocaml.immediate64" *) |
| 56 | + (* ; "inline"; "ocaml.inline" *) |
| 57 | + (* ; "inlined"; "ocaml.inlined" *) |
| 58 | + (* ; "noalloc"; "ocaml.noalloc" *) |
| 59 | + (* ; "ppwarning"; "ocaml.ppwarning" *) |
| 60 | + (* ; "tailcall"; "ocaml.tailcall" *) |
| 61 | + (* ; "unboxed"; "ocaml.unboxed" *) |
| 62 | + (* ; "untagged"; "ocaml.untagged" *) |
| 63 | + (* ; "unrolled"; "ocaml.unrolled" *) |
| 64 | + (* ; "warnerror"; "ocaml.warnerror" *) |
| 65 | + (* ; "warning"; "ocaml.warning" *) |
| 66 | + (* ; "warn_on_literal_pattern"; "ocaml.warn_on_literal_pattern" *) |
| 67 | + ] |
| 68 | + |
| 69 | +let builtin_attrs = |
| 70 | + let tbl = Hashtbl.create 128 in |
| 71 | + List.iter (fun attr -> Hashtbl.add tbl attr ()) builtin_attrs; |
| 72 | + tbl |
| 73 | + |
| 74 | +let is_builtin_attr s = Hashtbl.mem builtin_attrs s |
| 75 | + |
| 76 | +type attr_tracking_time = Parser | Invariant_check |
| 77 | + |
| 78 | +let register_attr attr_tracking_time name = |
| 79 | + match attr_tracking_time with |
| 80 | + | Parser when !Clflags.all_ppx <> [] -> () |
| 81 | + | Parser | Invariant_check -> |
| 82 | + if is_builtin_attr name.txt then |
| 83 | + Attribute_table.replace unused_attrs name () |
18 | 84 |
|
19 | 85 | let string_of_cst = function
|
20 | 86 | | Pconst_string(s, _, _) -> Some s
|
@@ -67,6 +133,16 @@ let error_of_extension ext =
|
67 | 133 | | ({txt; loc}, _) ->
|
68 | 134 | Location.errorf ~loc "Uninterpreted extension '%s'." txt
|
69 | 135 |
|
| 136 | +let mark_payload_attrs_used payload = |
| 137 | + let iter = |
| 138 | + { Ast_iterator.default_iterator |
| 139 | + with attribute = fun self a -> |
| 140 | + mark_used a.attr_name; |
| 141 | + Ast_iterator.default_iterator.attribute self a |
| 142 | + } |
| 143 | + in |
| 144 | + iter.payload iter payload |
| 145 | + |
70 | 146 | let kind_and_message = function
|
71 | 147 | | PStr[
|
72 | 148 | {pstr_desc=
|
|
0 commit comments