shape_lsp/
trait_lookup.rs1use crate::doc_render::render_doc_comment;
8use crate::module_cache::ModuleCache;
9use shape_ast::ast::{Item, Program, Span, TraitDef};
10use std::path::{Path, PathBuf};
11
12#[derive(Debug, Clone)]
13pub struct ResolvedTraitDef {
14 pub trait_def: TraitDef,
15 pub span: Span,
16 pub documentation: Option<String>,
17 pub source_path: Option<PathBuf>,
18 pub source_text: Option<String>,
19 pub import_path: Option<String>,
20}
21
22pub fn resolve_trait_definition(
23 program: &Program,
24 trait_name: &str,
25 module_cache: Option<&ModuleCache>,
26 current_file: Option<&Path>,
27 workspace_root: Option<&Path>,
28) -> Option<ResolvedTraitDef> {
29 for item in &program.items {
30 if let Item::Trait(trait_def, span) = item {
31 if trait_def.name == trait_name {
32 return Some(ResolvedTraitDef {
33 trait_def: trait_def.clone(),
34 span: *span,
35 documentation: program
36 .docs
37 .comment_for_span(*span)
38 .map(|comment| render_doc_comment(program, comment, None, None, None)),
39 source_path: None,
40 source_text: None,
41 import_path: None,
42 });
43 }
44 }
45 }
46
47 let cache = module_cache?;
48 let current_file = current_file?;
49
50 let mut import_paths = cache.list_importable_modules_with_context(current_file, workspace_root);
51 import_paths.sort();
52
53 for import_path in import_paths {
54 let Some(resolved) = cache.resolve_import(&import_path, current_file, workspace_root)
55 else {
56 continue;
57 };
58 let Some(module_info) =
59 cache.load_module_with_context(&resolved, current_file, workspace_root)
60 else {
61 continue;
62 };
63
64 for item in &module_info.program.items {
65 if let Item::Trait(trait_def, span) = item {
66 if trait_def.name == trait_name {
67 return Some(ResolvedTraitDef {
68 trait_def: trait_def.clone(),
69 span: *span,
70 documentation: module_info.program.docs.comment_for_span(*span).map(
71 |comment| {
72 render_doc_comment(
73 &module_info.program,
74 comment,
75 Some(cache),
76 Some(&module_info.path),
77 workspace_root,
78 )
79 },
80 ),
81 source_text: std::fs::read_to_string(&module_info.path).ok(),
82 source_path: Some(module_info.path.clone()),
83 import_path: Some(import_path),
84 });
85 }
86 }
87 }
88 }
89
90 None
91}