1#![feature(new_range_api)]
2#![warn(missing_docs)]
3use core::range::Range;
8use oak_core::{Language, TokenType, language::UniversalTokenRole, tree::RedNode, visitor::Visitor};
9
10#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
12pub struct Location {
13 #[serde(with = "oak_core::serde_arc_str")]
15 pub uri: oak_core::Arc<str>,
16 #[serde(with = "oak_core::serde_range")]
18 pub range: Range<usize>,
19}
20
21pub trait DefinitionProvider<L: Language> {
23 fn definition(&self, root: &RedNode<L>, offset: usize) -> Vec<Location>;
25}
26
27pub trait ReferencesProvider<L: Language> {
29 fn references(&self, root: &RedNode<L>, offset: usize, include_declaration: bool) -> Vec<Location>;
31}
32
33pub struct SimpleReferenceFinder<'a, L: Language> {
35 name: &'a str,
37 source: &'a str,
39 uri: oak_core::Arc<str>,
41 references: Vec<Location>,
43 _phantom: std::marker::PhantomData<L>,
45}
46
47impl<'a, L: Language> SimpleReferenceFinder<'a, L> {
48 pub fn find(root: &RedNode<'a, L>, name: &'a str, source: &'a str, uri: impl Into<oak_core::Arc<str>>) -> Vec<Location> {
56 let mut finder = Self { name, source, uri: uri.into(), references: Vec::new(), _phantom: std::marker::PhantomData };
57 finder.visit_node(*root);
58 finder.references
59 }
60}
61
62impl<'a, L: Language> Visitor<'a, L> for SimpleReferenceFinder<'a, L> {
63 fn visit_node(&mut self, node: RedNode<'a, L>) {
64 self.walk_node(node);
65 }
66
67 fn visit_token(&mut self, token: oak_core::tree::RedLeaf<L>) {
68 if token.kind.is_universal(UniversalTokenRole::Name) {
69 let text = &self.source[token.span.clone()];
70 if text == self.name {
71 self.references.push(Location { uri: self.uri.clone(), range: token.span });
72 }
73 }
74 }
75}