From 2298e7d252f1e6f16db7aa959a0cab900a40cca2 Mon Sep 17 00:00:00 2001 From: Kirigaya <1193466151@qq.com> Date: Fri, 27 Sep 2024 21:18:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/sv_parser.rs | 21 ++++------------ src/custom_request.rs | 4 ---- src/definition/def_types.rs | 10 -------- src/definition/extract_defs.rs | 6 ++++- src/definition/feature.rs | 21 ++++++++++++++-- src/definition/mod.rs | 2 ++ src/hover/feature.rs | 3 +-- src/hover/mod.rs | 44 ++++++++++++++++++++++++++++------ src/sources.rs | 1 - src/test/mod.rs | 3 +-- src/utils/mod.rs | 33 +++++++++++++++++++++++-- 11 files changed, 100 insertions(+), 48 deletions(-) diff --git a/src/core/sv_parser.rs b/src/core/sv_parser.rs index 7753da3..cf8e57f 100644 --- a/src/core/sv_parser.rs +++ b/src/core/sv_parser.rs @@ -1,15 +1,14 @@ use std::fs::{self, File}; use std::io::BufRead; -use std::{collections::HashMap, io::BufReader}; +use std::io::BufReader; use std::path::PathBuf; use anyhow::Error; -use percent_encoding::percent_decode_str; use ropey::Rope; use tower_lsp::lsp_types::Url; -use std::env::consts::OS; -use sv_parser::{parse_sv, unwrap_node, Locate, RefNode, SyntaxTree}; +use sv_parser::{unwrap_node, Locate, RefNode, SyntaxTree}; use crate::sources::recovery_sv_parse; +use crate::utils::to_escape_path; use super::fast_hdlparam::{FastHdlparam, Macro}; @@ -40,19 +39,7 @@ pub fn sv_parser(path: &str) -> Option { pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Result { // 对不同操作系统文件路径的支持 - let decoded_path = percent_decode_str(path.to_str().unwrap()).decode_utf8_lossy(); - let decoded_path_str = decoded_path.as_ref(); - let path = match OS { - "windows" => { - // 去掉开头的斜杠 - let trimmed_path_str = decoded_path_str.trim_start_matches('/'); - PathBuf::from(trimmed_path_str) - }, - _ => { - // 其他操作系统(如 Linux)保持原样 - PathBuf::from(decoded_path_str) - }, - }; + let path = to_escape_path(path); let mut hdlparam = FastHdlparam { fast_macro: Macro { diff --git a/src/custom_request.rs b/src/custom_request.rs index bc0d06f..930c4fa 100644 --- a/src/custom_request.rs +++ b/src/custom_request.rs @@ -70,7 +70,6 @@ impl <'a>tower_lsp::jsonrpc::Method<&'a Arc, (DoFastApiRequestParams, ) let request_param = _params.0; let path = request_param.path; let fut = future::ready(do_fast(path)); - info!("get future: {:?}", fut); fut } } @@ -109,8 +108,6 @@ pub fn do_fast(path: String) -> Result { // fast 解析不需要 include let includes: Vec = Vec::new(); - - info!("before parse {}", path); let parse_result = recovery_sv_parse( &text, @@ -121,7 +118,6 @@ pub fn do_fast(path: String) -> Result { if let Some(syntax_tree) = parse_result { if let Ok(hdlparam) = make_fast_from_syntaxtree(&syntax_tree, &path_buf) { - info!("after parse {}, get hdlparam", path); return Ok(hdlparam); } } diff --git a/src/definition/def_types.rs b/src/definition/def_types.rs index c8f1352..d70a176 100644 --- a/src/definition/def_types.rs +++ b/src/definition/def_types.rs @@ -790,16 +790,6 @@ impl GenericScope { scopes: Vec::new(), } } - - #[cfg(test)] - pub fn contains_scope(&self, scope_ident: &str) -> bool { - for scope in &self.scopes { - if scope.starts_with(scope_ident) { - return true; - } - } - false - } } impl Definition for GenericScope { diff --git a/src/definition/extract_defs.rs b/src/definition/extract_defs.rs index bc68377..9c08c37 100644 --- a/src/definition/extract_defs.rs +++ b/src/definition/extract_defs.rs @@ -6,7 +6,11 @@ use tower_lsp::lsp_types::*; pub fn get_ident(tree: &SyntaxTree, node: RefNode) -> (String, usize) { let loc = unwrap_locate!(node).unwrap(); let ident_str = tree.get_str(loc).unwrap().to_string(); - let byte_idx = tree.get_origin(loc).unwrap().1; + let byte_idx = match tree.get_origin(loc) { + Some(origin) => origin.1, + None => 0 + }; + (ident_str, byte_idx) } diff --git a/src/definition/feature.rs b/src/definition/feature.rs index ecb46ad..3679cdb 100644 --- a/src/definition/feature.rs +++ b/src/definition/feature.rs @@ -1,7 +1,10 @@ +use std::{path::PathBuf, str::FromStr}; + +use log::info; use ropey::RopeSlice; use tower_lsp::lsp_types::{GotoDefinitionResponse, LocationLink, Position, Range, Url}; -use crate::utils::resolve_path; +use crate::utils::{resolve_path, to_escape_path}; /// 跳转到定义 pub fn goto_include_definition(uri: &Url, line: &RopeSlice, pos: Position) -> Option { @@ -23,7 +26,21 @@ pub fn goto_include_definition(uri: &Url, line: &RopeSlice, pos: Position) -> Op path_string = &path_string[2 ..]; } - if let Some(abs_path) = resolve_path(uri.path(), path_string) { + // 路径转换 + let path = match PathBuf::from_str(uri.path()) { + Ok(path) => path, + Err(error) => { + info!("error happen in : {:?}", error); + return None; + } + }; + let escape_path = to_escape_path(&path); + let escape_path = escape_path.to_str().unwrap_or(""); + if escape_path.len() == 0 { + return None; + } + + if let Some(abs_path) = resolve_path(escape_path, path_string) { let target_uri = match Url::from_file_path(abs_path.as_path()) { Ok(uri) => uri, Err(_) => return None diff --git a/src/definition/mod.rs b/src/definition/mod.rs index 5c432c2..5b60d30 100644 --- a/src/definition/mod.rs +++ b/src/definition/mod.rs @@ -2,6 +2,7 @@ use crate::{definition::extract_defs::get_ident, 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::*; @@ -97,6 +98,7 @@ fn all_identifiers(syntax_tree: &SyntaxTree, token: &str) -> Vec<(String, usize) let mut idents: Vec<(String, usize)> = Vec::new(); for node in syntax_tree { if let RefNode::Identifier(_) = node { + let (ident, byte_idx) = get_ident(syntax_tree, node); if ident == token { idents.push((ident, byte_idx)); diff --git a/src/hover/feature.rs b/src/hover/feature.rs index beb3900..4b88c50 100644 --- a/src/hover/feature.rs +++ b/src/hover/feature.rs @@ -1,7 +1,6 @@ -use log::info; use regex::Regex; use ropey::RopeSlice; -use tower_lsp::lsp_types::{Hover, HoverContents, LanguageString, MarkedString, MarkupContent, Position}; +use tower_lsp::lsp_types::{Hover, HoverContents, LanguageString, MarkedString, Position}; use super::get_word_range_at_position; diff --git a/src/hover/mod.rs b/src/hover/mod.rs index 8ab9cb3..d43341a 100644 --- a/src/hover/mod.rs +++ b/src/hover/mod.rs @@ -1,9 +1,11 @@ -use std::{fmt::format, sync::RwLockReadGuard}; +use std::{path::PathBuf, str::FromStr, sync::RwLockReadGuard}; use crate::definition::*; use crate::server::LSPServer; use crate::sources::LSPSupport; use crate::utils::*; +use log::info; +use regex::Regex; use ropey::{Rope, RopeSlice}; use tower_lsp::lsp_types::*; @@ -60,10 +62,11 @@ fn get_hover(doc: &Rope, line: usize) -> String { let mut multiline: bool = false; let mut valid: bool = true; let mut current: String = doc.line(line).to_string(); + let ltrim: String = " ".repeat(current.len() - current.trim_start().len()); let mut line_idx = line; - // iterate upwards from the definition, and grab the comments + // 寻找周围的注释 while valid { hover.push(current.clone()); line_idx -= 1; @@ -86,18 +89,31 @@ fn get_hover(doc: &Rope, line: usize) -> String { } } hover.reverse(); + info!("hover array: {:?}", hover); + + let multi_space_regex = Regex::new(r"\s+").unwrap(); + + let line_handler = |line: &str| -> String { + let line = multi_space_regex.replace_all(line.trim(), " "); + let line = line.into_owned(); + return format!("{}\n", line); + }; + let mut result: Vec = Vec::new(); - for i in hover { - if let Some(stripped) = i.strip_prefix(<rim) { - result.push(stripped.to_owned()); + for line in hover { + if let Some(stripped) = line.strip_prefix(<rim) { + let line_hover = line_handler(stripped); + result.push(line_hover); } else { - result.push(i); + let line_hover = line_handler(&line); + result.push(line_hover); } } result.join("").trim_end().to_owned() } + fn match_include(uri: &Url, line: &RopeSlice, pos: Position, language_id: &String) -> Option { let line_text = line.as_str().unwrap_or(""); if line_text.trim().starts_with("`include") { @@ -116,8 +132,22 @@ fn match_include(uri: &Url, line: &RopeSlice, pos: Position, language_id: &Strin if path_string.starts_with("./") || path_string.starts_with(".\\") { path_string = &path_string[2 ..]; } + + // 路径转换 + let path = match PathBuf::from_str(uri.path()) { + Ok(path) => path, + Err(error) => { + info!("error happen in : {:?}", error); + return None; + } + }; + let escape_path = to_escape_path(&path); + let escape_path = escape_path.to_str().unwrap_or(""); + if escape_path.len() == 0 { + return None; + } - if let Some(abs_path) = resolve_path(uri.path(), path_string) { + if let Some(abs_path) = resolve_path(escape_path, path_string) { let content = format!("{:?}", abs_path); let language_string = LanguageString { language: language_id.to_string(), diff --git a/src/sources.rs b/src/sources.rs index 1be053d..fc5365a 100644 --- a/src/sources.rs +++ b/src/sources.rs @@ -15,7 +15,6 @@ use std::fs; use std::ops::Deref; use std::ops::Range as StdRange; use std::path::PathBuf; -use std::str::FromStr; use std::sync::{Arc, Condvar, Mutex, RwLock}; use std::thread; use sv_parser::*; diff --git a/src/test/mod.rs b/src/test/mod.rs index 3385c08..02a3f0f 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -129,10 +129,9 @@ mod test_fast { #[cfg(test)] mod test_svparse { - use std::{collections::HashMap, fs, path::{Path, PathBuf}}; + use std::{fs, path::{Path, PathBuf}}; use ropey::Rope; - use sv_parser::parse_sv_str; use tower_lsp::lsp_types::{Position, Range, Url}; use crate::sources::recovery_sv_parse; diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 6e58a2c..08c4caa 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,5 +1,6 @@ -use std::path::{Path, PathBuf}; +use std::{env::consts::OS, path::{Path, PathBuf}}; +use percent_encoding::percent_decode_str; use regex::Regex; use ropey::RopeSlice; use tower_lsp::lsp_types::*; @@ -90,14 +91,20 @@ pub fn get_language_id_by_uri(uri: &Url) -> String { } /// 根据基础路径和给出的 path 路径,计算出绝对路径 +/// /// 如果 path 是绝对路径直接返回 /// 会进行存在性检查,不存在的路径直接返回 None +/// /// 例子: +/// /// resolve_path("/home/ubuntu/hello.v", "./control.v") -> Some("/home/ubuntu/control.v") +/// /// resolve_path("/home/ubuntu/hello.v", "/opt/control.v") -> Some("/opt/control.v") +/// pub fn resolve_path(base: &str, path_string: &str) -> Option { let path = Path::new(path_string); let abs_path: PathBuf; + if path.is_absolute() { abs_path = PathBuf::from(path); } else { @@ -109,4 +116,26 @@ pub fn resolve_path(base: &str, path_string: &str) -> Option { return Some(path); } None -} \ No newline at end of file +} + +/// 把 uri 路径转换成合法的操作系统文件路径 +/// +/// windows 中 +/// +/// /c%3A/Users/MyCpu.v 转换成 c:/Users/MyCpu.v +pub fn to_escape_path(path: &PathBuf) -> PathBuf { + let decoded_path = percent_decode_str(path.to_str().unwrap()).decode_utf8_lossy(); + let decoded_path_str = decoded_path.as_ref(); + match OS { + "windows" => { + // 去掉开头的斜杠 + let trimmed_path_str = decoded_path_str.trim_start_matches('/'); + PathBuf::from(trimmed_path_str) + }, + _ => { + // 其他操作系统(如 Linux)保持原样 + PathBuf::from(decoded_path_str) + }, + } +} +