From e0753a25f9e9e5f5db0a3eba6af1e6994e76b234 Mon Sep 17 00:00:00 2001 From: LSTM-Kirigaya <1193466151@qq.com> Date: Wed, 9 Oct 2024 17:30:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8E=BB=E9=99=A4=20fast=20=E8=AE=A1=E7=AE=97?= =?UTF-8?q?=E4=B8=AD=20params=20=E9=87=8D=E5=A4=8D=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build_all.sh | 0 src/completion/sv.rs | 2 + src/core/hdlparam.rs | 14 +++ src/core/sv_parser.rs | 168 +++++++++++++++++++----------------- src/hover/feature.rs | 68 ++++++++------- src/hover/sv.rs | 25 +++--- src/main.rs | 3 +- src/request/mod.rs | 67 +++++++------- src/request/notification.rs | 42 +++++++++ src/server.rs | 5 ++ src/sources.rs | 109 +++++++++++++++++------ src/test/mod.rs | 7 ++ vhdl-parser | 2 +- 13 files changed, 330 insertions(+), 182 deletions(-) mode change 100644 => 100755 build_all.sh create mode 100644 src/request/notification.rs diff --git a/build_all.sh b/build_all.sh old mode 100644 new mode 100755 diff --git a/src/completion/sv.rs b/src/completion/sv.rs index 489362f..9c88502 100644 --- a/src/completion/sv.rs +++ b/src/completion/sv.rs @@ -94,6 +94,8 @@ pub fn completion(server: &LSPServer, params: &CompletionParams) -> Option>( server.key_comps .iter() diff --git a/src/core/hdlparam.rs b/src/core/hdlparam.rs index 025a6c9..75d254b 100644 --- a/src/core/hdlparam.rs +++ b/src/core/hdlparam.rs @@ -419,5 +419,19 @@ impl HdlParam { } None } + + /// 跟随一个路径进行删除 + pub fn delete_file(&self, path_string: &str) { + let mut path_to_hdl_file = self.path_to_hdl_file.write().unwrap(); + if let Some(hdl_file) = path_to_hdl_file.get(path_string) { + // 根据 hdl_file.fast.content 删除 self.module_name_to_path + let mut module_name_to_path = self.module_name_to_path.write().unwrap(); + for module_info in &hdl_file.fast.content { + module_name_to_path.remove(&module_info.name); + } + } + path_to_hdl_file.remove(path_string); + // TODO: 引入前端的 solve unhandled instance 机制 + } } \ No newline at end of file diff --git a/src/core/sv_parser.rs b/src/core/sv_parser.rs index 57999ef..6f10670 100644 --- a/src/core/sv_parser.rs +++ b/src/core/sv_parser.rs @@ -1,7 +1,9 @@ +use std::collections::HashSet; use std::fs::{self, File}; use std::io::BufRead; use std::io::BufReader; use std::path::PathBuf; +use log::info; use regex::Regex; use ropey::Rope; use tower_lsp::lsp_types::Url; @@ -54,6 +56,9 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re }; let mut ansi_port_last_dir = ""; + // TODO: 搞清楚为什么会出现重复 + let mut added_param_names = HashSet::::new(); + let content = syntax_tree.text.text().split('\n') .map(|s| s.to_string()) .collect::>(); @@ -114,48 +119,51 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re if let Some(id) = unwrap_node!(x, ParameterIdentifier) { let id = get_identifier(id).unwrap(); let name = syntax_tree.get_str(&id).unwrap(); - match unwrap_node!(x, ParameterDeclarationParam, ParameterPortDeclarationParamList) { - Some(RefNode::ParameterDeclarationParam(param_node)) => { - // println!("{:?}", param_node); - let keyword_locate = param_node.nodes.0.nodes.0; - // println!("keyword {:#?}", keyword_locate); - let (start_line, start_character) = (id.line, get_column_by_offset(&content, keyword_locate.offset) as u32); - let (mut end_line, mut end_character) = (id.line, start_character + id.len as u32); - let net_type = match unwrap_node!(param_node, DataType) { - Some(RefNode::DataType(data_type)) => { - let id = unwrap_node!(data_type, SimpleIdentifier, Keyword); - if id == None { - "wire" - } else { - let id = get_identifier(id.unwrap()).unwrap(); - syntax_tree.get_str(&id).unwrap() + if !added_param_names.contains(name) { + added_param_names.insert(name.to_string()); + match unwrap_node!(x, ParameterDeclarationParam, ParameterPortDeclarationParamList) { + Some(RefNode::ParameterDeclarationParam(param_node)) => { + // println!("{:?}", param_node); + let keyword_locate = param_node.nodes.0.nodes.0; + // println!("keyword {:#?}", keyword_locate); + let (start_line, start_character) = (id.line, get_column_by_offset(&content, keyword_locate.offset) as u32); + let (mut end_line, mut end_character) = (id.line, start_character + id.len as u32); + let net_type = match unwrap_node!(param_node, DataType) { + Some(RefNode::DataType(data_type)) => { + let id = unwrap_node!(data_type, SimpleIdentifier, Keyword); + if id == None { + "wire" + } else { + let id = get_identifier(id.unwrap()).unwrap(); + syntax_tree.get_str(&id).unwrap() + } } - } - _ => "wire" - }; - let init = if let Some(init) = unwrap_node!(param_node, ConstantMintypmaxExpression) { - match init { - RefNode::ConstantMintypmaxExpression(expression) => { - // println!("expression {:?}", x); - let param_init = sv_parser::NeedParseExpression::Parameter(expression.clone()); - let (exp, last_locate) = parse_expression(&syntax_tree, ¶m_init); - (end_line, end_character) = if last_locate != None { - // println!("param {:?} lastlocate {:?}", name, last_locate); - (last_locate.unwrap().line, (get_column_by_offset(&content, last_locate.unwrap().offset) + last_locate.unwrap().len) as u32) - } else { - (end_line, end_character) - }; - // println!("end pos {} {}", end_line, end_character); - exp + _ => "wire" + }; + let init = if let Some(init) = unwrap_node!(param_node, ConstantMintypmaxExpression) { + match init { + RefNode::ConstantMintypmaxExpression(expression) => { + // println!("expression {:?}", x); + let param_init = sv_parser::NeedParseExpression::Parameter(expression.clone()); + let (exp, last_locate) = parse_expression(&syntax_tree, ¶m_init); + (end_line, end_character) = if last_locate != None { + // println!("param {:?} lastlocate {:?}", name, last_locate); + (last_locate.unwrap().line, (get_column_by_offset(&content, last_locate.unwrap().offset) + last_locate.unwrap().len) as u32) + } else { + (end_line, end_character) + }; + // println!("end pos {} {}", end_line, end_character); + exp + } + _ => "unknown".to_string() } - _ => "unknown".to_string() - } - } else { - "unknown".to_string() - }; - hdlparam.add_parameter(name, net_type, init.as_str(), start_line, start_character, end_line, end_character); + } else { + "unknown".to_string() + }; + hdlparam.add_parameter(name, net_type, init.as_str(), start_line, start_character, end_line, end_character); + } + _ => () } - _ => () } } } @@ -163,49 +171,53 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re if let Some(id) = unwrap_node!(x, ParameterIdentifier) { let id = get_identifier(id).unwrap(); let name = syntax_tree.get_str(&id).unwrap(); - match unwrap_node!(x, ParameterDeclarationParam, ParameterPortDeclarationParamList) { - Some(RefNode::ParameterDeclarationParam(param_node)) => { - // println!("{:?}", param_node); - let keyword_locate = param_node.nodes.0.nodes.0; - // println!("keyword {:#?}", keyword_locate); - let (start_line, start_character) = (id.line, get_column_by_offset(&content, keyword_locate.offset) as u32); - let (mut end_line, mut end_character) = (id.line, start_character + id.len as u32); - let net_type = match unwrap_node!(param_node, DataType) { - Some(RefNode::DataType(data_type)) => { - let id = unwrap_node!(data_type, SimpleIdentifier, Keyword); - if id == None { - "wire" - } else { - let id = get_identifier(id.unwrap()).unwrap(); - syntax_tree.get_str(&id).unwrap() + if !added_param_names.contains(name) { + added_param_names.insert(name.to_string()); + match unwrap_node!(x, ParameterDeclarationParam, ParameterPortDeclarationParamList) { + Some(RefNode::ParameterDeclarationParam(param_node)) => { + // println!("{:?}", param_node); + let keyword_locate = param_node.nodes.0.nodes.0; + // println!("keyword {:#?}", keyword_locate); + let (start_line, start_character) = (id.line, get_column_by_offset(&content, keyword_locate.offset) as u32); + let (mut end_line, mut end_character) = (id.line, start_character + id.len as u32); + let net_type = match unwrap_node!(param_node, DataType) { + Some(RefNode::DataType(data_type)) => { + let id = unwrap_node!(data_type, SimpleIdentifier, Keyword); + if id == None { + "wire" + } else { + let id = get_identifier(id.unwrap()).unwrap(); + syntax_tree.get_str(&id).unwrap() + } } - } - _ => "wire" - }; - let init = if let Some(init) = unwrap_node!(param_node, ConstantMintypmaxExpression) { - match init { - RefNode::ConstantMintypmaxExpression(expression) => { - // println!("expression {:?}", x); - let param_init = sv_parser::NeedParseExpression::Parameter(expression.clone()); - let (exp, last_locate) = parse_expression(&syntax_tree, ¶m_init); - (end_line, end_character) = if last_locate != None { - // println!("param {:?} lastlocate {:?}", name, last_locate); - (last_locate.unwrap().line, (get_column_by_offset(&content, last_locate.unwrap().offset) + last_locate.unwrap().len) as u32) - } else { - (end_line, end_character) - }; - // println!("end pos {} {}", end_line, end_character); - exp + _ => "wire" + }; + let init = if let Some(init) = unwrap_node!(param_node, ConstantMintypmaxExpression) { + match init { + RefNode::ConstantMintypmaxExpression(expression) => { + // println!("expression {:?}", x); + let param_init = sv_parser::NeedParseExpression::Parameter(expression.clone()); + let (exp, last_locate) = parse_expression(&syntax_tree, ¶m_init); + (end_line, end_character) = if last_locate != None { + // println!("param {:?} lastlocate {:?}", name, last_locate); + (last_locate.unwrap().line, (get_column_by_offset(&content, last_locate.unwrap().offset) + last_locate.unwrap().len) as u32) + } else { + (end_line, end_character) + }; + // println!("end pos {} {}", end_line, end_character); + exp + } + _ => "unknown".to_string() } - _ => "unknown".to_string() - } - } else { - "unknown".to_string() - }; - hdlparam.add_parameter(name, net_type, init.as_str(), start_line, start_character, end_line, end_character); + } else { + "unknown".to_string() + }; + hdlparam.add_parameter(name, net_type, init.as_str(), start_line, start_character, end_line, end_character); + } + _ => () } - _ => () } + } } RefNode::PortDeclaration(x) => { diff --git a/src/hover/feature.rs b/src/hover/feature.rs index 4c93fd1..462feef 100644 --- a/src/hover/feature.rs +++ b/src/hover/feature.rs @@ -340,40 +340,50 @@ fn make_param_desc_hover(param: &crate::core::hdlparam::Parameter, range: &Range pub fn hover_module_declaration( server: &LSPServer, token_name: &str, - definition: &GenericDec, language_id: &str ) -> Option { - let module_info = match definition.def_type { - DefinitionType::GenericScope => { - let pathbuf = PathBuf::from_str(definition.url.path()).unwrap(); - let pathbuf = to_escape_path(&pathbuf); - let path_string = pathbuf.to_str().unwrap(); + // let module_info = match definition.def_type { + // DefinitionType::GenericScope => { + // let pathbuf = PathBuf::from_str(definition.url.path()).unwrap(); + // let pathbuf = to_escape_path(&pathbuf); + // let path_string = pathbuf.to_str().unwrap(); - let hdlparam = &server.srcs.hdl_param; - let search_result = || { - if let Some(hdl_file) = hdlparam.path_to_hdl_file.read().unwrap().get(path_string) { - for module in &hdl_file.fast.content { - if module.name == definition.ident { - return Some((module.clone(), path_string.to_string())); - } - } - } + // let hdlparam = &server.srcs.hdl_param; + // let search_result = || { + // if let Some(hdl_file) = hdlparam.path_to_hdl_file.read().unwrap().get(path_string) { + // for module in &hdl_file.fast.content { + // if module.name == definition.ident { + // return Some((module.clone(), path_string.to_string())); + // } + // } + // } - None - }; - search_result() - } + // None + // }; + // search_result() + // } - _ => { - let search_result = || { - if let Some(module) = server.srcs.hdl_param.find_module_by_name(token_name) { - let path_string = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap_or("unknown".to_string()); - return Some((module, path_string)); - } - None - }; - search_result() - } + // _ => { + // let search_result = || { + // if let Some(module) = server.srcs.hdl_param.find_module_by_name(token_name) { + // let path_string = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap_or("unknown".to_string()); + // return Some((module, path_string)); + // } + // None + // }; + // search_result() + // } + // }; + + let module_info = { + let search_result = || { + if let Some(module) = server.srcs.hdl_param.find_module_by_name(token_name) { + let path_string = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap_or("unknown".to_string()); + return Some((module, path_string)); + } + None + }; + search_result() }; if let Some((module, path_string)) = module_info { diff --git a/src/hover/sv.rs b/src/hover/sv.rs index 405bbb5..cfa7b1d 100644 --- a/src/hover/sv.rs +++ b/src/hover/sv.rs @@ -1,3 +1,4 @@ +#[allow(unused)] use log::info; use regex::Regex; use ropey::Rope; @@ -31,12 +32,7 @@ pub fn hover(server: &LSPServer, params: &HoverParams) -> Option { if let Some(hover) = hover_macro(server, &line_text, pos, &language_id) { return Some(hover); } - - let scope_tree = server.srcs.scope_tree.read().ok()?; - let global_scope = scope_tree.as_ref().unwrap(); - let symbol_definition: GenericDec = global_scope - .get_definition(&token, file.text.pos_to_byte(&pos), doc)?; // match positional port param if let Some(hover) = hover_position_port_param(server, &line_text, doc, pos, &language_id) { @@ -44,12 +40,7 @@ pub fn hover(server: &LSPServer, params: &HoverParams) -> Option { } // match module name - if let Some(hover) = hover_module_declaration(server, &token, &symbol_definition, &language_id) { - return Some(hover); - } - - // match 正常 symbol - if let Some(hover) = hover_common_symbol(server, &token, &symbol_definition, &file, doc, pos, &language_id) { + if let Some(hover) = hover_module_declaration(server, &token, &language_id) { return Some(hover); } @@ -57,6 +48,17 @@ pub fn hover(server: &LSPServer, params: &HoverParams) -> Option { if let Some(hover) = hover_format_digit(&line_text, pos, &language_id) { return Some(hover); } + + let scope_tree = server.srcs.scope_tree.read().ok()?; + let global_scope = scope_tree.as_ref().unwrap(); + + let symbol_definition: GenericDec = global_scope + .get_definition(&token, file.text.pos_to_byte(&pos), doc)?; + + // match 正常 symbol + if let Some(hover) = hover_common_symbol(server, &token, &symbol_definition, &file, doc, pos, &language_id) { + return Some(hover); + } None } @@ -242,7 +244,6 @@ fn hover_common_symbol( if let Some(instance) = hdlparam.walk_instantiation(&path_string, find_name_condition) { - info!("instance {:?}", instance); let def_line = file.text.byte_to_line(symbol_definition.byte_idx()); let mut markdown_comment = match make_hover_with_comment(&file.text, def_line, &language_id, true) { Some(hover) => { diff --git a/src/main.rs b/src/main.rs index e1dad98..f7b98d6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ #![recursion_limit = "256"] -use request::{ CustomParamRequest, CustomRequest, DoFastApi }; +use request::{ CustomParamRequest, CustomRequest, DoFastApi, UpdateFastApi }; use log::info; use std::sync::Arc; @@ -45,6 +45,7 @@ async fn main() { .custom_method("custom/request", CustomRequest) .custom_method("custom/paramRequest", CustomParamRequest) .custom_method("api/fast", DoFastApi) + .custom_method("api/update-fast", UpdateFastApi) .finish(); Server::new(stdin, stdout, socket) diff --git a/src/request/mod.rs b/src/request/mod.rs index bf4a1ff..0301d4c 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -5,7 +5,6 @@ use std::path::PathBuf; use std::sync::Arc; use log::info; -use notification::Notification; use ropey::Rope; use serde::{Deserialize, Serialize}; use tower_lsp::jsonrpc::Result; @@ -20,6 +19,7 @@ use crate::utils::*; use crate::server::Backend; use crate::sources::recovery_sv_parse; +pub mod notification; #[derive(Clone)] pub struct CustomRequest; @@ -89,7 +89,7 @@ fn make_textdocumenitem_from_path(path_buf: &PathBuf) -> Option(path: String, backend: &Arc) -> Result { +pub fn do_fast(path: String, backend: &Arc) -> Result { info!("parse fast \"{}\"", path); let language_id = get_language_id_by_path_str(&path); @@ -201,40 +201,37 @@ fn do_vhdl_fast(path: &str, backend: &Arc) -> Result { }) } +#[derive(Clone)] +pub struct UpdateFastApi; -// 下面是服务端发送给客户端的 -#[derive(Serialize, Deserialize)] -pub struct StringNotification { - pub content: String +impl <'a>tower_lsp::jsonrpc::Method<&'a Arc, (DoFastApiRequestParams, ), Result> for UpdateFastApi { + type Future = future::Ready>; + + fn invoke(&self, _server: &'a Arc, _params: (DoFastApiRequestParams, )) -> Self::Future { + let request_param = _params.0; + let path = request_param.path; + let hdlparam = update_fast(path, _server); + future::ready(hdlparam) + } } -impl Notification for StringNotification { - const METHOD: &'static str = "update/string"; - type Params = Self; -} +pub fn update_fast(path: String, backend: &Arc) -> Result { + { + let fast_sync_controller = backend.server.srcs.fast_sync_controller.read().unwrap(); + if let Some(fast_lock) = fast_sync_controller.get(&path) { + let fast_lock = fast_lock.clone(); + drop(fast_sync_controller); + let _unused = fast_lock.write().unwrap(); + } + } - -#[derive(Serialize, Deserialize)] -pub struct UpdateFastNotification { - pub fast: FastHdlparam, - pub path: String -} - -impl Notification for UpdateFastNotification { - const METHOD: &'static str = "update/fast"; - type Params = Self; -} - -// #[allow(unused)] -// pub async fn update_fast_to_client(fast: FastHdlparam, path: &PathBuf) { -// // info!("send fast to foreend {:?}", fast); - -// info!("send fast to foreend"); -// let backend = GLOBAL_BACKEND.get().unwrap(); -// let path = path.to_str().unwrap_or("").to_string(); - -// let params = UpdateFastNotification { fast, path }; -// info!("backend client: {:?}", backend.client); - -// backend.client.send_notification::(params).await; -// } \ No newline at end of file + // 去缓存中寻找 + let hdl_param = backend.server.srcs.hdl_param.clone(); + let path_to_hdl_file = hdl_param.path_to_hdl_file.read().unwrap(); + if let Some(hdl_file) = path_to_hdl_file.get(&path) { + let fast = hdl_file.fast.clone(); + Ok(fast) + } else { + do_fast(path, backend) + } +} \ No newline at end of file diff --git a/src/request/notification.rs b/src/request/notification.rs new file mode 100644 index 0000000..45ad3c9 --- /dev/null +++ b/src/request/notification.rs @@ -0,0 +1,42 @@ +use serde::{Deserialize, Serialize}; +use tower_lsp::lsp_types::notification::Notification; + +use crate::core::hdlparam::FastHdlparam; + + +// 下面是服务端发送给客户端的 +#[derive(Serialize, Deserialize)] +pub struct StringNotification { + pub content: String +} + +impl Notification for StringNotification { + const METHOD: &'static str = "update/string"; + type Params = Self; +} + + +#[derive(Serialize, Deserialize)] +pub struct UpdateFastNotification { + pub fast: FastHdlparam, + pub path: String +} + +impl Notification for UpdateFastNotification { + const METHOD: &'static str = "update/fast"; + type Params = Self; +} + +// #[allow(unused)] +// pub async fn update_fast_to_client(fast: FastHdlparam, path: &PathBuf) { +// // info!("send fast to foreend {:?}", fast); + +// info!("send fast to foreend"); +// let backend = GLOBAL_BACKEND.get().unwrap(); +// let path = path.to_str().unwrap_or("").to_string(); + +// let params = UpdateFastNotification { fast, path }; +// info!("backend client: {:?}", backend.client); + +// backend.client.send_notification::(params).await; +// } \ No newline at end of file diff --git a/src/server.rs b/src/server.rs index 94eb0e2..5570d59 100644 --- a/src/server.rs +++ b/src/server.rs @@ -4,6 +4,7 @@ use crate::completion::keyword::*; use flexi_logger::LoggerHandle; #[allow(unused)] use log::{debug, info, warn}; +use notification::DidDeleteFiles; use serde::{Deserialize, Serialize}; use std::string::ToString; use std::sync::{Mutex, RwLock}; @@ -248,6 +249,10 @@ impl LanguageServer for Backend { self.server.did_change(params); } + async fn did_delete_files(&self, params: DeleteFilesParams) { + self.server.did_delete_files(params); + } + async fn did_save(&self, params: DidSaveTextDocumentParams) { let diagnostics = self.server.did_save(params); self.client diff --git a/src/sources.rs b/src/sources.rs index b0df08e..2573ae9 100644 --- a/src/sources.rs +++ b/src/sources.rs @@ -108,6 +108,40 @@ impl LSPServer { &self.conf.read().unwrap(), ) } + + pub fn did_delete_files(&self, params: DeleteFilesParams) { + // 删除 sources 内对应的文件 + for file_delete in params.files { + let url = Url::parse(&file_delete.uri).unwrap(); + let pathbuf = PathBuf::from_str(url.path()).unwrap(); + let pathbuf = to_escape_path(&pathbuf); + let path_string = pathbuf.to_str().unwrap(); + + { + let mut fast_sync_controller = self.srcs.fast_sync_controller.write().unwrap(); + fast_sync_controller.remove(path_string); + } + + self.srcs.hdl_param.delete_file(path_string); + + { + let mut names = self.srcs.names.write().unwrap(); + names.remove(&url); + } + + { + let mut global_scope = self.srcs.scope_tree.write().unwrap(); + match &mut *global_scope { + Some(scope) => { + scope.defs.retain(|x| x.url() != url); + scope.scopes.retain(|x| x.url() != url); + }, + None => {}, + } + } + + } + } } /// The Source struct holds all file specific information @@ -176,14 +210,14 @@ pub struct Sources { pub meta: Arc>>>>, /// scope tree 类型的树形结构,用于提供 sv 的 lsp pub scope_tree: Arc>>, - /// 存储 vhdl design file ir 的对象 - pub design_file_map: Arc>>, // include directories, passed to parser to resolve `include pub include_dirs: Arc>>, // source directories pub source_dirs: Arc>>, /// hdlparam 后端实现 pub hdl_param: Arc, + // 同步解析线程和发送 fast 请求的 + pub fast_sync_controller: Arc>>>> } impl std::default::Default for Sources { @@ -199,10 +233,10 @@ impl Sources { names: Arc::new(RwLock::new(HashMap::new())), meta: Arc::new(RwLock::new(Vec::new())), scope_tree: Arc::new(RwLock::new(None)), - design_file_map: Arc::new(RwLock::new(HashMap::new())), include_dirs: Arc::new(RwLock::new(Vec::new())), source_dirs: Arc::new(RwLock::new(Vec::new())), - hdl_param: Arc::new(HdlParam::new()) + hdl_param: Arc::new(HdlParam::new()), + fast_sync_controller: Arc::new(RwLock::new(HashMap::>>::new())) } } pub fn init(&self) { @@ -254,6 +288,15 @@ impl Sources { info!("launch worker to parse {:?}", doc.uri.to_string()); let language_id = doc.language_id.to_string(); + // 新建一个 fast controller 用于控制下方的解析线程和外部的请求函数 + let pathbuf = PathBuf::from_str(&doc.uri.path()).unwrap(); + let pathbuf = to_escape_path(&pathbuf); + let path_string = pathbuf.to_str().unwrap(); + let mut fast_controller = self.fast_sync_controller.write().unwrap(); + let fast_lock = Arc::new(RwLock::new(true)); + fast_controller.insert(path_string.to_string(), fast_lock.clone()); + drop(fast_controller); + // spawn parse thread let parse_handle = thread::spawn(move || { let (lock, cvar) = &*valid_parse2; @@ -266,28 +309,32 @@ impl Sources { info!("do parse in {:?}, language_id: {:?}", uri.to_string(), language_id); - match language_id.as_str() { - "vhdl" => { - vhdl_parser_pipeline( - &source_handle, - &scope_handle, - &hdl_param_handle, - &text, - uri, - ); - }, - "verilog" | "systemverilog" => { - sv_parser_pipeline( - &source_handle, - &scope_handle, - &hdl_param_handle, - &text, - uri, - range, - &inc_dirs.read().unwrap() - ); - }, - _ => {} + // 此时 update fast 的地方为 write 会进行阻塞 + { + let _unused = fast_lock.read().unwrap(); + match language_id.as_str() { + "vhdl" => { + vhdl_parser_pipeline( + &source_handle, + &scope_handle, + &hdl_param_handle, + &text, + uri, + ); + }, + "verilog" | "systemverilog" => { + sv_parser_pipeline( + &source_handle, + &scope_handle, + &hdl_param_handle, + &text, + uri, + range, + &inc_dirs.read().unwrap() + ); + }, + _ => {} + } } // 通过条件锁进行控制 @@ -535,6 +582,10 @@ pub fn sv_parser_pipeline( last_change_range: &Option, include_dirs: &Vec ) { + if doc.len_chars() == 0 { + return; + } + let path = match PathBuf::from_str(uri.path()) { Ok(path) => path, Err(error) => { @@ -608,6 +659,10 @@ pub fn vhdl_parser_pipeline( doc: &Rope, uri: &Url ) { + if doc.len_chars() == 0 { + return; + } + let path = match PathBuf::from_str(uri.path()) { Ok(path) => path, Err(error) => { @@ -698,6 +753,7 @@ impl LSPSupport for Rope { return self.line_to_char(pos.line as usize) + line_slice.utf16_cu_to_char(pos.character as usize); } fn byte_to_pos(&self, byte_idx: usize) -> Position { + // info!("byte_idx: {byte_idx}"); return self.char_to_pos(self.byte_to_char(min(byte_idx, self.len_bytes() - 1))); } fn char_to_pos(&self, char_idx: usize) -> Position { @@ -737,6 +793,7 @@ impl<'a> LSPSupport for RopeSlice<'a> { self.line_to_char(pos.line as usize) + line_slice.utf16_cu_to_char(pos.character as usize) } fn byte_to_pos(&self, byte_idx: usize) -> Position { + // info!("byte_idx: {byte_idx}"); self.char_to_pos(self.byte_to_char(min(byte_idx, self.len_bytes() - 1))) } fn char_to_pos(&self, char_idx: usize) -> Position { diff --git a/src/test/mod.rs b/src/test/mod.rs index acf6eb0..edafa88 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -59,6 +59,13 @@ mod test_fast { println!("{:#?}", fast.content); } + #[test] + fn test_controller() { + let fast = sv_parser("/home/dide/project/Digital-Test/MipsDesign/src/Controller/controller.v"); + let fast = fast.unwrap(); + println!("{:#?}", fast.content[0].params); + } + #[test] fn test_testfiles() { let ws_path = env::current_dir().unwrap(); diff --git a/vhdl-parser b/vhdl-parser index e8e7466..a058a7c 160000 --- a/vhdl-parser +++ b/vhdl-parser @@ -1 +1 @@ -Subproject commit e8e746628785df31545fd465489dc75eba5a6c10 +Subproject commit a058a7c6411afa7543953bb93a098d9657c408b4