解决 macro 定义不存在解析失败的问题
This commit is contained in:
parent
ca272a67b8
commit
c8ae0f78a4
@ -22,10 +22,15 @@ impl LSPServer {
|
||||
self.srcs.wait_parse_ready(file_id, false);
|
||||
let file = self.srcs.get_file(file_id)?;
|
||||
let file = file.read().ok()?;
|
||||
let token: String = get_definition_token(file.text.line(pos.line as usize), pos);
|
||||
|
||||
let line_text = file.text.line(pos.line as usize);
|
||||
let token: String = get_definition_token(&line_text, pos);
|
||||
|
||||
info!("definition token: {:?}", token);
|
||||
|
||||
|
||||
|
||||
|
||||
let scope_tree = self.srcs.scope_tree.read().ok()?;
|
||||
|
||||
let def = scope_tree
|
||||
@ -47,7 +52,9 @@ impl LSPServer {
|
||||
self.srcs.wait_parse_ready(file_id, false);
|
||||
let file: std::sync::Arc<std::sync::RwLock<crate::sources::Source>> = self.srcs.get_file(file_id)?;
|
||||
let file: std::sync::RwLockReadGuard<'_, crate::sources::Source> = file.read().ok()?;
|
||||
let token: String = get_definition_token(file.text.line(pos.line as usize), pos);
|
||||
|
||||
let line_text = file.text.line(pos.line as usize);
|
||||
let token: String = get_definition_token(&line_text, pos);
|
||||
|
||||
let scope_tree: std::sync::RwLockReadGuard<'_, Option<GenericScope>> = self.srcs.scope_tree.read().ok()?;
|
||||
|
||||
@ -89,7 +96,9 @@ impl LSPServer {
|
||||
self.srcs.wait_parse_ready(file_id, false);
|
||||
let file = self.srcs.get_file(file_id)?;
|
||||
let file = file.read().ok()?;
|
||||
let token = get_definition_token(file.text.line(pos.line as usize), pos);
|
||||
|
||||
let line_text = file.text.line(pos.line as usize);
|
||||
let token = get_definition_token(&line_text, pos);
|
||||
let scope_tree = self.srcs.scope_tree.read().ok()?;
|
||||
// use the byte_idx of the definition if possible, otherwise use the cursor
|
||||
let byte_idx =
|
||||
@ -125,7 +134,7 @@ fn all_identifiers(syntax_tree: &SyntaxTree, token: &str) -> Vec<(String, usize)
|
||||
}
|
||||
|
||||
/// retrieve the token the user invoked goto definition or hover on
|
||||
fn get_definition_token(line: RopeSlice, pos: Position) -> String {
|
||||
fn get_definition_token(line: &RopeSlice, pos: Position) -> String {
|
||||
let mut token = String::new();
|
||||
let mut line_iter = line.chars();
|
||||
for _ in 0..(line.utf16_cu_to_char(pos.character as usize)) {
|
||||
@ -387,7 +396,8 @@ mod tests {
|
||||
fn test_definition_token() {
|
||||
test_init();
|
||||
let line = Rope::from_str("assign ab_c[2:0] = 3'b000;");
|
||||
let token = get_definition_token(line.line(0), Position::new(0, 10));
|
||||
let line_text = line.line(0);
|
||||
let token = get_definition_token(&line_text, Position::new(0, 10));
|
||||
assert_eq!(token, "ab_c".to_owned());
|
||||
}
|
||||
|
||||
@ -402,7 +412,8 @@ mod tests {
|
||||
let syntax_tree = parse(&doc, &url, &None, &Vec::new()).unwrap();
|
||||
let scope_tree = get_scopes(&syntax_tree, &url).unwrap();
|
||||
|
||||
let token = get_definition_token(doc.line(3), Position::new(3, 13));
|
||||
let line_text = doc.line(3);
|
||||
let token = get_definition_token(&line_text, Position::new(3, 13));
|
||||
for def in scope_tree.defs {
|
||||
if token == def.ident() {
|
||||
assert_eq!(doc.byte_to_pos(def.byte_idx()), Position::new(3, 9))
|
||||
|
3
src/definition/feature.rs
Normal file
3
src/definition/feature.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub fn goto_include_definition() {
|
||||
|
||||
}
|
@ -239,6 +239,8 @@ impl Sources {
|
||||
let range = &file.last_change_range.clone();
|
||||
drop(file);
|
||||
|
||||
info!("do parse in {:?}", uri.to_string());
|
||||
|
||||
let syntax_tree = parse(&text, uri, range, &inc_dirs.read().unwrap());
|
||||
let mut scope_tree = match &syntax_tree {
|
||||
Some(tree) => get_scopes(tree, uri),
|
||||
@ -295,6 +297,8 @@ impl Sources {
|
||||
// eprintln!("{:#?}", *global_scope);
|
||||
drop(global_scope);
|
||||
|
||||
|
||||
// 通过条件锁进行控制
|
||||
let mut valid = lock.lock().unwrap();
|
||||
*valid = true;
|
||||
cvar.notify_all();
|
||||
@ -409,6 +413,7 @@ pub fn parse(
|
||||
let mut parse_iterations = 1;
|
||||
let mut i = 0;
|
||||
let mut includes: Vec<PathBuf> = inc_paths.to_vec();
|
||||
let mut defines = HashMap::new();
|
||||
let mut reverted_change = false;
|
||||
let mut text = doc.clone();
|
||||
|
||||
@ -417,7 +422,7 @@ pub fn parse(
|
||||
match parse_sv_str(
|
||||
&text.to_string(),
|
||||
uri.to_file_path().unwrap(),
|
||||
&HashMap::new(),
|
||||
&defines,
|
||||
&includes,
|
||||
true,
|
||||
true
|
||||
@ -427,7 +432,7 @@ pub fn parse(
|
||||
}
|
||||
Err(err) => {
|
||||
match err {
|
||||
// syntax error
|
||||
// 语法错误
|
||||
sv_parser::Error::Parse(trace) => match trace {
|
||||
Some((_, bpos)) => {
|
||||
let mut line_start = text.byte_to_line(bpos);
|
||||
@ -450,8 +455,8 @@ pub fn parse(
|
||||
}
|
||||
None => return None,
|
||||
},
|
||||
// include error, take the include path from the error message and
|
||||
// add it as an include dir for the next parser invocation
|
||||
|
||||
// 遇到 include 错误,那就把提示中的 include 加入解析中再次解析
|
||||
sv_parser::Error::Include { source: x } => {
|
||||
if let sv_parser::Error::File { source: _, path: z } = *x {
|
||||
// Include paths have to be relative to the working directory
|
||||
@ -472,6 +477,17 @@ pub fn parse(
|
||||
parse_iterations += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 宏定义不存在的错误
|
||||
sv_parser::Error::DefineNotFound(not_found_macro_name) => {
|
||||
let com_define = Define {
|
||||
identifier: not_found_macro_name.to_string(),
|
||||
arguments: Vec::new(),
|
||||
text: Some(DefineText {text: "undefined".to_string(), origin: None})
|
||||
};
|
||||
defines.insert(not_found_macro_name, Some(com_define));
|
||||
parse_iterations += 1;
|
||||
}
|
||||
_ => error!("parse error, {:?}", err),
|
||||
};
|
||||
}
|
||||
|
@ -99,6 +99,40 @@ mod test_fast {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_svparse {
|
||||
use std::{fs, path::PathBuf};
|
||||
|
||||
use ropey::Rope;
|
||||
use tower_lsp::lsp_types::Url;
|
||||
|
||||
use crate::sources::parse;
|
||||
|
||||
#[test]
|
||||
fn test_mycpu() {
|
||||
let includes: Vec<PathBuf> = Vec::new();
|
||||
let path = "/home/dide/project/Digital-Test/MipsDesign/src/MyCpu.v";
|
||||
|
||||
let text = match fs::read_to_string(path) {
|
||||
Ok(text) => text,
|
||||
Err(_) => return
|
||||
};
|
||||
|
||||
let doc = Rope::from_str(&text);
|
||||
let uri = Url::from_file_path(&path).unwrap();
|
||||
let result = parse(&doc, &uri, &None, &includes);
|
||||
match result {
|
||||
Some(syntax_tree) => {
|
||||
println!("success");
|
||||
},
|
||||
None => {
|
||||
eprintln!("gen None");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_scope_tree {
|
||||
use std::{collections::HashMap, fs, path::{Path, PathBuf}};
|
||||
|
Loading…
x
Reference in New Issue
Block a user