use crate::base::FileId;
use crate::hir::{ResolveResult, Resolver, SymbolIndex, SymbolKind};
use std::borrow::Cow;
#[derive(Debug, Clone)]
pub struct DocumentLink {
pub start_line: u32,
pub start_col: u32,
pub end_line: u32,
pub end_col: u32,
pub target_file: FileId,
pub target_line: u32,
pub target_col: u32,
pub tooltip: Cow<'static, str>,
}
fn extract_scope(qualified_name: &str) -> String {
if let Some(import_pos) = qualified_name.find("::import:") {
return qualified_name[..import_pos].to_string();
}
if let Some(pos) = qualified_name.rfind("::") {
qualified_name[..pos].to_string()
} else {
String::new()
}
}
pub fn document_links(index: &SymbolIndex, file: FileId) -> Vec<DocumentLink> {
let mut links = Vec::new();
let symbols = index.symbols_in_file(file);
for sym in symbols {
match sym.kind {
SymbolKind::Import => {
let import_path = sym.name.as_ref();
let resolved_path = if let Some(stripped) = import_path.strip_suffix("::*") {
stripped
} else if let Some(stripped) = import_path.strip_suffix(":::**") {
stripped
} else {
import_path
};
let scope = extract_scope(&sym.qualified_name);
let resolver = Resolver::new(index).with_scope(scope);
let target = match resolver.resolve(resolved_path) {
ResolveResult::Found(t) => Some(t),
ResolveResult::Ambiguous(targets) => targets.into_iter().next(),
ResolveResult::NotFound => {
index.lookup_qualified(resolved_path).cloned()
}
};
if let Some(target) = target {
links.push(DocumentLink {
start_line: sym.start_line,
start_col: sym.start_col,
end_line: sym.end_line,
end_col: sym.end_col,
target_file: target.file,
target_line: target.start_line,
target_col: target.start_col,
tooltip: Cow::Owned(format!("Go to {}", target.qualified_name)),
});
}
}
_ => {
for type_ref_kind in &sym.type_refs {
for type_ref in type_ref_kind.as_refs() {
let target_qname = &type_ref.target;
if let Some(target) = index.lookup_qualified(target_qname) {
links.push(DocumentLink {
start_line: type_ref.start_line,
start_col: type_ref.start_col,
end_line: type_ref.end_line,
end_col: type_ref.end_col,
target_file: target.file,
target_line: target.start_line,
target_col: target.start_col,
tooltip: Cow::Owned(format!("Go to {}", target_qname)),
});
}
}
}
}
}
}
links
}