diff --git a/src/completion/sv.rs b/src/completion/sv.rs index 9049246..885dd00 100644 --- a/src/completion/sv.rs +++ b/src/completion/sv.rs @@ -373,7 +373,7 @@ fn make_module_completions( insert_text_mode: Some(InsertTextMode::ADJUST_INDENTATION), ..CompletionItem::default() }; - module_completioms.push(item); + module_completioms.push(item); } } diff --git a/src/core/mod.rs b/src/core/mod.rs index d53a595..6d7122f 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -7,3 +7,5 @@ pub mod vhdl_parser; pub mod cache_storage; pub mod primitive_parser; + +pub mod scope_tree; \ No newline at end of file diff --git a/src/definition/def_types.rs b/src/core/scope_tree/common.rs similarity index 98% rename from src/definition/def_types.rs rename to src/core/scope_tree/common.rs index da20382..a3293bc 100644 --- a/src/definition/def_types.rs +++ b/src/core/scope_tree/common.rs @@ -1,5 +1,3 @@ -use std::ffi::OsStr; - #[allow(unused)] use log::info; use ropey::Rope; @@ -117,23 +115,24 @@ pub trait Scope: std::fmt::Debug + Definition + Sync + Send { // first we need to go down the scope tree, to the scope the user is invoking a completion // in for scope in self.scopes() { + // 如果当前的 token 在这个 scope 中,那么需要递归获取这个 scope 中的所有补全项目 if &scope.url() == url && scope.start() <= byte_idx && byte_idx <= scope.end() { completions = scope.get_completion(token, byte_idx, url); break; } } + // 自动补全时,忽略大小写 let lower_case_token = token.to_lowercase(); - // now that we are in the users scope, we can attempt to find a relevant completion - // we proceed back upwards through the scope tree, adding any definitions that match - // the users token let completion_idents: Vec = completions.iter().map(|x| x.label.clone()).collect(); + + // 寻找前缀相同的 symbol for def in self.defs() { - if !completion_idents.contains(&def.ident()) && def.ident().to_lowercase().starts_with(&lower_case_token) { completions.push(def.completion()); } } + // 寻找前缀相同的 scope for scope in self.scopes() { if scope.starts_with(token) { completions.push(scope.completion()); @@ -155,7 +154,6 @@ pub trait Scope: std::fmt::Debug + Definition + Sync + Send { // in for scope in self.scopes() { if &scope.url() == url && scope.start() <= byte_idx && byte_idx <= scope.end() { - eprintln!("checking dot completion: {}", scope.ident()); let result = scope.get_dot_completion(token, byte_idx, url, scope_tree); if !result.is_empty() { return result; diff --git a/src/core/scope_tree/mod.rs b/src/core/scope_tree/mod.rs new file mode 100644 index 0000000..24f4975 --- /dev/null +++ b/src/core/scope_tree/mod.rs @@ -0,0 +1,226 @@ +use crate::core::hdlparam::{self, FastHdlparam}; +use ropey::Rope; +use sv_parser::*; +use tower_lsp::lsp_types::*; + +// 定义有关 scope 相关的基础类的 +pub mod common; +// 定义如何把 ast 转变为类似于 common 中的数据结构 +pub mod parse; + +use common::*; +use parse::*; + +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) +} + +pub fn get_scopes_from_vhdl_fast(fast: &FastHdlparam, text: &Rope, url: &Url) -> Option { + let mut scopes: Vec> = Vec::new(); + let mut global_scope: GenericScope = GenericScope::new(url); + global_scope.ident = String::from("global"); + + for module in &fast.content { + let mut scope: GenericScope = GenericScope::new(url); + scope.ident = module.name.clone(); + let module_range = module.range.clone(); + scope.start = position_to_byte_idx(text, &module_range.start); + scope.end = position_to_byte_idx(text, &module_range.end); + scope.byte_idx = scope.start + 7; + + for parameter in &module.params { + let mut def = GenericDec::new(url); + def.ident = parameter.name.clone(); + let parameter_range = parameter.range.clone(); + def.byte_idx = position_to_byte_idx(text, ¶meter_range.start); + def.completion_kind = CompletionItemKind::TYPE_PARAMETER; + def.symbol_kind = SymbolKind::TYPE_PARAMETER; + scope.defs.push(Box::new(def)); + } + for port in &module.ports { + let mut port_def = PortDec::new(url); + port_def.ident = port.name.clone(); + let port_range = port.range.clone(); + port_def.byte_idx = position_to_byte_idx(text, &port_range.start); + port_def.type_str = port.dir_type.clone(); + scope.defs.push(Box::new(port_def)); + } + for inst in &module.instances { + let mut instance = ModInst::new(url); + instance.ident = inst.name.clone(); + let inst_range = inst.range.clone(); + instance.byte_idx = position_to_byte_idx(text, &inst_range.start); + instance.type_str = inst.inst_type.clone(); + instance.mod_ident = inst.inst_type.clone(); + + scope.defs.push(Box::new(instance)); + } + scopes.push(Box::new(scope)); + } + + global_scope.scopes.append(&mut scopes); + Some(global_scope) +} + +fn position_to_byte_idx(text: &Rope, pos: &hdlparam::Position) -> usize { + let char = text.line_to_char(pos.line as usize) + pos.character as usize; + text.char_to_byte(char) +} diff --git a/src/definition/extract_defs.rs b/src/core/scope_tree/parse.rs similarity index 99% rename from src/definition/extract_defs.rs rename to src/core/scope_tree/parse.rs index 3b8f087..d8ea885 100644 --- a/src/definition/extract_defs.rs +++ b/src/core/scope_tree/parse.rs @@ -1,8 +1,10 @@ -use crate::definition::def_types::*; -use crate::definition::match_definitions; +use super::common::*; +use super::match_definitions; + use sv_parser::*; use tower_lsp::lsp_types::*; + /// 找到 node 的 名字,开始的位置和结束的位置 pub fn get_ident(tree: &SyntaxTree, node: RefNode) -> (String, usize) { let loc = unwrap_locate!(node).unwrap(); @@ -2340,7 +2342,8 @@ pub fn text_macro_def( let ident = get_ident(tree, RefNode::TextMacroIdentifier(&node.nodes.2.nodes.0)); text_macro.ident = ident.0; text_macro.byte_idx = ident.1; - let type_str = &mut text_macro.type_str; + let type_str = &mut text_macro.type_str; + advance_until_enter!( type_str, tree, @@ -2349,8 +2352,11 @@ pub fn text_macro_def( &TextMacroIdentifier ); + // 自动补全用的 text_macro.completion_kind = CompletionItemKind::CONSTANT; + // document 用的 text_macro.symbol_kind = SymbolKind::FUNCTION; + // 内部用于标定当前类型的 text_macro.def_type = DefinitionType::Macro; Some(text_macro) } diff --git a/src/definition/mod.rs b/src/definition/mod.rs index cae2457..516df04 100644 --- a/src/definition/mod.rs +++ b/src/definition/mod.rs @@ -1,21 +1,12 @@ -use crate::core::hdlparam::{self, FastHdlparam}; use crate::utils::get_language_id_by_uri; use crate::server::LspServer; #[allow(unused)] use log::info; -use ropey::Rope; -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; @@ -36,219 +27,4 @@ impl LspServer { _ => None } } -} - - -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) -} - -pub fn get_scopes_from_vhdl_fast(fast: &FastHdlparam, text: &Rope, url: &Url) -> Option { - let mut scopes: Vec> = Vec::new(); - let mut global_scope: GenericScope = GenericScope::new(url); - global_scope.ident = String::from("global"); - - for module in &fast.content { - let mut scope: GenericScope = GenericScope::new(url); - scope.ident = module.name.clone(); - let module_range = module.range.clone(); - scope.start = position_to_byte_idx(text, &module_range.start); - scope.end = position_to_byte_idx(text, &module_range.end); - scope.byte_idx = scope.start + 7; - - for parameter in &module.params { - let mut def = GenericDec::new(url); - def.ident = parameter.name.clone(); - let parameter_range = parameter.range.clone(); - def.byte_idx = position_to_byte_idx(text, ¶meter_range.start); - def.completion_kind = CompletionItemKind::TYPE_PARAMETER; - def.symbol_kind = SymbolKind::TYPE_PARAMETER; - scope.defs.push(Box::new(def)); - } - for port in &module.ports { - let mut port_def = PortDec::new(url); - port_def.ident = port.name.clone(); - let port_range = port.range.clone(); - port_def.byte_idx = position_to_byte_idx(text, &port_range.start); - port_def.type_str = port.dir_type.clone(); - scope.defs.push(Box::new(port_def)); - } - for inst in &module.instances { - let mut instance = ModInst::new(url); - instance.ident = inst.name.clone(); - let inst_range = inst.range.clone(); - instance.byte_idx = position_to_byte_idx(text, &inst_range.start); - instance.type_str = inst.inst_type.clone(); - instance.mod_ident = inst.inst_type.clone(); - - scope.defs.push(Box::new(instance)); - } - scopes.push(Box::new(scope)); - } - - global_scope.scopes.append(&mut scopes); - Some(global_scope) -} - -fn position_to_byte_idx(text: &Rope, pos: &hdlparam::Position) -> usize { - let char = text.line_to_char(pos.line as usize) + pos.character as usize; - text.char_to_byte(char) -} +} \ No newline at end of file diff --git a/src/definition/sv.rs b/src/definition/sv.rs index 96c7ed8..c9a3753 100644 --- a/src/definition/sv.rs +++ b/src/definition/sv.rs @@ -1,3 +1,4 @@ +use crate::core::scope_tree::common::{Definition, Scope}; use crate::utils::get_definition_token; use crate::server::LspServer; use crate::sources::LSPSupport; @@ -5,8 +6,7 @@ use crate::sources::LSPSupport; #[allow(unused)] use log::info; use tower_lsp::lsp_types::*; - -use super::{feature::*, Definition, Scope}; +use super::feature::*; pub fn goto_definition(server: &LspServer, params: &GotoDefinitionParams) -> Option { let doc = ¶ms.text_document_position_params.text_document.uri; diff --git a/src/definition/vhdl.rs b/src/definition/vhdl.rs index f43ab1d..1ec1834 100644 --- a/src/definition/vhdl.rs +++ b/src/definition/vhdl.rs @@ -5,8 +5,6 @@ use log::info; use tower_lsp::lsp_types::*; use crate::{server::LspServer, utils::{from_lsp_pos, get_definition_token, srcpos_to_location, to_escape_path}}; -use super::{Definition, Scope}; - pub fn goto_vhdl_definition(server: &LspServer, params: &GotoDefinitionParams) -> Option { let doc = ¶ms.text_document_position_params.text_document.uri; let pos = params.text_document_position_params.position; diff --git a/src/diagnostics/common.rs b/src/diagnostics/common.rs index 197c729..6ec92f9 100644 --- a/src/diagnostics/common.rs +++ b/src/diagnostics/common.rs @@ -65,9 +65,12 @@ pub trait AbstractLinterConfiguration { /// 获取与该工具匹配的诊断器名字与调用函数名。并检查它们是否有效 /// /// 参考链接:https://kirigaya.cn/blog/article?seq=284 - fn linter_status(&self) -> LinterStatus { + fn linter_status( + &self, + server: &LspServer + ) -> LinterStatus { let invoke_name = self.get_invoke_name(); - let available = is_command_valid(&invoke_name); + let available = is_command_valid(&invoke_name, server); LinterStatus { tool_name: self.get_exe_name(), available, diff --git a/src/diagnostics/vivado.rs b/src/diagnostics/vivado.rs index 0bb74ed..801ca47 100644 --- a/src/diagnostics/vivado.rs +++ b/src/diagnostics/vivado.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; use xml::name; use crate::{diagnostics::find_non_whitespace_indices, server::LspServer}; use ropey::Rope; -use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range, Url}; +use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity, NumberOrString, Position, Range, Url}; use super::AbstractLinterConfiguration; @@ -113,7 +113,7 @@ impl AbstractLinterConfiguration for VivadoConfiguration { let diagnostic = Diagnostic { range, - code: None, + code: Some(NumberOrString::String(error_code.to_string())), severity: Some(DiagnosticSeverity::ERROR), source: Some("Digital IDE: vivado".to_string()), message: error_description.to_string(), @@ -167,8 +167,6 @@ fn find_vivado_suitable_range( let pattern = format!(r"\b(?i){}\b", error_keyword); let regex = Regex::new(&pattern).unwrap(); - info!("find keyword: {:?}", error_keyword); - if let Some(line_text) = rope.line(error_no).as_str() { // 处理特殊情况: error_keyword 为 ; if error_keyword == ";" { @@ -177,10 +175,75 @@ fn find_vivado_suitable_range( } } if let Some(mat) = regex.find(line_text) { - info!("mat {} {}", mat.start(), mat.end()); + // info!("mat {} {}", mat.start(), mat.end()); return Some((mat.start(), mat.end())); } } find_non_whitespace_indices(rope, error_no) +} + + +/// 过滤 vivado 给出的一些报错 +fn filter_diagnostic_result( + diagnostics: Vec, + server: &LspServer, + language_id: &str +) -> Vec { + match language_id { + // vhdl + "vhdl" => { + filter_xvhdl_diagnostic_result(diagnostics, server) + } + // vlog & svlog + _ => { + filter_xvlog_diagnostic_result(diagnostics, server) + } + } +} + + +fn filter_xvhdl_diagnostic_result( + diagnostics: Vec, + #[allow(unused)] + server: &LspServer, +) -> Vec { + diagnostics +} + +/// 判断是否为类似于 xxx ignored 的错误 +/// ERROR: [VRFC 10-8530] module 'main' is ignored due to previous errors [/home/dide/project/Digital-Test/Digital-macro/user/src/main.v:1] +fn is_ignore_type(diag: &Diagnostic) -> bool { + // 获取 vrfc 编码 + let vrfc_code = if let Some(NumberOrString::String(code)) = &diag.code { + code + } else { + return false; + }; + + match vrfc_code.as_str() { + "10-8530" => { + true + } + + _ => { + false + } + } +} + +fn filter_xvlog_diagnostic_result( + diagnostics: Vec, + #[allow(unused)] + server: &LspServer, +) -> Vec { + // 第一级过滤, 去除所有的 ignore 类型的 + let diagnostics = diagnostics.into_iter().filter(|diag| !is_ignore_type(diag)).collect(); + + + // 第二级过滤, 对于 xxx not found, 需要先根据 fast 查看是否存在, 如果存在,还需要把同一行的某些特定错误一并去除 + + + + diagnostics } \ No newline at end of file diff --git a/src/document_highlight/sv.rs b/src/document_highlight/sv.rs index 7bf9796..84a88cd 100644 --- a/src/document_highlight/sv.rs +++ b/src/document_highlight/sv.rs @@ -3,7 +3,9 @@ use log::info; use sv_parser::{RefNode, SyntaxTree}; use tower_lsp::lsp_types::*; -use crate::{definition::{get_ident, Scope}, server::LspServer, sources::{LSPSupport, ParseIR, Source}}; +use crate::{server::LspServer, sources::{LSPSupport, ParseIR, Source}}; +use crate::core::scope_tree::parse::get_ident; +use crate::core::scope_tree::common::Scope; pub fn document_highlight( server: &LspServer, diff --git a/src/document_highlight/vhdl.rs b/src/document_highlight/vhdl.rs index 9a644a5..307ec4d 100644 --- a/src/document_highlight/vhdl.rs +++ b/src/document_highlight/vhdl.rs @@ -2,7 +2,9 @@ use log::info; use sv_parser::{RefNode, SyntaxTree}; use tower_lsp::lsp_types::*; -use crate::{definition::{get_ident, Scope}, server::LspServer, sources::{LSPSupport, ParseIR, Source}}; +use crate::{server::LspServer, sources::{LSPSupport, ParseIR, Source}}; +use crate::core::scope_tree::parse::get_ident; +use crate::core::scope_tree::common::Scope; pub fn document_highlight( server: &LspServer, diff --git a/src/document_symbol/sv.rs b/src/document_symbol/sv.rs index f12547b..d5e62c8 100644 --- a/src/document_symbol/sv.rs +++ b/src/document_symbol/sv.rs @@ -1,4 +1,4 @@ -use crate::{definition::Scope, server::LspServer}; +use crate::{core::scope_tree::common::Scope, server::LspServer}; use tower_lsp::lsp_types::*; pub fn document_symbol( diff --git a/src/document_symbol/vhdl.rs b/src/document_symbol/vhdl.rs index 0b98922..07f3803 100644 --- a/src/document_symbol/vhdl.rs +++ b/src/document_symbol/vhdl.rs @@ -4,7 +4,7 @@ use std::{path::PathBuf, str::FromStr}; use log::info; use tower_lsp::lsp_types::*; use vhdl_lang::{EntHierarchy, Token}; -use crate::{definition::Scope, server::LspServer, utils::{to_escape_path, to_lsp_range, to_symbol_kind}}; +use crate::{server::LspServer, utils::{to_escape_path, to_lsp_range, to_symbol_kind}}; pub fn document_symbol(server: &LspServer, params: &DocumentSymbolParams) -> Option { // info!("enter document symbol"); diff --git a/src/hover/sv.rs b/src/hover/sv.rs index 4fb22e8..7e1983e 100644 --- a/src/hover/sv.rs +++ b/src/hover/sv.rs @@ -3,11 +3,11 @@ use log::info; use regex::Regex; use ropey::Rope; use tower_lsp::lsp_types::*; -use crate::{core::hdlparam::{Instance, Module}, hover::{to_escape_path, BracketMatchResult, BracketMatcher}, server::LspServer, sources::LSPSupport}; +use crate::{core::{hdlparam::{Instance, Module}, scope_tree::common::Scope}, hover::{to_escape_path, BracketMatchResult, BracketMatcher}, server::LspServer, sources::LSPSupport}; use super::feature::*; use std::{path::PathBuf, str::FromStr, sync::RwLockReadGuard}; -use crate::definition::*; +use crate::core::scope_tree::common::*; use super::{get_definition_token, get_language_id_by_uri}; diff --git a/src/hover/vhdl.rs b/src/hover/vhdl.rs index 13f29f8..2ec654e 100644 --- a/src/hover/vhdl.rs +++ b/src/hover/vhdl.rs @@ -4,7 +4,8 @@ use log::info; use regex::Regex; use ropey::Rope; use tower_lsp::lsp_types::*; -use crate::{core::hdlparam::{Instance, Module}, definition::{Definition, DefinitionType, GenericDec, Scope}, hover::{BracketMatchResult, BracketMatcher}, server::LspServer, sources::LSPSupport}; +use crate::{core::hdlparam::{Instance, Module}, hover::{BracketMatchResult, BracketMatcher}, server::LspServer}; +use crate::core::scope_tree::common::*; use super::{from_lsp_pos, get_definition_token, get_language_id_by_uri, to_escape_path}; diff --git a/src/request/fast.rs b/src/request/fast.rs index 383e34a..40491b5 100644 --- a/src/request/fast.rs +++ b/src/request/fast.rs @@ -15,7 +15,7 @@ use crate::core::hdlparam::FastHdlparam; use crate::core::sv_parser::make_fast_from_syntaxtree; use crate::core::vhdl_parser::make_fast_from_units; -use crate::definition::VhdlProject; +use crate::core::scope_tree::common::VhdlProject; use crate::{core, utils::*}; use crate::server::Backend; use crate::sources::recovery_sv_parse_with_retry; diff --git a/src/request/linter.rs b/src/request/linter.rs index c72d32b..1d10bae 100644 --- a/src/request/linter.rs +++ b/src/request/linter.rs @@ -63,23 +63,23 @@ fn get_linter_status( // 再根据 linter name 进行分类讨论 match linter_name { "iverilog" => { - Ok(configuration.iverilog.linter_status()) + Ok(configuration.iverilog.linter_status(&backend.server)) } "vivado" => { - Ok(configuration.vivado.linter_status()) + Ok(configuration.vivado.linter_status(&backend.server)) } "modelsim" => { - Ok(configuration.modelsim.linter_status()) + Ok(configuration.modelsim.linter_status(&backend.server)) } "verible" => { - Ok(configuration.verible.linter_status()) + Ok(configuration.verible.linter_status(&backend.server)) } "verilator" => { - Ok(configuration.verilator.linter_status()) + Ok(configuration.verilator.linter_status(&backend.server)) } _ => { diff --git a/src/sources.rs b/src/sources.rs index 5fe545f..632f138 100644 --- a/src/sources.rs +++ b/src/sources.rs @@ -3,9 +3,9 @@ use crate::core::primitive_parser::PrimitiveText; use crate::core::sv_parser::make_fast_from_syntaxtree; use crate::core::vhdl_parser::make_fast_from_units; use crate::core::vhdl_parser::vhdl_parse_str; -use crate::definition::def_types::*; -use crate::definition::get_scopes_from_syntax_tree; -use crate::definition::get_scopes_from_vhdl_fast; +use crate::core::scope_tree::common::*; +use crate::core::scope_tree::get_scopes_from_syntax_tree; +use crate::core::scope_tree::get_scopes_from_vhdl_fast; use crate::diagnostics::provide_diagnostics; use crate::server::LspServer; use crate::server::LspConfiguration; diff --git a/src/test/mod.rs b/src/test/mod.rs index c1bffd7..3d8c7ab 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -311,7 +311,9 @@ mod test_svparse { #[cfg(test)] mod test_scope_tree { use std::{fs, path::{Path, PathBuf}}; - use crate::{definition::{get_scopes_from_syntax_tree, GenericScope}, sources::{recovery_sv_parse, recovery_sv_parse_with_retry}}; + use crate::sources::recovery_sv_parse_with_retry; + use crate::core::scope_tree::get_scopes_from_syntax_tree; + use crate::core::scope_tree::common::GenericScope; use ropey::Rope; use tower_lsp::lsp_types::Url; diff --git a/src/utils/command.rs b/src/utils/command.rs index 17655d1..3398ebc 100644 --- a/src/utils/command.rs +++ b/src/utils/command.rs @@ -1,8 +1,27 @@ use std::process::Command; -pub fn is_command_valid(command: &str) -> bool { +use log::info; + +use crate::server::LspServer; + +pub fn is_command_valid( + command: &str, + server: &LspServer +) -> bool { + let cache_info = server.cache.cache_info.read().unwrap(); + + let cwd = match &cache_info.linter_cache { + Some(pc) => pc, + None => { + info!("缓存系统尚未完成初始化,获取命令有效性取消"); + return false; + } + }; + // 尝试执行命令 - match Command::new(command).output() { + match Command::new(command) + .current_dir(cwd) + .output() { Ok(_) => true, Err(_) => false, }