cairo_lang_semantic/
lsp_helpers.rs

1use std::sync::Arc;
2
3use cairo_lang_defs::db::DefsGroup;
4use cairo_lang_defs::ids::{
5    GenericTypeId, ImportableId, LanguageElementId, ModuleId, ModuleItemId, NamedLanguageElementId,
6    TraitFunctionId, TraitId,
7};
8use cairo_lang_filesystem::db::{CORELIB_CRATE_NAME, FilesGroup, default_crate_settings};
9use cairo_lang_filesystem::ids::{CrateId, CrateLongId, FileId, SmolStrId, Tracked};
10use cairo_lang_syntax::node::ast::ItemModule;
11use cairo_lang_syntax::node::helpers::GetIdentifier;
12use cairo_lang_syntax::node::{SyntaxNode, TypedSyntaxNode};
13use cairo_lang_utils::Intern;
14use cairo_lang_utils::ordered_hash_map::{Entry, OrderedHashMap};
15use cairo_lang_utils::unordered_hash_set::UnorderedHashSet;
16use itertools::chain;
17use salsa::Database;
18
19use crate::expr::inference::InferenceId;
20use crate::items::constant::ConstantSemantic;
21use crate::items::enm::EnumSemantic;
22use crate::items::free_function::FreeFunctionSemantic;
23use crate::items::functions::GenericFunctionId;
24use crate::items::imp::ImplSemantic;
25use crate::items::macro_call::{MacroCallSemantic, module_macro_modules};
26use crate::items::module::ModuleSemantic;
27use crate::items::module_type_alias::ModuleTypeAliasSemantic;
28use crate::items::trt::TraitSemantic;
29use crate::items::us::SemanticUseEx;
30use crate::keyword::SELF_PARAM_KW;
31use crate::resolve::{ResolvedGenericItem, Resolver};
32use crate::types::TypeHead;
33use crate::{Variant, corelib};
34
35/// A filter for types.
36#[derive(Clone, Debug, Hash, PartialEq, Eq)]
37pub enum TypeFilter<'db> {
38    /// No filter is applied.
39    NoFilter,
40    /// Only methods with the given type head are returned.
41    TypeHead(TypeHead<'db>),
42}
43
44/// Implementation of [LspHelpers::methods_in_module].
45pub fn methods_in_module<'db>(
46    db: &'db dyn Database,
47    module_id: ModuleId<'db>,
48    type_filter: TypeFilter<'db>,
49) -> Arc<Vec<TraitFunctionId<'db>>> {
50    let mut result = Vec::new();
51    let Ok(module_traits_ids) = db.module_traits_ids(module_id) else {
52        return result.into();
53    };
54    for trait_id in module_traits_ids.iter().copied() {
55        if let Ok(trait_functions) = db.trait_functions(trait_id) {
56            for trait_function in trait_functions.values() {
57                let Ok(signature) = db.trait_function_signature(*trait_function) else {
58                    continue;
59                };
60                let Some(first_param) = signature.params.first() else {
61                    continue;
62                };
63                if first_param.name.long(db) != SELF_PARAM_KW {
64                    continue;
65                }
66                if let TypeFilter::TypeHead(type_head) = &type_filter
67                    && let Some(head) = first_param.ty.head(db)
68                    && !fit_for_method(&head, type_head)
69                {
70                    continue;
71                }
72
73                result.push(*trait_function)
74            }
75        }
76    }
77    Arc::new(result)
78}
79
80/// Query implementation of [LspHelpers::methods_in_module].
81#[salsa::tracked]
82pub fn methods_in_module_tracked<'db>(
83    db: &'db dyn Database,
84    module_id: ModuleId<'db>,
85    type_filter: TypeFilter<'db>,
86) -> Arc<Vec<TraitFunctionId<'db>>> {
87    methods_in_module(db, module_id, type_filter)
88}
89
90/// Checks if a type head can fit for a method.
91fn fit_for_method(head: &TypeHead<'_>, type_head: &TypeHead<'_>) -> bool {
92    // Allow generics so we can filter them later with resolver.
93    if let TypeHead::Generic(_) = head {
94        return true;
95    }
96    if head == type_head {
97        return true;
98    }
99    if let TypeHead::Snapshot(snapshot_head) = head {
100        return fit_for_method(snapshot_head.as_ref(), type_head);
101    }
102    false
103}
104
105/// Implementation of [LspHelpers::methods_in_crate].
106pub fn methods_in_crate<'db>(
107    db: &'db dyn Database,
108    crate_id: CrateId<'db>,
109    type_filter: TypeFilter<'db>,
110) -> Arc<Vec<TraitFunctionId<'db>>> {
111    let mut result = Vec::new();
112    for module_id in db.crate_modules(crate_id).iter() {
113        result.extend_from_slice(&db.methods_in_module(*module_id, type_filter.clone())[..])
114    }
115    Arc::new(result)
116}
117
118/// Query implementation of [LspHelpers::methods_in_crate].
119#[salsa::tracked]
120pub fn methods_in_crate_tracked<'db>(
121    db: &'db dyn Database,
122    crate_id: CrateId<'db>,
123    type_filter: TypeFilter<'db>,
124) -> Arc<Vec<TraitFunctionId<'db>>> {
125    methods_in_crate(db, crate_id, type_filter)
126}
127
128/// Implementation of [LspHelpers::visible_importables_in_module].
129pub fn visible_importables_in_module<'db>(
130    db: &'db dyn Database,
131    module_id: ModuleId<'db>,
132    user_module_id: ModuleId<'db>,
133    include_parent: bool,
134) -> Arc<Vec<(ImportableId<'db>, String)>> {
135    let mut visited_modules = UnorderedHashSet::default();
136    visible_importables_in_module_ex(
137        db,
138        module_id,
139        user_module_id,
140        include_parent,
141        &mut visited_modules,
142    )
143    .unwrap_or_else(|| Arc::new(Vec::new()))
144}
145
146/// Query implementation of [LspHelpers::visible_importables_in_module].
147#[salsa::tracked]
148pub fn visible_importables_in_module_tracked<'db>(
149    db: &'db dyn Database,
150    module_id: ModuleId<'db>,
151    user_module_id: ModuleId<'db>,
152    include_parent: bool,
153) -> Arc<Vec<(ImportableId<'db>, String)>> {
154    visible_importables_in_module(db, module_id, user_module_id, include_parent)
155}
156
157/// Returns the visible importables in a module, including the importables in the parent module if
158/// needed. The visibility is relative to the module `user_module_id`.
159fn visible_importables_in_module_ex<'db>(
160    db: &'db dyn Database,
161    module_id: ModuleId<'db>,
162    user_module_id: ModuleId<'db>,
163    include_parent: bool,
164    visited_modules: &mut UnorderedHashSet<ModuleId<'db>>,
165) -> Option<Arc<Vec<(ImportableId<'db>, String)>>> {
166    let mut result = Vec::new();
167    if visited_modules.contains(&module_id) {
168        return Some(result.into());
169    }
170
171    let resolver = Resolver::new(db, user_module_id, InferenceId::NoContext);
172
173    // Check if an item in the current module is visible from the user module.
174    let is_visible = |item_name: SmolStrId<'_>| {
175        let item_info = db.module_item_info_by_name(module_id, item_name).ok()??;
176        Some(resolver.is_item_visible(module_id, &item_info, user_module_id))
177    };
178    visited_modules.insert(module_id);
179    let mut modules_to_visit = vec![];
180    // Add importables and traverse modules imported into the current module.
181    for use_id in db.module_uses_ids(module_id).unwrap_or_default().iter().copied() {
182        if !is_visible(use_id.name(db)).unwrap_or_default() {
183            continue;
184        }
185        let Ok(resolved_item) = db.use_resolved_item(use_id) else {
186            continue;
187        };
188
189        let (resolved_item, name) = match resolved_item {
190            ResolvedGenericItem::Module(ModuleId::CrateRoot(crate_id)) => {
191                result.extend_from_slice(&db.visible_importables_in_crate(crate_id, module_id)[..]);
192
193                (ImportableId::Crate(crate_id), crate_id.long(db).name().long(db))
194            }
195            ResolvedGenericItem::Module(inner_module_id @ ModuleId::Submodule(module)) => {
196                modules_to_visit.push(inner_module_id);
197
198                (ImportableId::Submodule(module), module.name(db).long(db))
199            }
200            ResolvedGenericItem::Module(ModuleId::MacroCall { .. }) => {
201                continue;
202            }
203            ResolvedGenericItem::GenericConstant(item_id) => {
204                (ImportableId::Constant(item_id), item_id.name(db).long(db))
205            }
206            ResolvedGenericItem::GenericFunction(GenericFunctionId::Free(item_id)) => {
207                (ImportableId::FreeFunction(item_id), item_id.name(db).long(db))
208            }
209            ResolvedGenericItem::GenericFunction(GenericFunctionId::Extern(item_id)) => {
210                (ImportableId::ExternFunction(item_id), item_id.name(db).long(db))
211            }
212            ResolvedGenericItem::GenericType(GenericTypeId::Struct(item_id)) => {
213                (ImportableId::Struct(item_id), item_id.name(db).long(db))
214            }
215            ResolvedGenericItem::GenericType(GenericTypeId::Enum(item_id)) => {
216                let enum_name = item_id.name(db);
217
218                if let Ok(variants) = db.enum_variants(item_id) {
219                    for (name, id) in variants.iter() {
220                        result.push((
221                            ImportableId::Variant(*id),
222                            format!("{}::{}", enum_name.long(db), name.long(db)),
223                        ));
224                    }
225                }
226
227                (ImportableId::Enum(item_id), enum_name.long(db))
228            }
229            ResolvedGenericItem::GenericType(GenericTypeId::Extern(item_id)) => {
230                (ImportableId::ExternType(item_id), item_id.name(db).long(db))
231            }
232            ResolvedGenericItem::GenericTypeAlias(item_id) => {
233                (ImportableId::TypeAlias(item_id), item_id.name(db).long(db))
234            }
235            ResolvedGenericItem::GenericImplAlias(item_id) => {
236                (ImportableId::ImplAlias(item_id), item_id.name(db).long(db))
237            }
238            ResolvedGenericItem::Variant(Variant { id, .. }) => {
239                (ImportableId::Variant(id), id.name(db).long(db))
240            }
241            ResolvedGenericItem::Trait(item_id) => {
242                (ImportableId::Trait(item_id), item_id.name(db).long(db))
243            }
244            ResolvedGenericItem::Impl(item_id) => {
245                (ImportableId::Impl(item_id), item_id.name(db).long(db))
246            }
247            ResolvedGenericItem::Macro(item_id) => {
248                (ImportableId::MacroDeclaration(item_id), item_id.name(db).long(db))
249            }
250            ResolvedGenericItem::Variable(_)
251            | ResolvedGenericItem::TraitItem(_)
252            | ResolvedGenericItem::GenericFunction(GenericFunctionId::Impl(_)) => continue,
253        };
254
255        result.push((resolved_item, name.to_string()));
256    }
257
258    if !matches!(module_id, ModuleId::MacroCall { .. }) {
259        modules_to_visit.extend(module_macro_modules(db, false, module_id).iter().copied());
260    }
261
262    for submodule_id in db.module_submodules_ids(module_id).unwrap_or_default().iter().copied() {
263        if !is_visible(submodule_id.name(db)).unwrap_or_default() {
264            continue;
265        }
266        result.push((ImportableId::Submodule(submodule_id), submodule_id.name(db).to_string(db)));
267        modules_to_visit.push(ModuleId::Submodule(submodule_id));
268    }
269
270    // Handle enums separately because we need to include their variants.
271    for enum_id in db.module_enums_ids(module_id).unwrap_or_default().iter().copied() {
272        let enum_name = enum_id.name(db);
273        if !is_visible(enum_name).unwrap_or_default() {
274            continue;
275        }
276
277        result.push((ImportableId::Enum(enum_id), enum_name.to_string(db)));
278
279        if let Ok(variants) = db.enum_variants(enum_id) {
280            for (name, id) in variants.iter() {
281                result.push((
282                    ImportableId::Variant(*id),
283                    format!("{}::{}", enum_name.long(db), name.long(db)),
284                ));
285            }
286        }
287    }
288
289    macro_rules! module_importables {
290        ($query:ident, $map:expr) => {
291            for item_id in db.$query(module_id).ok().unwrap_or_default().iter().copied() {
292                if !is_visible(item_id.name(db)).unwrap_or_default() {
293                    continue;
294                }
295                result.push(($map(item_id), item_id.name(db).to_string(db)));
296            }
297        };
298    }
299
300    module_importables!(module_constants_ids, ImportableId::Constant);
301    module_importables!(module_free_functions_ids, ImportableId::FreeFunction);
302    module_importables!(module_structs_ids, ImportableId::Struct);
303    module_importables!(module_type_aliases_ids, ImportableId::TypeAlias);
304    module_importables!(module_impl_aliases_ids, ImportableId::ImplAlias);
305    module_importables!(module_traits_ids, ImportableId::Trait);
306    module_importables!(module_impls_ids, ImportableId::Impl);
307    module_importables!(module_extern_functions_ids, ImportableId::ExternFunction);
308    module_importables!(module_extern_types_ids, ImportableId::ExternType);
309    module_importables!(module_macro_declarations_ids, ImportableId::MacroDeclaration);
310
311    for submodule in modules_to_visit {
312        for (item_id, path) in
313            visible_importables_in_module_ex(db, submodule, user_module_id, false, visited_modules)
314                .unwrap_or_default()
315                .iter()
316        {
317            result.push((*item_id, format!("{}::{}", submodule.name(db).long(db), path)));
318        }
319    }
320    // Traverse the parent module if needed.
321    if include_parent {
322        match module_id {
323            ModuleId::CrateRoot(_) => {}
324            ModuleId::Submodule(submodule_id) => {
325                let parent_module_id = submodule_id.parent_module(db);
326                for (item_id, path) in visible_importables_in_module_ex(
327                    db,
328                    parent_module_id,
329                    user_module_id,
330                    include_parent,
331                    visited_modules,
332                )
333                .unwrap_or_default()
334                .iter()
335                {
336                    result.push((*item_id, format!("super::{path}")));
337                }
338            }
339            ModuleId::MacroCall { .. } => {}
340        }
341    }
342    Some(Arc::new(result))
343}
344
345/// Implementation of [LspHelpers::visible_importables_in_crate].
346pub fn visible_importables_in_crate<'db>(
347    db: &'db dyn Database,
348    crate_id: CrateId<'db>,
349    user_module_id: ModuleId<'db>,
350) -> Arc<Vec<(ImportableId<'db>, String)>> {
351    let is_current_crate = user_module_id.owning_crate(db) == crate_id;
352    let crate_name = if is_current_crate { "crate" } else { crate_id.long(db).name().long(db) };
353    let crate_as_module = ModuleId::CrateRoot(crate_id);
354    db.visible_importables_in_module(crate_as_module, user_module_id, false)
355        .iter()
356        .map(|(item_id, path)| (*item_id, format!("{crate_name}::{path}")))
357        .collect::<Vec<_>>()
358        .into()
359}
360
361/// Query implementation of [LspHelpers::visible_importables_in_crate].
362#[salsa::tracked]
363pub fn visible_importables_in_crate_tracked<'db>(
364    db: &'db dyn Database,
365    crate_id: CrateId<'db>,
366    user_module_id: ModuleId<'db>,
367) -> Arc<Vec<(ImportableId<'db>, String)>> {
368    visible_importables_in_crate(db, crate_id, user_module_id)
369}
370
371/// Implementation of [LspHelpers::visible_importables_from_module].
372pub fn visible_importables_from_module<'db>(
373    db: &'db dyn Database,
374    module_id: ModuleId<'db>,
375) -> Option<Arc<OrderedHashMap<ImportableId<'db>, String>>> {
376    let current_crate_id = module_id.owning_crate(db);
377    let prelude_submodule =
378        db.get_prelude_submodule(&db.crate_config(current_crate_id)?.settings)?;
379
380    let mut module_visible_importables = Vec::new();
381    // Collect importables from the prelude.
382    module_visible_importables.extend_from_slice(
383        &db.visible_importables_in_module(prelude_submodule, prelude_submodule, false)[..],
384    );
385    // Collect importables from all dependency crates, including the current crate and corelib.
386    let settings = db
387        .crate_config(current_crate_id)
388        .map(|c| &c.settings)
389        .unwrap_or_else(|| default_crate_settings(db));
390    for crate_id in chain!(
391        [current_crate_id],
392        (!settings.dependencies.contains_key(CORELIB_CRATE_NAME)).then(|| corelib::core_crate(db)),
393        settings.dependencies.iter().map(|(name, setting)| {
394            CrateLongId::Real {
395                name: SmolStrId::from(db, name.clone()),
396                discriminator: setting.discriminator.clone(),
397            }
398            .intern(db)
399        })
400    ) {
401        module_visible_importables
402            .extend_from_slice(&db.visible_importables_in_crate(crate_id, module_id)[..]);
403        module_visible_importables
404            .push((ImportableId::Crate(crate_id), crate_id.long(db).name().to_string(db)));
405    }
406
407    // Collect importables visible in the current module.
408    module_visible_importables
409        .extend_from_slice(&db.visible_importables_in_module(module_id, module_id, true)[..]);
410
411    // Deduplicate importables, preferring shorter paths.
412    // This is the reason for searching in the crates before the current module - to prioritize
413    // shorter, canonical paths prefixed with `crate::` over paths using `super::` or local
414    // imports.
415    let mut result: OrderedHashMap<ImportableId<'_>, String> = OrderedHashMap::default();
416    for (trait_id, path) in module_visible_importables {
417        match result.entry(trait_id) {
418            Entry::Occupied(existing_path) => {
419                if path.split("::").count() < existing_path.get().split("::").count() {
420                    *existing_path.into_mut() = path;
421                }
422            }
423            Entry::Vacant(entry) => {
424                entry.insert(path);
425            }
426        }
427    }
428    Some(Arc::new(result))
429}
430
431/// Query implementation of [LspHelpers::visible_importables_from_module].
432pub fn visible_importables_from_module_tracked<'db>(
433    db: &'db dyn Database,
434    module_id: ModuleId<'db>,
435) -> Option<Arc<OrderedHashMap<ImportableId<'db>, String>>> {
436    visible_importables_from_module_helper(db, (), module_id)
437}
438
439#[salsa::tracked]
440fn visible_importables_from_module_helper<'db>(
441    db: &'db dyn Database,
442    _tracked: Tracked,
443    module_id: ModuleId<'db>,
444) -> Option<Arc<OrderedHashMap<ImportableId<'db>, String>>> {
445    visible_importables_from_module(db, module_id)
446}
447
448/// Implementation of [LspHelpers::visible_traits_from_module].
449pub fn visible_traits_from_module<'db>(
450    db: &'db dyn Database,
451    module_id: ModuleId<'db>,
452) -> Option<Arc<OrderedHashMap<TraitId<'db>, String>>> {
453    let importables = db.visible_importables_from_module(module_id)?;
454
455    let traits = importables
456        .iter()
457        .filter_map(|(item, path)| {
458            if let ImportableId::Trait(trait_id) = item {
459                Some((*trait_id, path.clone()))
460            } else {
461                None
462            }
463        })
464        .collect::<OrderedHashMap<_, _>>()
465        .into();
466
467    Some(traits)
468}
469
470/// Query implementation of [LspHelpers::visible_traits_from_module].
471fn visible_traits_from_module_tracked<'db>(
472    db: &'db dyn Database,
473    module_id: ModuleId<'db>,
474) -> Option<Arc<OrderedHashMap<TraitId<'db>, String>>> {
475    visible_traits_from_module_helper(db, (), module_id)
476}
477
478#[salsa::tracked]
479fn visible_traits_from_module_helper<'db>(
480    db: &'db dyn Database,
481    _tracked: Tracked,
482    module_id: ModuleId<'db>,
483) -> Option<Arc<OrderedHashMap<TraitId<'db>, String>>> {
484    visible_traits_from_module(db, module_id)
485}
486
487/// Query implementation of [LspHelpers::inline_macro_expansion_files].
488#[salsa::tracked(returns(ref))]
489fn inline_macro_expansion_files_tracked<'db>(
490    db: &'db dyn Database,
491    _tracked: Tracked,
492    module_id: ModuleId<'db>,
493) -> Vec<FileId<'db>> {
494    let mut files = vec![];
495    if let Ok(module_macro_calls_ids) = db.module_macro_calls_ids(module_id) {
496        for macro_call in module_macro_calls_ids {
497            if let Ok(macro_call_data) = db.priv_macro_call_data(*macro_call)
498                && let Ok(ModuleId::MacroCall { generated_file_id, .. }) =
499                    macro_call_data.macro_call_module
500            {
501                files.push(generated_file_id);
502            }
503        }
504    }
505    if let Ok(traits) = db.module_traits_ids(module_id) {
506        for trait_id in traits {
507            if let Ok(trait_functions) = db.trait_functions(*trait_id) {
508                for trait_function_id in trait_functions.values() {
509                    if let Ok(Some(data)) = db.trait_function_body_resolver_data(*trait_function_id)
510                    {
511                        files.extend(data.files.iter().copied())
512                    }
513                }
514            }
515        }
516    }
517    if let Ok(impls) = db.module_impls_ids(module_id) {
518        for impls_id in impls {
519            if let Ok(impl_functions) = db.impl_functions(*impls_id) {
520                for impl_function_id in impl_functions.values() {
521                    if let Ok(data) = db.impl_function_body_resolver_data(*impl_function_id) {
522                        files.extend(data.files.iter().copied())
523                    }
524                }
525            }
526        }
527    }
528    if let Ok(free_functions) = db.module_free_functions_ids(module_id) {
529        for free_function_id in free_functions {
530            if let Ok(data) = db.free_function_body_resolver_data(*free_function_id) {
531                files.extend(data.files.iter().copied())
532            }
533        }
534    }
535    if let Ok(constants) = db.module_constants_ids(module_id) {
536        for constant_id in constants {
537            if let Ok(data) = db.constant_resolver_data(*constant_id) {
538                files.extend(data.files.iter().copied())
539            }
540        }
541    }
542    if let Ok(type_aliases) = db.module_type_aliases_ids(module_id) {
543        for type_alias_id in type_aliases {
544            if let Ok(data) = db.module_type_alias_resolver_data(*type_alias_id) {
545                files.extend(data.files.iter().copied())
546            }
547        }
548    }
549
550    files
551}
552
553#[salsa::tracked]
554fn find_module_containing_node<'db>(
555    db: &'db dyn Database,
556    _tracked: Tracked,
557    node: SyntaxNode<'db>,
558) -> Option<ModuleId<'db>> {
559    // Get the main module of the main file containing the node.
560    // The node may be located in a virtual file of a submodule.
561    let main_module = {
562        // Get the file where the node is located.
563        // This might be a virtual file generated by a compiler plugin.
564        let node_file_id = node.stable_ptr(db).file_id(db);
565
566        // Get the root module of a file containing the node.
567        *db.file_modules(node_file_id).ok()?.first()?
568    };
569
570    // Get the stack (bottom-up) of submodule names in the file containing the node, in the main
571    // module, that lead to the node.
572    node.ancestors(db)
573        .filter_map(|node| ItemModule::cast(db, node))
574        .map(|item_module| {
575            item_module
576                .stable_ptr(db)
577                .name_green(db)
578                .identifier(db)
579        })
580        // Buffer the stack to get DoubleEndedIterator.
581        .collect::<Vec<_>>()
582        .into_iter()
583        // And get id of the (sub)module containing the node by traversing this stack top-down.
584        .try_rfold(main_module, |module, name| {
585            let ModuleItemId::Submodule(submodule) =
586                db.module_item_by_name(module, name).ok()??
587            else {
588                return None;
589            };
590            Some(ModuleId::Submodule(submodule))
591        })
592}
593
594/// Trait for LSP helpers.
595pub trait LspHelpers<'db>: Database {
596    /// Returns all methods in a module that match the given type filter.
597    fn methods_in_module(
598        &'db self,
599        module_id: ModuleId<'db>,
600        type_filter: TypeFilter<'db>,
601    ) -> Arc<Vec<TraitFunctionId<'db>>> {
602        methods_in_module_tracked(self.as_dyn_database(), module_id, type_filter)
603    }
604    /// Returns all methods in a crate that match the given type filter.
605    fn methods_in_crate(
606        &'db self,
607        crate_id: CrateId<'db>,
608        type_filter: TypeFilter<'db>,
609    ) -> Arc<Vec<TraitFunctionId<'db>>> {
610        methods_in_crate_tracked(self.as_dyn_database(), crate_id, type_filter)
611    }
612    /// Returns all the importables visible from a module, alongside a visible use path to the
613    /// trait.
614    fn visible_importables_from_module(
615        &'db self,
616        module_id: ModuleId<'db>,
617    ) -> Option<Arc<OrderedHashMap<ImportableId<'db>, String>>> {
618        visible_importables_from_module_tracked(self.as_dyn_database(), module_id)
619    }
620    /// Returns all visible importables in a module, alongside a visible use path to the trait.
621    /// `user_module_id` is the module from which the importables should be visible. If
622    /// `include_parent` is true, the parent module of `module_id` is also considered.
623    fn visible_importables_in_module(
624        &'db self,
625        module_id: ModuleId<'db>,
626        user_module_id: ModuleId<'db>,
627        include_parent: bool,
628    ) -> Arc<Vec<(ImportableId<'db>, String)>> {
629        visible_importables_in_module_tracked(
630            self.as_dyn_database(),
631            module_id,
632            user_module_id,
633            include_parent,
634        )
635    }
636    /// Returns all visible importables in a crate, alongside a visible use path to the trait.
637    /// `user_module_id` is the module from which the importables should be visible.
638    fn visible_importables_in_crate(
639        &'db self,
640        crate_id: CrateId<'db>,
641        user_module_id: ModuleId<'db>,
642    ) -> Arc<Vec<(ImportableId<'db>, String)>> {
643        visible_importables_in_crate_tracked(self.as_dyn_database(), crate_id, user_module_id)
644    }
645    /// Returns all the traits visible from a module, alongside a visible use path to the trait.
646    fn visible_traits_from_module(
647        &'db self,
648        module_id: ModuleId<'db>,
649    ) -> Option<Arc<OrderedHashMap<TraitId<'db>, String>>> {
650        visible_traits_from_module_tracked(self.as_dyn_database(), module_id)
651    }
652    /// Returns all files generated by inline macro expansion inside provided module.
653    fn inline_macro_expansion_files(&'db self, module_id: ModuleId<'db>) -> &'db Vec<FileId<'db>> {
654        inline_macro_expansion_files_tracked(self.as_dyn_database(), (), module_id)
655    }
656
657    /// Finds a [`ModuleId`] containing the node.
658    fn find_module_containing_node(&'db self, node: SyntaxNode<'db>) -> Option<ModuleId<'db>> {
659        find_module_containing_node(self.as_dyn_database(), (), node)
660    }
661}
662impl<'db, T: Database + ?Sized> LspHelpers<'db> for T {}