diff --git a/src/definition.rs b/src/definition.rs index 6128720..00de7be 100644 --- a/src/definition.rs +++ b/src/definition.rs @@ -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> = 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> = 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)) diff --git a/src/definition/feature.rs b/src/definition/feature.rs new file mode 100644 index 0000000..807125c --- /dev/null +++ b/src/definition/feature.rs @@ -0,0 +1,3 @@ +pub fn goto_include_definition() { + +} \ No newline at end of file diff --git a/src/sources.rs b/src/sources.rs index a005ea2..0b7fb1e 100644 --- a/src/sources.rs +++ b/src/sources.rs @@ -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 = 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), }; } diff --git a/src/test/mod.rs b/src/test/mod.rs index 2588471..34ad40a 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -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 = 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}};