use crate::{
LanguageService,
binder::{SymbolKey, SymbolTable},
helpers,
};
use lspt::{
Declaration, DeclarationParams, Definition, DefinitionParams, TypeDefinitionParams, Union2,
};
use wat_syntax::SyntaxKind;
impl LanguageService {
pub fn goto_definition(&self, params: DefinitionParams) -> Option<Definition> {
let document = self.get_document(¶ms.text_document.uri)?;
let root = document.root_tree(self);
let token = super::find_meaningful_token(self, document, &root, params.position)?;
let parent = token
.parent()
.filter(|parent| matches!(parent.kind(), SyntaxKind::IMMEDIATE | SyntaxKind::INDEX))?;
let line_index = document.line_index(self);
let symbol_table = SymbolTable::of(self, document);
let key = SymbolKey::new(&parent);
symbol_table.resolved.get(&key).map(|key| {
Union2::A(helpers::create_location_by_symbol(
params.text_document.uri.clone(),
line_index,
*key,
&root,
))
})
}
pub fn goto_type_definition(&self, params: TypeDefinitionParams) -> Option<Definition> {
let document = self.get_document(¶ms.text_document.uri)?;
let line_index = document.line_index(self);
let root = document.root_tree(self);
let symbol_table = SymbolTable::of(self, document);
let token = super::find_meaningful_token(self, document, &root, params.position)?;
let parent = token
.parent()
.filter(|parent| parent.kind() == SyntaxKind::IMMEDIATE)?;
symbol_table
.resolved
.get(&SymbolKey::new(&parent))
.and_then(|key| {
key.try_to_node(&root)?
.children()
.find_map(|child| match child.kind() {
SyntaxKind::TYPE_USE | SyntaxKind::HEAP_TYPE => {
child.first_child_by_kind(&|kind| kind == SyntaxKind::INDEX)
}
SyntaxKind::REF_TYPE => child
.first_child_by_kind(&|kind| kind == SyntaxKind::HEAP_TYPE)
.and_then(|node| {
node.first_child_by_kind(&|kind| kind == SyntaxKind::INDEX)
}),
SyntaxKind::GLOBAL_TYPE => child
.first_child_by_kind(&|kind| kind == SyntaxKind::REF_TYPE)
.and_then(|node| {
node.first_child_by_kind(&|kind| kind == SyntaxKind::HEAP_TYPE)
})
.and_then(|node| {
node.first_child_by_kind(&|kind| kind == SyntaxKind::INDEX)
}),
_ => None,
})
.and_then(|type_idx| symbol_table.resolved.get(&SymbolKey::new(&type_idx)))
})
.map(|key| {
Union2::A(helpers::create_location_by_symbol(
params.text_document.uri.clone(),
line_index,
*key,
&root,
))
})
}
pub fn goto_declaration(&self, params: DeclarationParams) -> Option<Declaration> {
self.goto_definition(DefinitionParams {
text_document: params.text_document,
position: params.position,
work_done_token: params.work_done_token,
partial_result_token: params.partial_result_token,
})
}
}