1#![feature(new_range_api)]
2use oak_core::{
3 Arc, Range,
4 language::{ElementRole, ElementType, Language, TokenType, UniversalElementRole, UniversalTokenRole},
5 source::Source,
6 tree::{RedNode, RedTree},
7};
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct SymbolInformation {
13 pub name: String,
15 pub role: UniversalElementRole,
17 #[serde(with = "oak_core::serde_arc_str")]
19 pub uri: Arc<str>,
20 #[serde(with = "oak_core::serde_range")]
22 pub range: Range<usize>,
23 pub container_name: Option<String>,
25}
26
27pub trait SymbolProvider<L: Language> {
29 fn document_symbols<S: Source + ?Sized>(&self, uri: &str, root: &RedNode<L>, source: &S) -> Vec<SymbolInformation>;
31}
32
33pub struct UniversalSymbolProvider;
35
36impl UniversalSymbolProvider {
37 pub fn new() -> Self {
38 Self
39 }
40
41 fn collect_symbols<L: Language, S: Source + ?Sized>(&self, uri: &str, node: &RedNode<L>, symbols: &mut Vec<SymbolInformation>, container_name: Option<String>, source: &S) {
42 let role = node.green.kind.role();
43
44 if role.universal() == UniversalElementRole::Definition {
45 let mut name = None;
47 for child in node.children() {
48 match child {
49 RedTree::Leaf(leaf) => {
50 if leaf.kind.is_universal(UniversalTokenRole::Name) || leaf.kind.is_universal(UniversalTokenRole::None) {
52 name = Some(source.get_text_in(leaf.span).to_string());
53 break;
54 }
55 }
56 _ => {}
57 }
58 }
59
60 let name = name.unwrap_or_else(|| format!("<{:?}>", node.green.kind));
61
62 symbols.push(SymbolInformation { name: name.clone(), role: role.universal(), uri: uri.to_string().into(), range: node.span(), container_name: container_name.clone() });
63
64 for child in node.children() {
66 if let RedTree::Node(child_node) = child {
67 self.collect_symbols(uri, &child_node, symbols, Some(name.clone()), source);
68 }
69 }
70 }
71 else {
72 for child in node.children() {
74 if let RedTree::Node(child_node) = child {
75 self.collect_symbols(uri, &child_node, symbols, container_name.clone(), source);
76 }
77 }
78 }
79 }
80}
81
82impl<L: Language> SymbolProvider<L> for UniversalSymbolProvider {
83 fn document_symbols<S: Source + ?Sized>(&self, uri: &str, root: &RedNode<L>, source: &S) -> Vec<SymbolInformation> {
84 let mut symbols = Vec::new();
85 self.collect_symbols(uri, root, &mut symbols, None, source);
86 symbols
87 }
88}