224 lines
7.4 KiB
Rust
224 lines
7.4 KiB
Rust
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<GotoDefinitionResponse> {
|
|
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 def = scope_tree
|
|
.as_ref()?
|
|
// 获取定义
|
|
.get_definition(&token, file.text.pos_to_byte(&pos), &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<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)
|
|
}
|
|
|