2024-10-05 00:12:36 +08:00

202 lines
6.6 KiB
Rust

use crate::utils::get_language_id_by_uri;
use crate::server::LSPServer;
#[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 mod extract_defs;
pub use extract_defs::*;
mod sv;
mod vhdl;
impl LSPServer {
pub fn goto_definition(&self, params: GotoDefinitionParams) -> Option<GotoDefinitionResponse> {
let language_id = get_language_id_by_uri(&params.text_document_position_params.text_document.uri);
match language_id.as_str() {
"vhdl" => vhdl::goto_vhdl_definition(
self,
&params
),
"verilog" | "systemverilog" => sv::goto_definition(
self,
&params
),
_ => None
}
}
}
type ScopesAndDefs = Option<(Vec<Box<dyn Scope>>, Vec<Box<dyn Definition>>)>;
/// 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<Box<dyn Definition>> = Vec::new();
let mut scopes: Vec<Box<dyn Scope>> = 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<GenericScope> {
let mut scopes: Vec<Box<dyn Scope>> = 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)
}