[ty] Add completions for submodule imports

While we did previously support submodule completions via our
`all_members` API, that only works when submodules are attributes of
their parent module. For example, `os.path`. But that didn't work when
the submodule was not an attribute of its parent. For example,
`http.client`. To make the latter work, we read the directory of the
parent module to discover its submodules.
This commit is contained in:
Alex Waygood 2025-06-25 14:55:16 +01:00 committed by Andrew Gallant
parent 948463aafa
commit c9df4ddf6a
4 changed files with 163 additions and 8 deletions

View file

@ -69,14 +69,29 @@ impl<'db> SemanticModel<'db> {
};
let ty = Type::module_literal(self.db, self.file, &module);
let builtin = module.is_known(KnownModule::Builtins);
crate::types::all_members(self.db, ty)
.into_iter()
.map(|member| Completion {
name: member.name,
ty: member.ty,
let mut completions = vec![];
for crate::types::Member { name, ty } in crate::types::all_members(self.db, ty) {
completions.push(Completion { name, ty, builtin });
}
for submodule_basename in module.all_submodules(self.db) {
let Some(basename) = ModuleName::new(submodule_basename.as_str()) else {
continue;
};
let mut submodule_name = module_name.clone();
submodule_name.extend(&basename);
let Some(submodule) = resolve_module(self.db, &submodule_name) else {
continue;
};
let ty = Type::module_literal(self.db, self.file, &submodule);
completions.push(Completion {
name: submodule_basename,
ty,
builtin,
})
.collect()
});
}
completions
}
/// Returns completions for symbols available in a `object.<CURSOR>` context.