a2kit 4.4.2

Retro disk image and language utility
Documentation
use lsp_types as lsp;
use tree_sitter;
use std::sync::Arc;
use crate::lang::merlin::Symbols;
use crate::lang::server::{Tokens,SemanticTokensBuilder};
use crate::lang::{lsp_range, node_text, Navigate, Navigation};
use crate::DYNERR;

pub struct SemanticTokensProvider {
    parser: super::MerlinParser,
    row: isize,
	col: isize,
	curr_macro: Option<String>,
	builder: SemanticTokensBuilder,
	symbols: Arc<Symbols>
}

impl SemanticTokensProvider {
	pub fn new() -> Self {
		Self {
			parser: super::MerlinParser::new(),
			row: 0,
			col: 0,
			curr_macro: None,
			builder: SemanticTokensBuilder::new(),
			symbols: Arc::new(Symbols::new())
		}
	}
    pub fn use_shared_symbols(&mut self,sym: Arc<Symbols>) {
        self.symbols = sym;
    }
}

impl Tokens for SemanticTokensProvider {
	fn get(&mut self, txt: &str) -> Result<lsp::SemanticTokens,DYNERR> {
		self.builder.reset();
		self.row = 0;
		self.curr_macro = None;
		for line in txt.lines() {
            if line.trim_start().len()==0 {
				self.row += 1;
                continue;
            }
            let tree = self.parser.parse(line,&self.symbols)?;
			self.col = self.parser.col_offset();
            self.walk(&tree)?;
			self.row += 1;
		}
		self.builder.clone_result()
	}
}

impl Navigate for SemanticTokensProvider {
    fn visit(&mut self,curs: &tree_sitter::TreeCursor) -> Result<Navigation,DYNERR> {
		let mut rng = lsp_range(curs.node().range(),self.row,self.col);
        let knd = curs.node().kind();
		if knd == "macro_def" {
			self.curr_macro = Some(node_text(&curs.node(), self.parser.line()));
			self.builder.push(rng,"macro");
			return Ok(Navigation::GotoSibling);
		}
		if knd == "psop_eom" {
			self.curr_macro = None;
			self.builder.push(rng,"function");
			return Ok(Navigation::GotoSibling);
		}
		if knd == "macro_ref" {
			self.builder.push(rng,"macro");
			return Ok(Navigation::GotoSibling);
		}
		if knd == "global_label" && self.curr_macro.is_some() {
			if let Some(mac) = self.symbols.macros.get(self.curr_macro.as_ref().unwrap()) {
				if mac.children.contains_key(&node_text(&curs.node(), self.parser.line())) {
					self.builder.push(rng,"parameter");
					return Ok(Navigation::GotoSibling);
				}
			}
		}
		if ["global_label","current_addr"].contains(&knd)
		{
			self.builder.push(rng,"enum");
			return Ok(Navigation::GotoSibling);
		}
		if knd=="local_label"
		{
			self.builder.push(rng,"parameter");
			return Ok(Navigation::GotoSibling);
		}
		if knd=="var_label" || knd=="var_mac"
		{
			self.builder.push(rng,"variable");
			return Ok(Navigation::GotoSibling);
		}
		if ["heading","comment"].contains(&knd)
		{
			self.builder.push(rng,"comment");
			return Ok(Navigation::GotoSibling);
		}
		if knd.starts_with("eop_")
		{
			self.builder.push(rng,"operator");
			return Ok(Navigation::GotoSibling);
		}
		if knd.starts_with("op_")
		{
			if let Some(child) = curs.node().named_child(0) {
				rng.end.character = child.range().start_point.column as u32;
			}
			self.builder.push(rng,"keyword");
			return Ok(Navigation::GotoChild);
		}
		if knd=="mode"
		{
			self.builder.push(rng,"keyword");
			return Ok(Navigation::GotoSibling);
		}
		if ["imm_prefix","addr_prefix","num_str_prefix","data_prefix"].contains(&knd)
		{
			self.builder.push(rng,"keyword");
			return Ok(Navigation::GotoSibling);
		}
		if knd.starts_with("psop_")
		{
			if let Some(child) = curs.node().named_child(0) {
				rng.end.character = child.range().start_point.column as u32;
			}
			self.builder.push(rng,"function");
			return Ok(Navigation::GotoChild);
		}
		if ["dstring","pchar","nchar","filename"].contains(&knd)
		{
			self.builder.push(rng,"string");
			return Ok(Navigation::GotoSibling);
		}
		if ["num","hex_data"].contains(&knd)
		{
			self.builder.push(rng,"number");
			return Ok(Navigation::GotoSibling);
		}
		if knd=="trailing" {
			self.builder.push(rng,"comment");
			return Ok(Navigation::GotoSibling);
		}
		return Ok(Navigation::GotoChild);
    }
}