use crate::{utils::get_definition_token}; use crate::server::LSPServer; use crate::sources::LSPSupport; #[allow(unused)] use log::info; use sv_parser::*; use tower_lsp::lsp_types::*; pub mod def_types; pub use def_types::*; pub mod feature; pub use feature::*; pub mod extract_defs; pub use extract_defs::*; pub mod vhdl; impl LSPServer { pub fn goto_definition(&self, params: GotoDefinitionParams) -> Option { let doc = params.text_document_position_params.text_document.uri; let pos = params.text_document_position_params.position; let file_id = self.srcs.get_id(&doc).to_owned(); self.srcs.wait_parse_ready(file_id, false); let file = self.srcs.get_file(file_id)?; let file = file.read().ok()?; let line_text = file.text.line(pos.line as usize); let token: String = get_definition_token(&line_text, pos); // match include if let Some(definition) = goto_include_definition(&doc, &line_text, pos) { return Some(definition); } // match macro if let Some(definition) = goto_macro_definition(self, &line_text, pos) { return Some(definition); } // match instance let scope_tree = self.srcs.scope_tree.read().ok()?; let byte_idx = file.text.pos_to_byte(&pos); let global_scope = scope_tree.as_ref()?; let def = global_scope.get_definition(&token, byte_idx, &doc)?; let def_pos = file.text.byte_to_pos(def.byte_idx()); Some(GotoDefinitionResponse::Scalar(Location::new( def.url(), Range::new(def_pos, def_pos), ))) } } type ScopesAndDefs = Option<(Vec>, Vec>)>; /// Take a given syntax node from a sv-parser syntax tree and extract out the definition/scope at /// that point. pub fn match_definitions( syntax_tree: &SyntaxTree, event_iter: &mut EventIter, node: RefNode, url: &Url, ) -> ScopesAndDefs { let mut definitions: Vec> = Vec::new(); let mut scopes: Vec> = Vec::new(); match node { RefNode::ModuleDeclaration(n) => { let module = module_dec(syntax_tree, n, event_iter, url); if module.is_some() { scopes.push(Box::new(module?)); } } RefNode::InterfaceDeclaration(n) => { let interface = interface_dec(syntax_tree, n, event_iter, url); if interface.is_some() { scopes.push(Box::new(interface?)); } } RefNode::UdpDeclaration(n) => { let dec = udp_dec(syntax_tree, n, event_iter, url); if dec.is_some() { scopes.push(Box::new(dec?)); } } RefNode::ProgramDeclaration(n) => { let dec = program_dec(syntax_tree, n, event_iter, url); if dec.is_some() { scopes.push(Box::new(dec?)); } } RefNode::PackageDeclaration(n) => { let dec = package_dec(syntax_tree, n, event_iter, url); if dec.is_some() { scopes.push(Box::new(dec?)); } } RefNode::ConfigDeclaration(n) => { let dec = config_dec(syntax_tree, n, event_iter, url); if dec.is_some() { scopes.push(Box::new(dec?)); } } RefNode::ClassDeclaration(n) => { let dec = class_dec(syntax_tree, n, event_iter, url); if dec.is_some() { scopes.push(Box::new(dec?)); } } RefNode::PortDeclaration(n) => { let ports = port_dec_non_ansi(syntax_tree, n, event_iter, url); if ports.is_some() { for port in ports? { definitions.push(Box::new(port)); } } } RefNode::NetDeclaration(n) => { let nets = net_dec(syntax_tree, n, event_iter, url); if nets.is_some() { for net in nets? { definitions.push(Box::new(net)); } } } RefNode::DataDeclaration(n) => { let vars = data_dec(syntax_tree, n, event_iter, url); if let Some(vars) = vars { for var in vars { match var { Declaration::Dec(dec) => definitions.push(Box::new(dec)), Declaration::Import(dec) => definitions.push(Box::new(dec)), Declaration::Scope(scope) => scopes.push(Box::new(scope)), } } } } RefNode::ParameterDeclaration(n) => { let vars = param_dec(syntax_tree, n, event_iter, url); if vars.is_some() { for var in vars? { definitions.push(Box::new(var)); } } } RefNode::LocalParameterDeclaration(n) => { let vars = localparam_dec(syntax_tree, n, event_iter, url); if vars.is_some() { for var in vars? { definitions.push(Box::new(var)); } } } RefNode::FunctionDeclaration(n) => { let dec = function_dec(syntax_tree, n, event_iter, url); if dec.is_some() { scopes.push(Box::new(dec?)); } } RefNode::TaskDeclaration(n) => { let dec = task_dec(syntax_tree, n, event_iter, url); if dec.is_some() { scopes.push(Box::new(dec?)); } } RefNode::ModportDeclaration(n) => { let decs = modport_dec(syntax_tree, n, event_iter, url); if decs.is_some() { for dec in decs? { definitions.push(Box::new(dec)); } } } RefNode::ModuleInstantiation(n) => { let decs = module_inst(syntax_tree, n, event_iter, url); if decs.is_some() { for dec in decs? { definitions.push(Box::new(dec)); } } } RefNode::TextMacroDefinition(n) => { let dec = text_macro_def(syntax_tree, n, event_iter, url); if dec.is_some() { definitions.push(Box::new(dec?)); } } _ => (), } Some((scopes, definitions)) } /// convert the syntax tree to a scope tree /// the root node is the global scope pub fn get_scopes_from_syntax_tree(syntax_tree: &SyntaxTree, url: &Url) -> Option { let mut scopes: Vec> = Vec::new(); let mut global_scope: GenericScope = GenericScope::new(url); global_scope.ident = String::from("global"); let mut event_iter = syntax_tree.into_iter().event(); // iterate over each enter event and extract out any scopes or definitions // match_definitions is recursively called so we get a tree in the end while let Some(event) = event_iter.next() { match event { NodeEvent::Enter(node) => { let mut result = match_definitions(syntax_tree, &mut event_iter, node, url)?; global_scope.defs.append(&mut result.1); scopes.append(&mut result.0); } NodeEvent::Leave(_) => (), } } global_scope.scopes.append(&mut scopes); Some(global_scope) }