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")] pub struct LinterStatus { pub tool_name: String, pub available: bool, pub invoke_name: String } impl Default for LinterStatus { fn default() -> Self { LinterStatus { tool_name: "".to_string(), available: false, invoke_name: "".to_string() } } } pub trait AbstractLinterConfiguration { /// - language_id: 语言 id /// - invoker: 调用可执行文件的名字,比如 `iverilog`,`xvlog`,`verible-verilog-syntax` /// - args: 调用执行器进行诊断的命令行参数(不包含文件路径) fn new(language_id: &str, invoker: &str, args: Vec) -> 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 = { let os = std::env::consts::OS; if os == "windows" { self.get_windows_extension() } else { "" } }; let linter_path = self.get_linter_path(); let pathbuf = PathBuf::from_str(linter_path); if linter_path.len() == 0 || !pathbuf.as_ref().unwrap().exists() { format!("{}{}", execute_name, suffix) } else { // 路径存在 let pathbuf = pathbuf.unwrap(); let pathbuf = pathbuf.join(format!("{}{}", execute_name, suffix)); let path_string = pathbuf.to_str().unwrap(); path_string.to_string() } } /// 获取与该工具匹配的诊断器名字与调用函数名。并检查它们是否有效 /// /// 参考链接:https://kirigaya.cn/blog/article?seq=284 fn linter_status(&self) -> LinterStatus; }