@@ -521,6 +521,8 @@ let rec forStructureItem ~(env : SharedTypes.Env.t) ~(exported : Exported.t)
521521 (fun {Typedtree. vb_pat; vb_attributes} ->
522522 handlePattern vb_attributes vb_pat)
523523 bindings;
524+ bindings
525+ |> List. iter (fun {Typedtree. vb_expr} -> scanLetModules ~env vb_expr);
524526 ! items
525527 | Tstr_module
526528 {mb_id; mb_attributes; mb_loc; mb_name = name; mb_expr = {mod_desc}}
@@ -630,16 +632,14 @@ and forModule ~env mod_desc moduleName =
630632 | Tmod_functor (ident , argName , maybeType , resultExpr ) ->
631633 (match maybeType with
632634 | None -> ()
633- | Some t -> (
634- match forTreeModuleType ~name: argName.txt ~env t with
635- | None -> ()
636- | Some kind ->
637- let stamp = Ident. binding_time ident in
638- let declared =
639- ProcessAttributes. newDeclared ~item: kind ~name: argName
640- ~extent: t.Typedtree. mty_loc ~stamp ~module Path:NotVisible false []
641- in
642- Stamps. addModule env.stamps stamp declared));
635+ | Some t ->
636+ let kind = forTypeModule ~name: argName.txt ~env t.mty_type in
637+ let stamp = Ident. binding_time ident in
638+ let declared =
639+ ProcessAttributes. newDeclared ~item: kind ~name: argName
640+ ~extent: argName.loc ~stamp ~module Path:NotVisible false []
641+ in
642+ Stamps. addModule env.stamps stamp declared);
643643 forModule ~env resultExpr.mod_desc moduleName
644644 | Tmod_apply (functor_ , _arg , _coercion ) ->
645645 forModule ~env functor_.mod_desc moduleName
@@ -653,6 +653,69 @@ and forModule ~env mod_desc moduleName =
653653 let modTypeKind = forTypeModule ~name: moduleName ~env typ in
654654 Constraint (modKind, modTypeKind)
655655
656+ (*
657+ Walk a typed expression and register any `let module M = ...` bindings as local
658+ modules in stamps. This makes trailing-dot completion work for aliases like `M.`
659+ that are introduced inside expression scopes. The declared module is marked as
660+ NotVisible (non-exported) and the extent is the alias identifier location so
661+ scope lookups match precisely.
662+ *)
663+ and scanLetModules ~env (e : Typedtree.expression ) =
664+ match e.exp_desc with
665+ | Texp_letmodule (id , name , mexpr , body ) ->
666+ let stamp = Ident. binding_time id in
667+ let item = forModule ~env mexpr.mod_desc name.txt in
668+ let declared =
669+ ProcessAttributes. newDeclared ~item ~extent: name.loc ~name ~stamp
670+ ~module Path:NotVisible false []
671+ in
672+ Stamps. addModule env.stamps stamp declared;
673+ scanLetModules ~env body
674+ | Texp_let (_rf , bindings , body ) ->
675+ List. iter (fun {Typedtree. vb_expr} -> scanLetModules ~env vb_expr) bindings;
676+ scanLetModules ~env body
677+ | Texp_apply {funct; args; _} ->
678+ scanLetModules ~env funct;
679+ args
680+ |> List. iter (function
681+ | _ , Some e -> scanLetModules ~env e
682+ | _ , None -> () )
683+ | Texp_tuple exprs -> List. iter (scanLetModules ~env ) exprs
684+ | Texp_sequence (e1 , e2 ) ->
685+ scanLetModules ~env e1;
686+ scanLetModules ~env e2
687+ | Texp_match (e , cases , exn_cases , _ ) ->
688+ scanLetModules ~env e;
689+ let scan_case {Typedtree. c_lhs = _ ; c_guard; c_rhs} =
690+ (match c_guard with
691+ | Some g -> scanLetModules ~env g
692+ | None -> () );
693+ scanLetModules ~env c_rhs
694+ in
695+ List. iter scan_case cases;
696+ List. iter scan_case exn_cases
697+ | Texp_function {case; _} ->
698+ let {Typedtree. c_lhs = _; c_guard; c_rhs} = case in
699+ (match c_guard with
700+ | Some g -> scanLetModules ~env g
701+ | None -> () );
702+ scanLetModules ~env c_rhs
703+ | Texp_try (e , cases ) ->
704+ scanLetModules ~env e;
705+ cases
706+ |> List. iter (fun {Typedtree. c_lhs = _ ; c_guard; c_rhs} ->
707+ (match c_guard with
708+ | Some g -> scanLetModules ~env g
709+ | None -> () );
710+ scanLetModules ~env c_rhs)
711+ | Texp_ifthenelse (e1 , e2 , e3Opt ) -> (
712+ scanLetModules ~env e1;
713+ scanLetModules ~env e2;
714+ match e3Opt with
715+ | Some e3 -> scanLetModules ~env e3
716+ | None -> () )
717+ | _ -> ()
718+
656719and forStructure ~name ~env strItems =
657720 let exported = Exported. init () in
658721 let items =
0 commit comments