use probl_syntax::Span;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DefKind {
Variable,
Parameter,
Function,
Record,
Field,
Enum,
Variant,
}
impl DefKind {
pub fn name(self) -> &'static str {
match self {
DefKind::Variable => "variable",
DefKind::Parameter => "parameter",
DefKind::Function => "function",
DefKind::Record => "record",
DefKind::Field => "field",
DefKind::Enum => "enum",
DefKind::Variant => "variant",
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Definition {
pub name: String,
pub kind: DefKind,
pub mutable: bool,
pub span: Span,
pub scope: Span,
pub global: bool,
pub owner: Option<String>,
pub ty: Option<String>,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Symbols {
pub definitions: Vec<Definition>,
pub references: Vec<(Span, usize)>,
pub functions: Vec<Span>,
}
impl Symbols {
pub fn at(&self, offset: u32) -> Option<usize> {
let inside = |s: Span| s.lo <= offset && offset <= s.hi;
self.references
.iter()
.find(|(span, _)| inside(*span))
.map(|&(_, d)| d)
.or_else(|| self.definitions.iter().position(|d| inside(d.span)))
}
pub fn visible(&self, offset: u32) -> Vec<usize> {
let in_function = self.functions.iter().any(|f| f.lo <= offset && offset <= f.hi);
let mut found: Vec<usize> = (0..self.definitions.len())
.filter(|&i| {
let d = &self.definitions[i];
!matches!(d.kind, DefKind::Field)
&& ((d.scope.lo <= offset && offset <= d.scope.hi) || (d.global && in_function))
})
.collect();
found.sort_by_key(|&i| std::cmp::Reverse(self.definitions[i].scope.lo));
found
}
}