From 723ee40a4e0f79b22a70cb7b8592776fd8a01f90 Mon Sep 17 00:00:00 2001 From: LSTM-Kirigaya <1193466151@qq.com> Date: Mon, 9 Dec 2024 19:33:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=20linter=20=E7=9A=84?= =?UTF-8?q?=E8=AF=8A=E6=96=AD=20pipeline=20=E6=9E=B6=E6=9E=84=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/cache_storage.rs | 101 +++++++++++++---- src/diagnostics/common.rs | 17 +-- src/diagnostics/iverilog.rs | 33 ++++-- src/diagnostics/mod.rs | 203 ++++++++++++++++++++++++++++++----- src/diagnostics/modelsim.rs | 33 +++--- src/diagnostics/verible.rs | 25 +++-- src/diagnostics/verilator.rs | 29 ++--- src/diagnostics/vivado.rs | 34 +++--- src/request/config.rs | 10 +- src/request/linter.rs | 3 +- src/server.rs | 16 +-- src/sources.rs | 3 +- src/utils/command.rs | 2 +- sv-parser | 2 +- 14 files changed, 382 insertions(+), 129 deletions(-) diff --git a/src/core/cache_storage.rs b/src/core/cache_storage.rs index 48a1925..ef3adc2 100644 --- a/src/core/cache_storage.rs +++ b/src/core/cache_storage.rs @@ -26,11 +26,32 @@ pub struct CacheItem { pub cache_name: String } +impl Default for CacheItem { + fn default() -> Self { + CacheItem { + file_name: "".to_string(), + size: 0, + version: "".to_string(), + cache_name: "".to_string() + } + } +} + + +struct CacheInfo { + // version + pub version: Option, + /// 解析类型文件缓存的根目录 + pub parser_cache: Option, + /// 第三方 linter 文件缓存的根目录 + pub linter_cache: Option, +} /// 用于进行高效 IR 缓存的模块 pub struct CacheManager { /// 缓存文件夹根目录 pub root_dir: PathBuf, + pub cache_info: Arc>, /// meta 文件内容 pub meta_name: String, /// meta 内容 @@ -40,23 +61,52 @@ pub struct CacheManager { impl CacheManager { pub fn new(root_dir: PathBuf) -> Self { - // 读入 meta 文件 let meta_name = "index.cache"; - let meta_path = root_dir.join(meta_name); - let meta = get_or_init_meta(&meta_path); - - // 如果不存在 root dir,则创建 - if !root_dir.exists() { - match fs::create_dir_all(&root_dir) { - Ok(_) => {}, - Err(err) => info!("error happen when create {root_dir:?}: {err:?}") - } - } + let cache_info = Arc::new(RwLock::new(CacheInfo { + version: None, + parser_cache: None, + linter_cache: None, + })); CacheManager { root_dir, + cache_info, meta_name: meta_name.to_string(), - meta: Arc::new(RwLock::new(meta)) + meta: Arc::new(RwLock::new(HashMap::::new())) + } + } + + pub fn start(&self, version: &str) { + let root_dir = &self.root_dir; + let mut cache_info = self.cache_info.write().unwrap(); + cache_info.version = Some(version.to_string()); + + let linter_cache = root_dir.join(version).join("lc"); + let parser_cache = root_dir.join(version).join("pc"); + + // 如果不存在指定的缓存文件夹,则创建 + // ~/digital-ide/{版本号}/ + // 📁 lc: linter的cache + // 📁 pc: parser的cache + CacheManager::check_dir(&linter_cache); + CacheManager::check_dir(&parser_cache); + + // 读入 meta 文件 + let meta_path = parser_cache.join(&self.meta_name); + let meta = get_or_init_meta(&meta_path); + let mut cache_meta = self.meta.write().unwrap(); + for (key, value) in meta.into_iter() { + cache_meta.insert(key, value); + } + + info!("缓存系统初始化完成,pc: {:?}, lc: {:?}", parser_cache, linter_cache); + cache_info.parser_cache = Some(parser_cache); + cache_info.linter_cache = Some(linter_cache); + } + + fn check_dir(dir: &PathBuf) { + if !dir.exists() { + fs::create_dir_all(dir); } } @@ -123,6 +173,7 @@ impl CacheManager { hash_string } + /// 更新缓存,并写入磁盘 pub fn update_cache(&self, path: &PathBuf, fast: FastHdlparam) { let path_string = path.to_str().unwrap(); let version = self.get_version(path); @@ -138,19 +189,23 @@ impl CacheManager { let mut meta_handle = self.meta.write().unwrap(); meta_handle.insert(path_string.to_string(), cache_item); + + let cache_info = self.cache_info.read().unwrap(); // 准备必要的独立数据塞入线程进行调度 - let meta = (&*meta_handle).clone(); - let meta_save_path = self.root_dir.join(self.meta_name.clone()); - let cache_save_path = self.root_dir.join(cache_name); - - std::thread::spawn(move || { - info!("save meta to {meta_save_path:?}"); - let _ = k_serialize(&meta_save_path, meta); - - info!("save index to {cache_save_path:?}"); - let _ = k_serialize(&cache_save_path, fast); - }); + if let Some(parser_cache) = &cache_info.parser_cache { + let meta = (&*meta_handle).clone(); + let meta_save_path = parser_cache.join(&self.meta_name); + let cache_save_path = parser_cache.join(cache_name); + + std::thread::spawn(move || { + info!("save meta to {meta_save_path:?}"); + let _ = k_serialize(&meta_save_path, meta); + + info!("save index to {cache_save_path:?}"); + let _ = k_serialize(&cache_save_path, fast); + }); + } } } diff --git a/src/diagnostics/common.rs b/src/diagnostics/common.rs index 0a5a40e..b66f7d4 100644 --- a/src/diagnostics/common.rs +++ b/src/diagnostics/common.rs @@ -1,6 +1,9 @@ use std::{path::PathBuf, str::FromStr}; - +#[allow(unused)] +use log::info; use serde::{Deserialize, Serialize}; +use ropey::Rope; +use tower_lsp::lsp_types::{Diagnostic, Url}; #[derive(Deserialize, Serialize, Debug)] #[serde(rename_all = "camelCase")] @@ -22,19 +25,21 @@ impl Default for LinterStatus { } pub trait AbstractLinterConfiguration { - fn new(language_id: &str) -> Self; + /// - language_id: 语言 id + /// - invoker: 调用可执行文件的名字,比如 `iverilog`,`xvlog`,`verible-verilog-syntax` + /// - args: 调用执行器进行诊断的命令行参数(不包含文件路径) + fn new(language_id: &str, invoker: &str, args: Vec) -> Self; - /// 提供一次诊断 - fn provide_diagnostics(&self); - + /// 提供一次诊断目前基于 uri 中的地址读取真实路径来获取诊断结果 + fn provide_diagnostics(&self, uri: &Url, rope: &Rope) -> Vec; /// 获取工具在 Windows 下的后缀,比如 iverilog 就是 exe , xvlog 就是 bat fn get_windows_extension(&self) -> &str; + /// 获取 linter 安装路径,内部实现,内部调用 fn get_linter_path(&self) -> &str; /// 获取真实调用路径,比如 - /// /// iverilog.exe 或者 /path/to/verilog.exe fn get_invoke_name(&self, execute_name: &str) -> String { let suffix = { diff --git a/src/diagnostics/iverilog.rs b/src/diagnostics/iverilog.rs index e3db3ed..bc03fcc 100644 --- a/src/diagnostics/iverilog.rs +++ b/src/diagnostics/iverilog.rs @@ -1,12 +1,14 @@ -use std::{path::PathBuf, str::FromStr}; +use std::process::{Command, Stdio}; use serde::{Deserialize, Serialize}; +use ropey::Rope; +use tower_lsp::lsp_types::{Diagnostic, Url}; use crate::utils::command::is_command_valid; use super::{AbstractLinterConfiguration, LinterStatus}; -#[derive(Default, Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct IverilogConfiguration { pub language_id: String, pub linter: IverilogLinter @@ -15,33 +17,44 @@ pub struct IverilogConfiguration { #[derive(Debug, Serialize, Deserialize)] pub struct IverilogLinter { pub name: String, + pub exe_name: String, /// 目前是否启动 pub enabled: bool, pub path: String, pub args: Vec, } -impl Default for IverilogLinter { - fn default() -> Self { - Self { +impl IverilogLinter { + fn new(invoker: &str, args: Vec) -> Self { + IverilogLinter { name: "iverilog".to_string(), + exe_name: invoker.to_string(), enabled: false, - path: "iverilog".to_string(), - args: Vec::new(), + path: invoker.to_string(), + args } } } impl AbstractLinterConfiguration for IverilogConfiguration { - fn new(language_id: &str) -> Self { + fn new(language_id: &str, invoker: &str, args: Vec) -> Self { IverilogConfiguration { language_id: language_id.to_string(), - linter: IverilogLinter::default() + linter: IverilogLinter::new(invoker, args) } } - fn provide_diagnostics(&self) { + fn provide_diagnostics( + &self, + uri: &Url, + #[allow(unused)] + rope: &Rope + ) -> Vec { + let mut diagnostics = Vec::::new(); + + + diagnostics } fn get_windows_extension(&self) -> &str { diff --git a/src/diagnostics/mod.rs b/src/diagnostics/mod.rs index d1a4b5a..5cd8514 100644 --- a/src/diagnostics/mod.rs +++ b/src/diagnostics/mod.rs @@ -26,7 +26,6 @@ pub use modelsim::*; /// 诊断模块的每一个子诊断器都需要实现如下的函数 /// - provide_diagnostics: 提供一次诊断 /// - - /// 获取诊断核心函数 pub fn provide_diagnostics( uri: Url, @@ -58,27 +57,46 @@ pub fn provide_diagnostics( // 根据配置决定使用哪一个诊断器 // 外层代码需要保证只有一个 linter.enable 为 true - if linter_configuration.verilator.linter.enabled { - info!("verilator linter enter"); - - } else if linter_configuration.verible.linter.enabled { - info!("verible linter enter"); - - } else if linter_configuration.modelsim.linter.enabled { - info!("modelsim linter enter"); - - } else if linter_configuration.vivado.linter.enabled { - info!("vivado linter enter"); - + match linter_configuration { + config if config.iverilog.linter.enabled => { + info!("iverilog linter enter"); + diagnostics.append( + &mut config.iverilog.provide_diagnostics(&uri, rope) + ); + } + config if config.verilator.linter.enabled => { + info!("verilator linter enter"); + diagnostics.append( + &mut config.verilator.provide_diagnostics(&uri, rope) + ); + } + config if config.verible.linter.enabled => { + info!("verible linter enter"); + diagnostics.append( + &mut config.verible.provide_diagnostics(&uri, rope) + ); + } + config if config.modelsim.linter.enabled => { + info!("modelsim linter enter"); + diagnostics.append( + &mut config.modelsim.provide_diagnostics(&uri, rope) + ); + } + config if config.vivado.linter.enabled => { + info!("vivado linter enter"); + diagnostics.append( + &mut config.vivado.provide_diagnostics(&uri, rope) + ); + } + _ => {} } - PublishDiagnosticsParams { uri, diagnostics, version: None } } -/// 根据输入的名字选择诊断器 +/// 根据输入的名字选择诊断器,并更新所有诊断器的基本路径 /// - `linter_name` 为 `"vivado" | "modelsim" | "verilator" | "verible" | "iverilog"` /// - `language_id` 为 `"vhdl" | "verilog" | "systemverilog"` /// - `linter_path` 为第三方的可执行文件的路径 @@ -114,27 +132,44 @@ pub fn update_diagnostics_configuration( "iverilog" => { linter_configuration.iverilog.linter.enabled = true; linter_configuration.iverilog.linter.path = linter_path.to_string(); - info!("{} 诊断器 {} 已经激活, 工作负载为 {}", language_id, linter_name, linter_configuration.iverilog.linter.path); + let invoke_name = linter_configuration.iverilog.get_invoke_name("iverilog"); + info!("{} 诊断器 {} 已经激活, 工作负载为 {}", language_id, linter_name, invoke_name); } "verilator" => { linter_configuration.verilator.linter.enabled = true; linter_configuration.verilator.linter.path = linter_path.to_string(); - info!("{} 诊断器 {} 已经激活, 工作负载为 {}", language_id, linter_name, linter_configuration.verilator.linter.path); + let invoke_name = linter_configuration.verilator.get_invoke_name("verilator"); + info!("{} 诊断器 {} 已经激活, 工作负载为 {}", language_id, linter_name, invoke_name); } "verible" => { linter_configuration.verible.linter.enabled = true; linter_configuration.verible.linter.path = linter_path.to_string(); - info!("{} 诊断器 {} 已经激活, 工作负载为 {}", language_id, linter_name, linter_configuration.verible.linter.path); + let invoke_name = linter_configuration.verible.get_invoke_name("verible-verilog-syntax"); + info!("{} 诊断器 {} 已经激活, 工作负载为 {}", language_id, linter_name, invoke_name); } "modelsim" => { linter_configuration.modelsim.linter.enabled = true; linter_configuration.modelsim.linter.path = linter_path.to_string(); - info!("{} 诊断器 {} 已经激活, 工作负载为 {}", language_id, linter_name, linter_configuration.modelsim.linter.path); + let invoke_name = { + if language_id == "vhdl" { + linter_configuration.modelsim.get_invoke_name("vcom") + } else { + linter_configuration.modelsim.get_invoke_name("vlog") + } + }; + info!("{} 诊断器 {} 已经激活, 工作负载为 {}", language_id, linter_name, invoke_name); } "vivado" => { linter_configuration.vivado.linter.enabled = true; linter_configuration.vivado.linter.path = linter_path.to_string(); - info!("{} 诊断器 {} 已经激活, 工作负载为 {}", language_id, linter_name, linter_configuration.vivado.linter.path); + let invoke_name = { + if language_id == "vhdl" { + linter_configuration.vivado.get_invoke_name("xvhdl") + } else { + linter_configuration.vivado.get_invoke_name("xvlog") + } + }; + info!("{} 诊断器 {} 已经激活, 工作负载为 {}", language_id, linter_name, invoke_name); } _ => { info!("未找到匹配的诊断器: {}", linter_name); @@ -172,12 +207,128 @@ pub struct DigitalLinterConfiguration { impl DigitalLinterConfiguration { pub fn new(language_id: &str) -> Self { - DigitalLinterConfiguration { - iverilog: IverilogConfiguration::new(language_id), - verible: VeribleConfiguration::new(language_id), - verilator: VerilatorConfiguration::new(language_id), - modelsim: ModelsimConfiguration::new(language_id), - vivado: VivadoConfiguration::new(language_id) + match language_id { + "vhdl" => { + DigitalLinterConfiguration { + iverilog: IverilogConfiguration::new( + language_id, + "iverilog", + vec![ + "-t null".to_string() + ] + ), + verible: VeribleConfiguration::new( + language_id, + "verible-verilog-syntax", + vec![] + ), + verilator: VerilatorConfiguration::new( + language_id, + "verilator", + vec![] + ), + modelsim: ModelsimConfiguration::new( + language_id, + "vcom", + vec![ + "-quiet".to_string(), + "-nologo".to_string(), + "-2008".to_string() + ] + ), + vivado: VivadoConfiguration::new( + language_id, + "xvhdl", + vec![ + "--nolog".to_string() + ] + ) + } + } + + "systemverilog" => { + DigitalLinterConfiguration { + iverilog: IverilogConfiguration::new( + language_id, + "iverilog", + vec![ + "-g2012".to_string() + ] + ), + verible: VeribleConfiguration::new( + language_id, + "verible-verilog-syntax", + vec![] + ), + verilator: VerilatorConfiguration::new( + language_id, + "verilator", + vec![ + "--lint-only".to_string(), + "-sv".to_string(), + "-Wall".to_string() + ] + ), + modelsim: ModelsimConfiguration::new( + language_id, + "vlog", + vec![ + "-quiet".to_string(), + "-nologo".to_string(), + "-sv".to_string() + ] + ), + vivado: VivadoConfiguration::new( + language_id, + "xvlog", + vec![ + "--sv".to_string(), + "--nolog".to_string() + ] + ) + } + } + + // 默认为 verilog + _ => { + DigitalLinterConfiguration { + iverilog: IverilogConfiguration::new( + language_id, + "iverilog", + vec![ + "-t null".to_string() + ] + ), + verible: VeribleConfiguration::new( + language_id, + "verible-verilog-syntax", + vec![] + ), + verilator: VerilatorConfiguration::new( + language_id, + "verilator", + vec![ + "--lint-only".to_string(), + "-Wall".to_string() + ] + ), + modelsim: ModelsimConfiguration::new( + language_id, + "vlog", + vec![ + "-quiet".to_string(), + "-nologo".to_string() + ] + ), + vivado: VivadoConfiguration::new( + language_id, + "xvlog", + vec![ + "--nolog".to_string() + ] + ) + } + } } } } diff --git a/src/diagnostics/modelsim.rs b/src/diagnostics/modelsim.rs index ebb85ec..9ce5a91 100644 --- a/src/diagnostics/modelsim.rs +++ b/src/diagnostics/modelsim.rs @@ -1,12 +1,12 @@ -use std::{path::PathBuf, str::FromStr}; - +#[allow(unused)] +use log::info; use serde::{Deserialize, Serialize}; - use crate::utils::command::is_command_valid; - use super::{AbstractLinterConfiguration, LinterStatus}; +use ropey::Rope; +use tower_lsp::lsp_types::{Diagnostic, Url}; -#[derive(Default, Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct ModelsimConfiguration { pub language_id: String, pub linter: ModelsimLinter @@ -16,6 +16,7 @@ pub struct ModelsimConfiguration { #[derive(Debug, Serialize, Deserialize)] pub struct ModelsimLinter { pub name: String, + pub exe_name: String, /// 目前是否启动 pub enabled: bool, pub path: String, @@ -23,28 +24,36 @@ pub struct ModelsimLinter { } -impl Default for ModelsimLinter { - fn default() -> Self { +impl ModelsimLinter { + fn new(invoker: &str, args: Vec) -> Self { Self { name: "modelsim".to_string(), + exe_name: invoker.to_string(), enabled: false, - path: "Modelsim-verilog-syntax".to_string(), - args: Vec::new(), + path: invoker.to_string(), + args, } } } impl AbstractLinterConfiguration for ModelsimConfiguration { - fn new(language_id: &str) -> Self { + fn new(language_id: &str, invoker: &str, args: Vec) -> Self { ModelsimConfiguration { language_id: language_id.to_string(), - linter: ModelsimLinter::default() + linter: ModelsimLinter::new(invoker, args) } } - fn provide_diagnostics(&self) { + fn provide_diagnostics( + &self, + uri: &Url, + #[allow(unused)] + rope: &Rope + ) -> Vec { + let mut diagnostics = Vec::::new(); + diagnostics } fn get_windows_extension(&self) -> &str { diff --git a/src/diagnostics/verible.rs b/src/diagnostics/verible.rs index 88c0b27..d169ab7 100644 --- a/src/diagnostics/verible.rs +++ b/src/diagnostics/verible.rs @@ -10,7 +10,7 @@ use super::{AbstractLinterConfiguration, LinterStatus}; -#[derive(Default, Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct VeribleConfiguration { pub language_id: String, pub linter: VeribleLinter, @@ -20,6 +20,7 @@ pub struct VeribleConfiguration { #[derive(Debug, Serialize, Deserialize)] pub struct VeribleLinter { pub name: String, + pub exe_name: String, /// 目前是否启动 pub enabled: bool, pub path: String, @@ -33,13 +34,14 @@ pub struct VeribleFormat { pub args: Vec, } -impl Default for VeribleLinter { - fn default() -> Self { +impl VeribleLinter { + fn new(invoker: &str, args: Vec) -> Self { Self { name: "verible".to_string(), + exe_name: invoker.to_string(), enabled: false, - path: "verible-verilog-syntax".to_string(), - args: Vec::new(), + path: invoker.to_string(), + args, } } } @@ -116,16 +118,23 @@ fn verible_syntax( impl AbstractLinterConfiguration for VeribleConfiguration { - fn new(language_id: &str) -> Self { + fn new(language_id: &str, invoker: &str, args: Vec) -> Self { VeribleConfiguration { language_id: language_id.to_string(), - linter: VeribleLinter::default(), + linter: VeribleLinter::new(invoker, args), format: VeribleFormat::default() } } - fn provide_diagnostics(&self) { + fn provide_diagnostics( + &self, + uri: &Url, + #[allow(unused)] + rope: &Rope + ) -> Vec { + let mut diagnostics = Vec::::new(); + diagnostics } fn get_linter_path(&self) -> &str { diff --git a/src/diagnostics/verilator.rs b/src/diagnostics/verilator.rs index f5b68be..72f5a3f 100644 --- a/src/diagnostics/verilator.rs +++ b/src/diagnostics/verilator.rs @@ -9,7 +9,7 @@ use crate::utils::command::is_command_valid; use super::{AbstractLinterConfiguration, LinterStatus}; -#[derive(Debug, Default, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct VerilatorConfiguration { pub language_id: String, pub linter: VerilatorLinter, @@ -18,23 +18,21 @@ pub struct VerilatorConfiguration { #[derive(Debug, Serialize, Deserialize)] pub struct VerilatorLinter { pub name: String, + pub exe_name: String, /// 目前是否启动 pub enabled: bool, pub path: String, pub args: Vec, } -impl Default for VerilatorLinter { - fn default() -> Self { +impl VerilatorLinter { + fn new(invoker: &str, args: Vec) -> Self { Self { name: "verilator".to_string(), + exe_name: invoker.to_string(), enabled: false, - path: "verilator".to_string(), - args: vec![ - "--lint-only".to_string(), - "--sv".to_string(), - "-Wall".to_string(), - ], + path: invoker.to_string(), + args, } } } @@ -125,15 +123,22 @@ fn verilator_syntax( impl AbstractLinterConfiguration for VerilatorConfiguration { - fn new(language_id: &str) -> Self { + fn new(language_id: &str, invoker: &str, args: Vec) -> Self { VerilatorConfiguration { language_id: language_id.to_string(), - linter: VerilatorLinter::default() + linter: VerilatorLinter::new(invoker, args) } } - fn provide_diagnostics(&self) { + fn provide_diagnostics( + &self, + uri: &Url, + #[allow(unused)] + rope: &Rope + ) -> Vec { + let mut diagnostics = Vec::::new(); + diagnostics } fn get_linter_path(&self) -> &str { diff --git a/src/diagnostics/vivado.rs b/src/diagnostics/vivado.rs index 9171d6f..e26df89 100644 --- a/src/diagnostics/vivado.rs +++ b/src/diagnostics/vivado.rs @@ -1,10 +1,13 @@ +#[allow(unused)] +use log::info; use serde::{Deserialize, Serialize}; - use crate::utils::command::is_command_valid; +use ropey::Rope; +use tower_lsp::lsp_types::{Diagnostic, Url}; use super::{AbstractLinterConfiguration, LinterStatus}; -#[derive(Debug, Default, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct VivadoConfiguration { pub language_id: String, pub linter: VivadoLinter, @@ -13,37 +16,42 @@ pub struct VivadoConfiguration { #[derive(Debug, Serialize, Deserialize)] pub struct VivadoLinter { pub name: String, + pub exe_name: String, /// 目前是否启动 pub enabled: bool, pub path: String, pub args: Vec, } -impl Default for VivadoLinter { - fn default() -> Self { +impl VivadoLinter { + fn new(invoker: &str, args: Vec) -> Self { Self { name: "vivado".to_string(), + exe_name: invoker.to_string(), enabled: false, - path: "Vivado".to_string(), - args: vec![ - "--lint-only".to_string(), - "--sv".to_string(), - "-Wall".to_string(), - ], + path: invoker.to_string(), + args, } } } impl AbstractLinterConfiguration for VivadoConfiguration { - fn new(language_id: &str) -> Self { + fn new(language_id: &str, invoker: &str, args: Vec) -> Self { VivadoConfiguration { language_id: language_id.to_string(), - linter: VivadoLinter::default() + linter: VivadoLinter::new(invoker, args) } } - fn provide_diagnostics(&self) { + fn provide_diagnostics( + &self, + uri: &Url, + #[allow(unused)] + rope: &Rope + ) -> Vec { + let mut diagnostics = Vec::::new(); + diagnostics } fn get_linter_path(&self) -> &str { diff --git a/src/request/config.rs b/src/request/config.rs index 22d28f8..6ad30e4 100644 --- a/src/request/config.rs +++ b/src/request/config.rs @@ -69,9 +69,10 @@ fn update_configuration( let linter_name_configuration = &configs[0]; let linter_path_configuration = &configs[1]; - // something like digital-ide.function.lsp.linter.vlog.diagnostor + // linter_name_config_name 形如 digital-ide.function.lsp.linter.vlog.diagnostor let linter_name_config_name = &linter_name_configuration.name; + // 同步到全局配置中 lsp_configuration.insert( linter_name_config_name.to_string(), linter_name_configuration.value.clone() @@ -82,12 +83,7 @@ fn update_configuration( // linter_name_config_name 形如 digital-ide.function.lsp.linter.vlog.diagnostor let mut cookies = linter_name_config_name.split("."); let name = cookies.nth(4).unwrap(); - match name { - "vlog" => "verilog", - "vhdl" => "vhdl", - "svlog" => "systemverilog", - _ => return - } + name }; let linter_name = linter_name_configuration.value.as_str().unwrap(); diff --git a/src/request/linter.rs b/src/request/linter.rs index ad05270..c72d32b 100644 --- a/src/request/linter.rs +++ b/src/request/linter.rs @@ -46,7 +46,6 @@ fn get_linter_status( linter_path: &str ) -> Result { let configuration = backend.server.configuration.read().unwrap(); - // 获取对应语言的配置项目 let configuration = match language_id { "verilog" => &configuration.vlog_linter_configuration, @@ -86,7 +85,7 @@ fn get_linter_status( _ => { return Err(tower_lsp::jsonrpc::Error { code: tower_lsp::jsonrpc::ErrorCode::InvalidRequest, - message: Cow::Owned(format!("无效的语言 ID {}", language_id)), + message: Cow::Owned(format!("无效的诊断器 {}", linter_name)), data: None }); } diff --git a/src/server.rs b/src/server.rs index e42e5b6..6935001 100644 --- a/src/server.rs +++ b/src/server.rs @@ -131,11 +131,7 @@ impl Default for LspConfiguration { impl LanguageServer for Backend { async fn initialize(&self, params: InitializeParams) -> Result { // 申明 LSP 的基本信息和提供的能力 - let server_info = Some(ServerInfo { - name: "Digital IDE 专用 LSP 后端服务器".to_string(), - version: Some("0.4.0".to_string()) - }); - + let mut version = "0.4.0".to_string(); let root_uri = ¶ms.root_uri; let mut configure = self.server.configuration.write().unwrap(); @@ -144,10 +140,16 @@ impl LanguageServer for Backend { if let Some(serde_json::Value::Object(options)) = params.initialization_options { let extension_path = options.get("extensionPath").unwrap().as_str().unwrap(); let tool_chain = options.get("toolChain").unwrap().as_str().unwrap(); + version = options.get("version").unwrap().as_str().unwrap().to_string(); configure.tool_chain = tool_chain.to_string(); configure.extension_path = extension_path.to_string(); } + let server_info = Some(ServerInfo { + name: "Digital IDE 专用 LSP 后端服务器".to_string(), + version: Some(version.to_string()) + }); + info!("当前客户端初始化结果"); info!("workspaceFolder: {:?}", configure.workspace_folder); info!("extensionPath: {:?}", configure.extension_path); @@ -159,8 +161,8 @@ impl LanguageServer for Backend { &configure.extension_path ); - // 初始化诊断器 - + // 初始化系统缓存路径 + self.server.cache.start(&version); let text_document_sync = TextDocumentSyncCapability::Options( TextDocumentSyncOptions { diff --git a/src/sources.rs b/src/sources.rs index 93ddcd5..7c51d0e 100644 --- a/src/sources.rs +++ b/src/sources.rs @@ -31,7 +31,6 @@ use sv_parser::*; use vhdl_lang::Project; use thread::JoinHandle; use tower_lsp::lsp_types::*; -use walkdir::WalkDir; impl LspServer { pub fn did_open(&self, params: DidOpenTextDocumentParams) -> PublishDiagnosticsParams { @@ -100,6 +99,8 @@ impl LspServer { } } + /// 保存时触发的行为 + /// - 提供诊断信息(主要是第三方诊断器,因为 save 后磁盘上的内容就和缓冲区中的一致了) pub fn did_save(&self, params: DidSaveTextDocumentParams) -> PublishDiagnosticsParams { let urls = self.srcs.names.read().unwrap().keys().cloned().collect(); let file_id = self.srcs.get_id(¶ms.text_document.uri); diff --git a/src/utils/command.rs b/src/utils/command.rs index 11c8887..17655d1 100644 --- a/src/utils/command.rs +++ b/src/utils/command.rs @@ -3,7 +3,7 @@ use std::process::Command; pub fn is_command_valid(command: &str) -> bool { // 尝试执行命令 match Command::new(command).output() { - Ok(output) => output.status.success(), + Ok(_) => true, Err(_) => false, } } diff --git a/sv-parser b/sv-parser index b6ae8b8..ba95abd 160000 --- a/sv-parser +++ b/sv-parser @@ -1 +1 @@ -Subproject commit b6ae8b8a1ff22609e2a837b12dd798226f299f71 +Subproject commit ba95abd436b0a032e0cfdcb9400ce2cfb678792f