解决 include 解析的问题

This commit is contained in:
锦恢 2025-01-05 21:44:00 +08:00
parent 229fe4dc97
commit a6717a702e
5 changed files with 52 additions and 76 deletions

View File

@ -1,4 +1,5 @@
use crate::core::hdlparam::{self, FastHdlparam}; use crate::core::hdlparam::{self, FastHdlparam};
use log::info;
use ropey::Rope; use ropey::Rope;
use sv_parser::*; use sv_parser::*;
use tower_lsp::lsp_types::*; use tower_lsp::lsp_types::*;
@ -24,6 +25,10 @@ pub fn match_definitions(
let mut definitions: Vec<Box<dyn Definition>> = Vec::new(); let mut definitions: Vec<Box<dyn Definition>> = Vec::new();
let mut scopes: Vec<Box<dyn Scope>> = Vec::new(); let mut scopes: Vec<Box<dyn Scope>> = Vec::new();
match node { match node {
RefNode::IncludeStatement(n) => {
info!("enter IncludeStatement");
info!("{:?}", n);
}
RefNode::ModuleDeclaration(n) => { RefNode::ModuleDeclaration(n) => {
let module = module_dec(syntax_tree, n, event_iter, url); let module = module_dec(syntax_tree, n, event_iter, url);
if module.is_some() { if module.is_some() {

View File

@ -1,6 +1,7 @@
use super::common::*; use super::common::*;
use super::match_definitions; use super::match_definitions;
#[allow(unused)]
use log::info; use log::info;
use sv_parser::*; use sv_parser::*;
use tower_lsp::lsp_types::*; use tower_lsp::lsp_types::*;
@ -2345,7 +2346,7 @@ pub fn text_macro_def(
let ident = get_ident(tree, RefNode::TextMacroIdentifier(&node.nodes.2.nodes.0)); let ident = get_ident(tree, RefNode::TextMacroIdentifier(&node.nodes.2.nodes.0));
text_macro.ident = ident.0; text_macro.ident = ident.0;
text_macro.byte_idx = ident.1; text_macro.byte_idx = ident.1;
let mut type_str = &mut text_macro.type_str; let type_str = &mut text_macro.type_str;
advance_until_enter!( advance_until_enter!(
type_str, type_str,

View File

@ -13,7 +13,7 @@ use crate::core::hdlparam::{AssignType, Position, Range};
use crate::sources::{recovery_sv_parse_with_retry, LSPSupport}; use crate::sources::{recovery_sv_parse_with_retry, LSPSupport};
use crate::utils::to_escape_path; use crate::utils::to_escape_path;
use super::hdlparam::{self, FastHdlparam, InstParameter, InstPort, Macro}; use super::hdlparam::{self, FastHdlparam, Include, InstParameter, InstPort, Macro};
macro_rules! advance_until_leave { macro_rules! advance_until_leave {
($tokens:ident, $tree:ident, $event_iter:ident, $node:path) => {{ ($tokens:ident, $tree:ident, $event_iter:ident, $node:path) => {{
@ -74,7 +74,7 @@ pub fn sv_parser(path: &str) -> Option<FastHdlparam> {
let result = recovery_sv_parse_with_retry(&doc, &uri, &None, &includes); let result = recovery_sv_parse_with_retry(&doc, &uri, &None, &includes);
if let Some((syntax_tree, _)) = result { if let Some((syntax_tree, _)) = result {
if let Ok(fast) = make_fast_from_syntaxtree(&syntax_tree, &path) { if let Ok(fast) = make_fast_from_syntaxtree(&syntax_tree) {
return Some(fast); return Some(fast);
} }
} }
@ -83,17 +83,14 @@ pub fn sv_parser(path: &str) -> Option<FastHdlparam> {
} }
pub fn make_fast_from_syntaxtree( pub fn make_fast_from_syntaxtree(
syntax_tree: &SyntaxTree, syntax_tree: &SyntaxTree
path: &PathBuf
) -> Result<FastHdlparam, std::io::Error> { ) -> Result<FastHdlparam, std::io::Error> {
// 对不同操作系统文件路径的支持 // 对不同操作系统文件路径的支持
let path = to_escape_path(path);
let mut fast: FastHdlparam = FastHdlparam { let mut fast: FastHdlparam = FastHdlparam {
fast_macro: Macro { fast_macro: Macro {
defines: Vec::new(), defines: Vec::new(),
errors: Vec::new(), errors: Vec::new(),
includes: get_includes(&path), includes: Vec::<Include>::new(),
invalid: Vec::new() invalid: Vec::new()
}, },
content: Vec::new(), content: Vec::new(),
@ -106,9 +103,34 @@ pub fn make_fast_from_syntaxtree(
let doc = Rope::from_str(syntax_tree.text.text()); let doc = Rope::from_str(syntax_tree.text.text());
// 上一个 module 可以在 fast 的 content 的最后一个中找到 // 上一个 module 可以在 fast 的 content 的最后一个中找到
for node in syntax_tree { for node in syntax_tree {
match node { match node {
RefNode::IncludeCompilerDirective(x) => {
match x {
sv_parser::IncludeCompilerDirective::DoubleQuote(x) => {
let (_, ref keyword, ref literal) = x.nodes;
let (keyword_locate, _) = keyword.nodes;
let (literal_locate, _) = literal.nodes;
let include_path_string = syntax_tree.get_str_trim(literal).unwrap().trim_matches('"');
let include_range = Range {
start: get_position(&doc, keyword_locate, 0),
end: get_position(&doc, literal_locate, literal_locate.len)
};
fast.fast_macro.includes.push(Include {
path: include_path_string.to_string(),
range: include_range
});
}
sv_parser::IncludeCompilerDirective::AngleBracket(_) => {
},
sv_parser::IncludeCompilerDirective::TextMacroUsage(_) => {
},
}
}
RefNode::TextMacroDefinition(x) => { RefNode::TextMacroDefinition(x) => {
if let Some(start) = unwrap_node!(x, TextMacroDefinition) { if let Some(start) = unwrap_node!(x, TextMacroDefinition) {
let start = get_identifier(start).unwrap(); let start = get_identifier(start).unwrap();
@ -674,54 +696,6 @@ pub fn get_position(doc: &Rope, locate: Locate, offset: usize) -> Position {
hdlparam::Position::from_lsp_position(&pos) hdlparam::Position::from_lsp_position(&pos)
} }
fn get_includes(path: &PathBuf) -> Vec<crate::core::hdlparam::Include> {
let mut includes = Vec::new();
let file = File::open(path).unwrap();
let reader = BufReader::new(file);
for (line_number, line_content) in reader.lines().enumerate() {
let line_content = match line_content {
Ok(content) => content,
Err(e) => {
println!("line {} has error {}", line_number, e);
"".to_string()
}
};
if line_content.trim().starts_with("`include") {
let parts: Vec<&str> = line_content.split_whitespace().collect();
if parts.len() >= 2 {
let mut path = parts[1].trim();
if path.starts_with("\"") {
path = path.strip_prefix("\"").unwrap();
}
if path.ends_with("\"") {
path = path.strip_suffix("\"").unwrap();
}
let last_character = line_content.find(path).unwrap() + path.len();
includes.push(crate::core::hdlparam::Include {
path: path.to_string(),
range: crate::core::hdlparam::Range {
start: crate::core::hdlparam::Position {
line: (line_number + 1) as u32, character: 1
},
end: crate::core::hdlparam::Position {
line: (line_number + 1) as u32, character: last_character as u32
}
}
});
}
}
}
includes
}
#[allow(unused)] #[allow(unused)]
fn update_module_range(path: &PathBuf, fast: &mut FastHdlparam) { fn update_module_range(path: &PathBuf, fast: &mut FastHdlparam) {
let file = File::open(path).unwrap(); let file = File::open(path).unwrap();

View File

@ -194,7 +194,7 @@ fn do_sv_fast(
let sources = &backend.server.db; let sources = &backend.server.db;
if let Some((syntax_tree, parse_result)) = parse_result { if let Some((syntax_tree, parse_result)) = parse_result {
if let Ok(mut fast) = make_fast_from_syntaxtree(&syntax_tree, &path_buf) { if let Ok(mut fast) = make_fast_from_syntaxtree(&syntax_tree) {
fast.file_type = file_type.to_string(); fast.file_type = file_type.to_string();
let hdl_param = sources.hdl_param.clone(); let hdl_param = sources.hdl_param.clone();
hdl_param.update_hdl_file( hdl_param.update_hdl_file(

View File

@ -27,6 +27,7 @@ use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use std::sync::RwLockWriteGuard;
use std::sync::{Condvar, Mutex, RwLock}; use std::sync::{Condvar, Mutex, RwLock};
use std::thread; use std::thread;
use sv_parser::*; use sv_parser::*;
@ -373,17 +374,16 @@ impl DigitalDataBase {
{ {
let _unused = fast_lock.read().unwrap(); let _unused = fast_lock.read().unwrap();
// 从内存中直接获取增量更新系统维护的代码文本 // 从内存中直接获取增量更新系统维护的代码文本
let file = parse_loop_used_source_handle.read().unwrap(); let file = parse_loop_used_source_handle.write().unwrap();
let text = file.text.clone(); let text = file.text.clone();
let uri = &file.uri.clone(); let uri = &file.uri.clone();
let range = &file.last_change_range.clone(); let range = &file.last_change_range.clone();
drop(file);
match language_id.as_str() { match language_id.as_str() {
"vhdl" => { "vhdl" => {
vhdl_parser_pipeline( vhdl_parser_pipeline(
&configuration, &configuration,
&parse_loop_used_source_handle, file,
&scope_handle, &scope_handle,
&project_handle, &project_handle,
&hdl_param_handle, &hdl_param_handle,
@ -394,7 +394,7 @@ impl DigitalDataBase {
"verilog" | "systemverilog" => { "verilog" | "systemverilog" => {
sv_parser_pipeline( sv_parser_pipeline(
&configuration, &configuration,
&parse_loop_used_source_handle, file,
&scope_handle, &scope_handle,
&hdl_param_handle, &hdl_param_handle,
&text, &text,
@ -681,7 +681,7 @@ pub fn recovery_sv_parse(
pub fn sv_parser_pipeline( pub fn sv_parser_pipeline(
#[allow(unused)] #[allow(unused)]
conf: &Arc<RwLock<LspConfiguration>>, conf: &Arc<RwLock<LspConfiguration>>,
source_handle: &Arc<RwLock<Source>>, mut file_handle: RwLockWriteGuard<'_, Source>,
scope_handle: &Arc<RwLock<Option<GenericScope>>>, scope_handle: &Arc<RwLock<Option<GenericScope>>>,
hdl_param_handle: &Arc<HdlParam>, hdl_param_handle: &Arc<HdlParam>,
doc: &Rope, doc: &Rope,
@ -709,12 +709,10 @@ pub fn sv_parser_pipeline(
None => None, None => None,
}; };
let mut file = source_handle.write().unwrap();
// 加入语法树 & 更新 fast // 加入语法树 & 更新 fast
if let Some((syntax_tree, parse_result)) = ast { if let Some((syntax_tree, parse_result)) = ast {
if let Ok(fast) = make_fast_from_syntaxtree(&syntax_tree, &escape_path) { if let Ok(fast) = make_fast_from_syntaxtree(&syntax_tree) {
info!("update parse_result: {:?}", parse_result); info!("update: {:?}", fast.fast_macro);
hdl_param_handle.update_hdl_file( hdl_param_handle.update_hdl_file(
escape_path_string.to_string(), escape_path_string.to_string(),
fast, fast,
@ -723,12 +721,12 @@ pub fn sv_parser_pipeline(
); );
} }
file.finish_at_least_once = true; file_handle.finish_at_least_once = true;
} else { } else {
file.finish_at_least_once = false; file_handle.finish_at_least_once = false;
} }
// file.syntax_tree = syntax_tree;
drop(file); drop(file_handle);
info!("finish parse {:?}", uri.to_string()); info!("finish parse {:?}", uri.to_string());
@ -750,13 +748,12 @@ pub fn sv_parser_pipeline(
// 使用 scope_tree 来更新全局的 scope // 使用 scope_tree 来更新全局的 scope
None => *global_scope = scope_tree, None => *global_scope = scope_tree,
} }
// eprintln!("{:#?}", *global_scope);
drop(global_scope); drop(global_scope);
} }
pub fn vhdl_parser_pipeline( pub fn vhdl_parser_pipeline(
conf: &Arc<RwLock<LspConfiguration>>, conf: &Arc<RwLock<LspConfiguration>>,
source_handle: &Arc<RwLock<Source>>, mut file_handle: RwLockWriteGuard<'_, Source>,
scope_handle: &Arc<RwLock<Option<GenericScope>>>, scope_handle: &Arc<RwLock<Option<GenericScope>>>,
project_handle: &Arc<RwLock<Option<VhdlProject>>>, project_handle: &Arc<RwLock<Option<VhdlProject>>>,
hdl_param_handle: &Arc<HdlParam>, hdl_param_handle: &Arc<HdlParam>,
@ -847,7 +844,6 @@ pub fn vhdl_parser_pipeline(
let mut global_project = project_handle.write().unwrap(); let mut global_project = project_handle.write().unwrap();
match &mut *global_project { match &mut *global_project {
Some(vhdl_project) => { Some(vhdl_project) => {
let mut source = source_handle.write().unwrap();
let text = doc.to_string(); let text = doc.to_string();
let mut scope_tree = if let Some(design_file) = vhdl_parse_str(&escape_path, &text) { let mut scope_tree = if let Some(design_file) = vhdl_parse_str(&escape_path, &text) {
let arch_and_entity = vhdl_project.project.get_analyzed_units(&escape_path); let arch_and_entity = vhdl_project.project.get_analyzed_units(&escape_path);
@ -886,10 +882,10 @@ pub fn vhdl_parser_pipeline(
None None
} }
} else { } else {
source.finish_at_least_once = false; file_handle.finish_at_least_once = false;
None None
}; };
drop(source); drop(file_handle);
info!("finish parse {:?}", uri.to_string()); info!("finish parse {:?}", uri.to_string());