修复部分bug
This commit is contained in:
parent
5d8eb18042
commit
2298e7d252
@ -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 {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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));
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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(<rim) {
|
if let Some(stripped) = line.strip_prefix(<rim) {
|
||||||
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(),
|
||||||
|
@ -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::*;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user