@@ -756,6 +756,72 @@ let getCompletionsForPath ~debug ~opens ~full ~pos ~exact ~scope
756756 findAllCompletions ~env ~prefix ~exact ~names Used ~completion Context
757757 | None -> [] ))
758758
759+ (* Collect exception constructor names from cmt infos. *)
760+ let exceptions_from_cmt_infos (infos : Cmt_format.cmt_infos ) :
761+ (string * bool ) list =
762+ let by_name : (string, bool) Hashtbl.t = Hashtbl. create 16 in
763+ let add_ext (ext : Typedtree.extension_constructor ) : unit =
764+ let name = ext.ext_name.txt in
765+ let hasArgs =
766+ match ext.ext_kind with
767+ | Text_decl (Cstr_tuple args , _ret ) -> args <> []
768+ | Text_decl (Cstr_record fields , _ret ) -> fields <> []
769+ | Text_rebind _ -> true
770+ in
771+ let prev =
772+ match Hashtbl. find_opt by_name name with
773+ | Some b -> b
774+ | None -> false
775+ in
776+ Hashtbl. replace by_name name (prev || hasArgs)
777+ in
778+ let rec of_structure_items (items : Typedtree.structure_item list ) : unit =
779+ match items with
780+ | [] -> ()
781+ | item :: rest ->
782+ (match item.str_desc with
783+ | Tstr_exception ext -> add_ext ext
784+ | _ -> () );
785+ of_structure_items rest
786+ in
787+ let rec of_signature_items (items : Typedtree.signature_item list ) : unit =
788+ match items with
789+ | [] -> ()
790+ | item :: rest ->
791+ (match item.sig_desc with
792+ | Tsig_exception ext -> add_ext ext
793+ | _ -> () );
794+ of_signature_items rest
795+ in
796+ let of_parts (parts : Cmt_format.binary_part array ) : unit =
797+ Array. iter
798+ (function
799+ | Cmt_format. Partial_structure s -> of_structure_items s.str_items
800+ | Partial_structure_item si -> of_structure_items [si]
801+ | Partial_signature s -> of_signature_items s.sig_items
802+ | Partial_signature_item si -> of_signature_items [si]
803+ | _ -> () )
804+ parts
805+ in
806+ (match infos.cmt_annots with
807+ | Cmt_format. Implementation s -> of_structure_items s.str_items
808+ | Interface s -> of_signature_items s.sig_items
809+ | Partial_implementation parts -> of_parts parts
810+ | Partial_interface parts -> of_parts parts
811+ | _ -> () );
812+ Hashtbl. fold (fun name hasArgs acc -> (name, hasArgs) :: acc) by_name []
813+
814+ (* Predefined Stdlib/Pervasives exceptions. *)
815+ let predefined_exceptions : (string * bool) list =
816+ [
817+ (" Not_found" , true );
818+ (" Invalid_argument" , true );
819+ (" Assert_failure" , true );
820+ (" Failure" , true );
821+ (" Match_failure" , true );
822+ (" Division_by_zero" , false );
823+ ]
824+
759825(* * Completions intended for piping, from a completion path. *)
760826let completionsForPipeFromCompletionPath ~envCompletionIsMadeFrom ~opens ~pos
761827 ~scope ~debug ~prefix ~env ~rawOpens ~full completionPath =
@@ -1010,6 +1076,33 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
10101076 | Some (Tpromise (env , typ ), _env ) ->
10111077 [Completion. create " dummy" ~env ~kind: (Completion. Value typ)]
10121078 | _ -> [] )
1079+ | CPId {path = [" throw" ]; completionContext = Value ; loc = _ } ->
1080+ let exn_typ = Ctype. newconstr Predef. path_exn [] in
1081+ let names_from_cmt =
1082+ let moduleName = env.file.moduleName in
1083+ match Hashtbl. find_opt full.package.pathsForModule moduleName with
1084+ | None -> []
1085+ | Some paths -> (
1086+ let uri = getUri paths in
1087+ let cmt_path = getCmtPath ~uri paths in
1088+ match Shared. tryReadCmt cmt_path with
1089+ | None -> []
1090+ | Some infos -> exceptions_from_cmt_infos infos)
1091+ in
1092+ let all = names_from_cmt @ predefined_exceptions in
1093+ all
1094+ |> List. map (fun (name , hasArgs ) ->
1095+ let insertText =
1096+ if hasArgs then Printf. sprintf " (%s($0))" name
1097+ else Printf. sprintf " (%s)" name
1098+ in
1099+ let isBuiltin = List. mem (name, hasArgs) predefined_exceptions in
1100+ let detail =
1101+ if isBuiltin then " Built-in Exception"
1102+ else " User-defined Exception"
1103+ in
1104+ Completion. create name ~env ~kind: (Completion. Value exn_typ)
1105+ ~includes Snippets:true ~insert Text ~detail )
10131106 | CPId {path; completionContext; loc} ->
10141107 if Debug. verbose () then print_endline " [ctx_path]--> CPId" ;
10151108 (* Looks up the type of an identifier.
0 commit comments