修复部分bug

This commit is contained in:
锦恢 2024-09-27 21:18:09 +08:00
parent 5d8eb18042
commit 2298e7d252
11 changed files with 100 additions and 48 deletions

View File

@ -1,15 +1,14 @@
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::BufRead; use std::io::BufRead;
use std::{collections::HashMap, io::BufReader}; use std::io::BufReader;
use std::path::PathBuf; use std::path::PathBuf;
use anyhow::Error; use anyhow::Error;
use percent_encoding::percent_decode_str;
use ropey::Rope; use ropey::Rope;
use tower_lsp::lsp_types::Url; use tower_lsp::lsp_types::Url;
use std::env::consts::OS; use sv_parser::{unwrap_node, Locate, RefNode, SyntaxTree};
use sv_parser::{parse_sv, unwrap_node, Locate, RefNode, SyntaxTree};
use crate::sources::recovery_sv_parse; use crate::sources::recovery_sv_parse;
use crate::utils::to_escape_path;
use super::fast_hdlparam::{FastHdlparam, Macro}; use super::fast_hdlparam::{FastHdlparam, Macro};
@ -40,19 +39,7 @@ pub fn sv_parser(path: &str) -> Option<FastHdlparam> {
pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Result<FastHdlparam, Error> { pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Result<FastHdlparam, Error> {
// 对不同操作系统文件路径的支持 // 对不同操作系统文件路径的支持
let decoded_path = percent_decode_str(path.to_str().unwrap()).decode_utf8_lossy(); let path = to_escape_path(path);
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 mut hdlparam = FastHdlparam { let mut hdlparam = FastHdlparam {
fast_macro: Macro { fast_macro: Macro {

View File

@ -70,7 +70,6 @@ impl <'a>tower_lsp::jsonrpc::Method<&'a Arc<Backend>, (DoFastApiRequestParams, )
let request_param = _params.0; let request_param = _params.0;
let path = request_param.path; let path = request_param.path;
let fut = future::ready(do_fast(path)); let fut = future::ready(do_fast(path));
info!("get future: {:?}", fut);
fut fut
} }
} }
@ -110,8 +109,6 @@ pub fn do_fast(path: String) -> Result<FastHdlparam> {
let includes: Vec<PathBuf> = Vec::new(); let includes: Vec<PathBuf> = Vec::new();
info!("before parse {}", path);
let parse_result = recovery_sv_parse( let parse_result = recovery_sv_parse(
&text, &text,
&uri, &uri,
@ -121,7 +118,6 @@ pub fn do_fast(path: String) -> Result<FastHdlparam> {
if let Some(syntax_tree) = parse_result { if let Some(syntax_tree) = parse_result {
if let Ok(hdlparam) = make_fast_from_syntaxtree(&syntax_tree, &path_buf) { if let Ok(hdlparam) = make_fast_from_syntaxtree(&syntax_tree, &path_buf) {
info!("after parse {}, get hdlparam", path);
return Ok(hdlparam); return Ok(hdlparam);
} }
} }

View File

@ -790,16 +790,6 @@ impl GenericScope {
scopes: Vec::new(), 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 { impl Definition for GenericScope {

View File

@ -6,7 +6,11 @@ use tower_lsp::lsp_types::*;
pub fn get_ident(tree: &SyntaxTree, node: RefNode) -> (String, usize) { pub fn get_ident(tree: &SyntaxTree, node: RefNode) -> (String, usize) {
let loc = unwrap_locate!(node).unwrap(); let loc = unwrap_locate!(node).unwrap();
let ident_str = tree.get_str(loc).unwrap().to_string(); 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) (ident_str, byte_idx)
} }

View File

@ -1,7 +1,10 @@
use std::{path::PathBuf, str::FromStr};
use log::info;
use ropey::RopeSlice; use ropey::RopeSlice;
use tower_lsp::lsp_types::{GotoDefinitionResponse, LocationLink, Position, Range, Url}; 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<GotoDefinitionResponse> { pub fn goto_include_definition(uri: &Url, line: &RopeSlice, pos: Position) -> Option<GotoDefinitionResponse> {
@ -23,7 +26,21 @@ pub fn goto_include_definition(uri: &Url, line: &RopeSlice, pos: Position) -> Op
path_string = &path_string[2 ..]; 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 <goto_include_definition>: {:?}", 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()) { let target_uri = match Url::from_file_path(abs_path.as_path()) {
Ok(uri) => uri, Ok(uri) => uri,
Err(_) => return None Err(_) => return None

View File

@ -2,6 +2,7 @@ use crate::{definition::extract_defs::get_ident, utils::get_definition_token};
use crate::server::LSPServer; use crate::server::LSPServer;
use crate::sources::LSPSupport; use crate::sources::LSPSupport;
#[allow(unused)]
use log::info; use log::info;
use sv_parser::*; use sv_parser::*;
use tower_lsp::lsp_types::*; 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(); let mut idents: Vec<(String, usize)> = Vec::new();
for node in syntax_tree { for node in syntax_tree {
if let RefNode::Identifier(_) = node { if let RefNode::Identifier(_) = node {
let (ident, byte_idx) = get_ident(syntax_tree, node); let (ident, byte_idx) = get_ident(syntax_tree, node);
if ident == token { if ident == token {
idents.push((ident, byte_idx)); idents.push((ident, byte_idx));

View File

@ -1,7 +1,6 @@
use log::info;
use regex::Regex; use regex::Regex;
use ropey::RopeSlice; 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; use super::get_word_range_at_position;

View File

@ -1,9 +1,11 @@
use std::{fmt::format, sync::RwLockReadGuard}; use std::{path::PathBuf, str::FromStr, sync::RwLockReadGuard};
use crate::definition::*; use crate::definition::*;
use crate::server::LSPServer; use crate::server::LSPServer;
use crate::sources::LSPSupport; use crate::sources::LSPSupport;
use crate::utils::*; use crate::utils::*;
use log::info;
use regex::Regex;
use ropey::{Rope, RopeSlice}; use ropey::{Rope, RopeSlice};
use tower_lsp::lsp_types::*; use tower_lsp::lsp_types::*;
@ -60,10 +62,11 @@ fn get_hover(doc: &Rope, line: usize) -> String {
let mut multiline: bool = false; let mut multiline: bool = false;
let mut valid: bool = true; let mut valid: bool = true;
let mut current: String = doc.line(line).to_string(); let mut current: String = doc.line(line).to_string();
let ltrim: String = " ".repeat(current.len() - current.trim_start().len()); let ltrim: String = " ".repeat(current.len() - current.trim_start().len());
let mut line_idx = line; let mut line_idx = line;
// iterate upwards from the definition, and grab the comments // 寻找周围的注释
while valid { while valid {
hover.push(current.clone()); hover.push(current.clone());
line_idx -= 1; line_idx -= 1;
@ -86,18 +89,31 @@ fn get_hover(doc: &Rope, line: usize) -> String {
} }
} }
hover.reverse(); 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<String> = Vec::new(); let mut result: Vec<String> = Vec::new();
for i in hover { for line in hover {
if let Some(stripped) = i.strip_prefix(&ltrim) { if let Some(stripped) = line.strip_prefix(&ltrim) {
result.push(stripped.to_owned()); let line_hover = line_handler(stripped);
result.push(line_hover);
} else { } else {
result.push(i); let line_hover = line_handler(&line);
result.push(line_hover);
} }
} }
result.join("").trim_end().to_owned() result.join("").trim_end().to_owned()
} }
fn match_include(uri: &Url, line: &RopeSlice, pos: Position, language_id: &String) -> Option<Hover> { fn match_include(uri: &Url, line: &RopeSlice, pos: Position, language_id: &String) -> Option<Hover> {
let line_text = line.as_str().unwrap_or(""); let line_text = line.as_str().unwrap_or("");
if line_text.trim().starts_with("`include") { if line_text.trim().starts_with("`include") {
@ -117,7 +133,21 @@ fn match_include(uri: &Url, line: &RopeSlice, pos: Position, language_id: &Strin
path_string = &path_string[2 ..]; 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 <goto_include_definition>: {:?}", 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 content = format!("{:?}", abs_path); let content = format!("{:?}", abs_path);
let language_string = LanguageString { let language_string = LanguageString {
language: language_id.to_string(), language: language_id.to_string(),

View File

@ -15,7 +15,6 @@ use std::fs;
use std::ops::Deref; use std::ops::Deref;
use std::ops::Range as StdRange; use std::ops::Range as StdRange;
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr;
use std::sync::{Arc, Condvar, Mutex, RwLock}; use std::sync::{Arc, Condvar, Mutex, RwLock};
use std::thread; use std::thread;
use sv_parser::*; use sv_parser::*;

View File

@ -129,10 +129,9 @@ mod test_fast {
#[cfg(test)] #[cfg(test)]
mod test_svparse { mod test_svparse {
use std::{collections::HashMap, fs, path::{Path, PathBuf}}; use std::{fs, path::{Path, PathBuf}};
use ropey::Rope; use ropey::Rope;
use sv_parser::parse_sv_str;
use tower_lsp::lsp_types::{Position, Range, Url}; use tower_lsp::lsp_types::{Position, Range, Url};
use crate::sources::recovery_sv_parse; use crate::sources::recovery_sv_parse;

View File

@ -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 regex::Regex;
use ropey::RopeSlice; use ropey::RopeSlice;
use tower_lsp::lsp_types::*; use tower_lsp::lsp_types::*;
@ -90,14 +91,20 @@ pub fn get_language_id_by_uri(uri: &Url) -> String {
} }
/// 根据基础路径和给出的 path 路径,计算出绝对路径 /// 根据基础路径和给出的 path 路径,计算出绝对路径
///
/// 如果 path 是绝对路径直接返回 /// 如果 path 是绝对路径直接返回
/// 会进行存在性检查,不存在的路径直接返回 None /// 会进行存在性检查,不存在的路径直接返回 None
///
/// 例子: /// 例子:
///
/// resolve_path("/home/ubuntu/hello.v", "./control.v") -> Some("/home/ubuntu/control.v") /// 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") /// resolve_path("/home/ubuntu/hello.v", "/opt/control.v") -> Some("/opt/control.v")
///
pub fn resolve_path(base: &str, path_string: &str) -> Option<PathBuf> { pub fn resolve_path(base: &str, path_string: &str) -> Option<PathBuf> {
let path = Path::new(path_string); let path = Path::new(path_string);
let abs_path: PathBuf; let abs_path: PathBuf;
if path.is_absolute() { if path.is_absolute() {
abs_path = PathBuf::from(path); abs_path = PathBuf::from(path);
} else { } else {
@ -110,3 +117,25 @@ pub fn resolve_path(base: &str, path_string: &str) -> Option<PathBuf> {
} }
None None
} }
/// 把 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)
},
}
}