解决 macro 定义不存在解析失败的问题
This commit is contained in:
parent
ca272a67b8
commit
c8ae0f78a4
@ -22,10 +22,15 @@ impl LSPServer {
|
|||||||
self.srcs.wait_parse_ready(file_id, false);
|
self.srcs.wait_parse_ready(file_id, false);
|
||||||
let file = self.srcs.get_file(file_id)?;
|
let file = self.srcs.get_file(file_id)?;
|
||||||
let file = file.read().ok()?;
|
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);
|
info!("definition token: {:?}", token);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let scope_tree = self.srcs.scope_tree.read().ok()?;
|
let scope_tree = self.srcs.scope_tree.read().ok()?;
|
||||||
|
|
||||||
let def = scope_tree
|
let def = scope_tree
|
||||||
@ -47,7 +52,9 @@ impl LSPServer {
|
|||||||
self.srcs.wait_parse_ready(file_id, false);
|
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::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 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()?;
|
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);
|
self.srcs.wait_parse_ready(file_id, false);
|
||||||
let file = self.srcs.get_file(file_id)?;
|
let file = self.srcs.get_file(file_id)?;
|
||||||
let file = file.read().ok()?;
|
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()?;
|
let scope_tree = self.srcs.scope_tree.read().ok()?;
|
||||||
// use the byte_idx of the definition if possible, otherwise use the cursor
|
// use the byte_idx of the definition if possible, otherwise use the cursor
|
||||||
let byte_idx =
|
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
|
/// 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 token = String::new();
|
||||||
let mut line_iter = line.chars();
|
let mut line_iter = line.chars();
|
||||||
for _ in 0..(line.utf16_cu_to_char(pos.character as usize)) {
|
for _ in 0..(line.utf16_cu_to_char(pos.character as usize)) {
|
||||||
@ -387,7 +396,8 @@ mod tests {
|
|||||||
fn test_definition_token() {
|
fn test_definition_token() {
|
||||||
test_init();
|
test_init();
|
||||||
let line = Rope::from_str("assign ab_c[2:0] = 3'b000;");
|
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());
|
assert_eq!(token, "ab_c".to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,7 +412,8 @@ mod tests {
|
|||||||
let syntax_tree = parse(&doc, &url, &None, &Vec::new()).unwrap();
|
let syntax_tree = parse(&doc, &url, &None, &Vec::new()).unwrap();
|
||||||
let scope_tree = get_scopes(&syntax_tree, &url).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 {
|
for def in scope_tree.defs {
|
||||||
if token == def.ident() {
|
if token == def.ident() {
|
||||||
assert_eq!(doc.byte_to_pos(def.byte_idx()), Position::new(3, 9))
|
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();
|
let range = &file.last_change_range.clone();
|
||||||
drop(file);
|
drop(file);
|
||||||
|
|
||||||
|
info!("do parse in {:?}", uri.to_string());
|
||||||
|
|
||||||
let syntax_tree = parse(&text, uri, range, &inc_dirs.read().unwrap());
|
let syntax_tree = parse(&text, uri, range, &inc_dirs.read().unwrap());
|
||||||
let mut scope_tree = match &syntax_tree {
|
let mut scope_tree = match &syntax_tree {
|
||||||
Some(tree) => get_scopes(tree, uri),
|
Some(tree) => get_scopes(tree, uri),
|
||||||
@ -295,6 +297,8 @@ impl Sources {
|
|||||||
// eprintln!("{:#?}", *global_scope);
|
// eprintln!("{:#?}", *global_scope);
|
||||||
drop(global_scope);
|
drop(global_scope);
|
||||||
|
|
||||||
|
|
||||||
|
// 通过条件锁进行控制
|
||||||
let mut valid = lock.lock().unwrap();
|
let mut valid = lock.lock().unwrap();
|
||||||
*valid = true;
|
*valid = true;
|
||||||
cvar.notify_all();
|
cvar.notify_all();
|
||||||
@ -409,6 +413,7 @@ pub fn parse(
|
|||||||
let mut parse_iterations = 1;
|
let mut parse_iterations = 1;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let mut includes: Vec<PathBuf> = inc_paths.to_vec();
|
let mut includes: Vec<PathBuf> = inc_paths.to_vec();
|
||||||
|
let mut defines = HashMap::new();
|
||||||
let mut reverted_change = false;
|
let mut reverted_change = false;
|
||||||
let mut text = doc.clone();
|
let mut text = doc.clone();
|
||||||
|
|
||||||
@ -417,7 +422,7 @@ pub fn parse(
|
|||||||
match parse_sv_str(
|
match parse_sv_str(
|
||||||
&text.to_string(),
|
&text.to_string(),
|
||||||
uri.to_file_path().unwrap(),
|
uri.to_file_path().unwrap(),
|
||||||
&HashMap::new(),
|
&defines,
|
||||||
&includes,
|
&includes,
|
||||||
true,
|
true,
|
||||||
true
|
true
|
||||||
@ -427,7 +432,7 @@ pub fn parse(
|
|||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
match err {
|
match err {
|
||||||
// syntax error
|
// 语法错误
|
||||||
sv_parser::Error::Parse(trace) => match trace {
|
sv_parser::Error::Parse(trace) => match trace {
|
||||||
Some((_, bpos)) => {
|
Some((_, bpos)) => {
|
||||||
let mut line_start = text.byte_to_line(bpos);
|
let mut line_start = text.byte_to_line(bpos);
|
||||||
@ -450,8 +455,8 @@ pub fn parse(
|
|||||||
}
|
}
|
||||||
None => return None,
|
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 } => {
|
sv_parser::Error::Include { source: x } => {
|
||||||
if let sv_parser::Error::File { source: _, path: z } = *x {
|
if let sv_parser::Error::File { source: _, path: z } = *x {
|
||||||
// Include paths have to be relative to the working directory
|
// Include paths have to be relative to the working directory
|
||||||
@ -472,6 +477,17 @@ pub fn parse(
|
|||||||
parse_iterations += 1;
|
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),
|
_ => 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)]
|
#[cfg(test)]
|
||||||
mod test_scope_tree {
|
mod test_scope_tree {
|
||||||
use std::{collections::HashMap, fs, path::{Path, PathBuf}};
|
use std::{collections::HashMap, fs, path::{Path, PathBuf}};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user