实现 endmodule 的 inlay hints
This commit is contained in:
parent
1142aa324f
commit
9688a330bf
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1459,6 +1459,7 @@ dependencies = [
|
||||
name = "sv-parser-pp"
|
||||
version = "0.13.3"
|
||||
dependencies = [
|
||||
"log",
|
||||
"nom",
|
||||
"nom-greedyerror",
|
||||
"sv-parser-error",
|
||||
|
@ -227,7 +227,9 @@ endmodule
|
||||
// resetall 也常用于开始
|
||||
// 1834-2005中指出,建议的用法是将 `resetall 放在每个源文本文件的开头,后面紧跟着文件中所需的指令。
|
||||
// 通常可用于源文本开头,避免该文件受到其他文件代码的影响。或放置在末尾,避免编译器设置的进一步传递
|
||||
r#"`resetall` 用于重置所有编译器设置为默认值。它通常用于在模块或文件的末尾清除所有编译器设置,以确保后续代码不受之前设置的影响。
|
||||
r#"`resetall` 用于重置所有编译器设置为默认值。通常可用于源文本开头,避免该文件受到其他文件代码的影响。或放置在末尾,避免编译器设置的进一步传递。
|
||||
|
||||
1834-2005中指出,建议的用法是将 `resetall 放在每个源文本文件的开头,后面紧跟着文件中所需的指令。
|
||||
|
||||
```verilog
|
||||
`timescale 1ns/1ps // 设置时间单位和精度
|
||||
@ -273,7 +275,7 @@ endmodule
|
||||
// 也即是,仿真时间单位必须大于等于时间精度
|
||||
// `timescale 1ns/1ns不会报错,但是`timescale 1ps/1ns会报错
|
||||
// [Synth 8-522] parsing error: error in timescale or timeprecision statement. <timeprecision> must be at least as precise as <timeunit>
|
||||
r#"设置时间单位和精度,设置时间单位和精度,格式为 <code> `timescale </code> 仿真时间单位/时间精度,<code>仿真时间单位</code> 必须大于 <code>时间精度</code>,例如
|
||||
r#"设置时间单位和精度,设置时间单位和精度,格式为 <code> `timescale </code> 仿真时间单位/时间精度,<code>仿真时间单位</code> 必须大于等于 <code>时间精度</code>,例如
|
||||
```verilog
|
||||
`timescale 1ns/1ps
|
||||
|
||||
@ -343,7 +345,7 @@ r#"`nounconnected_drive` 和 `unconnected_drive` 是配合使用的编译指令
|
||||
"begin_keywords",
|
||||
"`begin_keywords\n$1\n`end_keywords ",
|
||||
// begin_keywords并不是指定Verilog的编译版本,而是指定使用的Verilog关键字版本
|
||||
r#"`begin_keywords` 和 `end_keywords` 是用于指定 Verilog 语言版本的编译指令。它们允许设计者在同一个文件中使用不同版本的 Verilog 语法,从而实现兼容性或逐步迁移到新版本。
|
||||
r#"`begin_keywords` 和 `end_keywords` 是用于指定 Verilog 关键字版本的编译指令。它们允许设计者在同一个文件中使用不同版本的 Verilog 关键字语法,从而实现兼容性或逐步迁移到新版本。
|
||||
|
||||
`begin_keywords` 支持以下 Verilog 版本:
|
||||
|
||||
|
@ -76,8 +76,8 @@ pub fn sv_parser(path: &str) -> Option<FastHdlparam> {
|
||||
// println!("result: {result:?}");
|
||||
|
||||
if let Some(syntax_tree) = result {
|
||||
if let Ok(hdlparam) = make_fast_from_syntaxtree(&syntax_tree, &path) {
|
||||
return Some(hdlparam);
|
||||
if let Ok(fast) = make_fast_from_syntaxtree(&syntax_tree, &path) {
|
||||
return Some(fast);
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ pub fn make_fast_from_syntaxtree(
|
||||
// 对不同操作系统文件路径的支持
|
||||
let path = to_escape_path(path);
|
||||
|
||||
let mut hdlparam = FastHdlparam {
|
||||
let mut fast: FastHdlparam = FastHdlparam {
|
||||
fast_macro: Macro {
|
||||
defines: Vec::new(),
|
||||
errors: Vec::new(),
|
||||
@ -103,10 +103,11 @@ pub fn make_fast_from_syntaxtree(
|
||||
};
|
||||
let mut ansi_port_last_dir = "";
|
||||
|
||||
// println!("{:?}", syntax_tree);
|
||||
// &SyntaxTree is iterable
|
||||
let doc = Rope::from_str(syntax_tree.text.text());
|
||||
|
||||
// 上一个 module 可以在 fast 的 content 的最后一个中找到
|
||||
|
||||
for node in syntax_tree {
|
||||
match node {
|
||||
RefNode::TextMacroDefinition(x) => {
|
||||
@ -148,20 +149,20 @@ pub fn make_fast_from_syntaxtree(
|
||||
};
|
||||
let define_range = Range { start: start_pos, end: end_pos };
|
||||
|
||||
hdlparam.add_define(name, replacement, define_range, params_vec);
|
||||
fast.add_define(name, replacement, define_range, params_vec);
|
||||
}
|
||||
}
|
||||
RefNode::ModuleDeclaration(x) => {
|
||||
let start_keyword = unwrap_node!(x, Keyword).unwrap();
|
||||
let start_keyword = get_identifier(start_keyword).unwrap();
|
||||
let start_pos = get_position(&doc, start_keyword, 0);
|
||||
let module_range = get_pp_range(&doc, RefNode::ModuleDeclaration(x));
|
||||
let module_range = Range { start: start_pos, end: module_range.end };
|
||||
let module_range = Range { start: start_pos.clone(), end: start_pos };
|
||||
|
||||
let id = unwrap_node!(x, ModuleIdentifier).unwrap();
|
||||
let id = get_identifier(id).unwrap();
|
||||
let name = syntax_tree.get_str(&id).unwrap();
|
||||
hdlparam.new_module(name, module_range);
|
||||
|
||||
fast.new_module(name, module_range);
|
||||
}
|
||||
RefNode::ParameterDeclaration(param_dec) => {
|
||||
let mut event_iter = param_dec.into_iter().event();
|
||||
@ -192,7 +193,7 @@ pub fn make_fast_from_syntaxtree(
|
||||
};
|
||||
let end_pos = get_position(&doc, loc.clone(), loc.len);
|
||||
let param_range = Range { start: start_pos, end: end_pos };
|
||||
hdlparam.add_parameter(name, net_type, init, param_range);
|
||||
fast.add_parameter(name, net_type, init, param_range);
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
@ -235,7 +236,7 @@ pub fn make_fast_from_syntaxtree(
|
||||
let name = syntax_tree.get_str(&id).unwrap();
|
||||
let port_range = Range { start: start_pos.clone(), end: get_position(&doc, id, id.len) };
|
||||
|
||||
hdlparam.add_port(name, dir_type, net_type, width.as_str(), port_range);
|
||||
fast.add_port(name, dir_type, net_type, width.as_str(), port_range);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -284,7 +285,7 @@ pub fn make_fast_from_syntaxtree(
|
||||
_ => "1".to_string()
|
||||
};
|
||||
|
||||
hdlparam.add_port(name, ansi_port_last_dir, net_type, width.as_str(), port_range);
|
||||
fast.add_port(name, ansi_port_last_dir, net_type, width.as_str(), port_range);
|
||||
}
|
||||
}
|
||||
RefNode::ModuleInstantiation(x) => {
|
||||
@ -316,7 +317,7 @@ pub fn make_fast_from_syntaxtree(
|
||||
let inst_port_assignments = get_instance_ports(&syntax_tree, &doc, hier_node.clone());
|
||||
let port_range = get_pp_range(&doc, hier_node).to_option();
|
||||
|
||||
hdlparam.add_instance(
|
||||
fast.add_instance(
|
||||
name, inst_type, inst_range,
|
||||
param_range, inst_param_assignments,
|
||||
port_range, inst_port_assignments
|
||||
@ -342,7 +343,7 @@ pub fn make_fast_from_syntaxtree(
|
||||
let inst_port_assignments = get_instance_ports(&syntax_tree, &doc, gate_node.clone());
|
||||
let port_range = get_pp_range(&doc, gate_node).to_option();
|
||||
|
||||
hdlparam.add_instance(
|
||||
fast.add_instance(
|
||||
name, inst_type, inst_range,
|
||||
param_range, Vec::<InstParameter>::new(),
|
||||
port_range, inst_port_assignments
|
||||
@ -351,13 +352,31 @@ pub fn make_fast_from_syntaxtree(
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
RefNode::Keyword(x) => {
|
||||
let id = x.nodes.0;
|
||||
let name = syntax_tree.get_str(&id).unwrap();
|
||||
let pos = get_position(&doc, id, name.len());
|
||||
|
||||
// 根据关键词进行特殊处理
|
||||
// 比如找到 endmodule 的位置来确定目前的这个 module 的 end
|
||||
match name {
|
||||
"endmodule" => {
|
||||
// 尝试获取 content 最后一个元素的可变引用,该引用如果存在,说明已经创建了一个 module
|
||||
if let Some(last_module) = fast.content.last_mut() {
|
||||
last_module.range.end.line = pos.line;
|
||||
last_module.range.end.character = pos.line;
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
// update_module_range(&path, &mut hdlparam);
|
||||
|
||||
Ok(hdlparam)
|
||||
Ok(fast)
|
||||
}
|
||||
|
||||
// 获取 port 或者 param 的 range
|
||||
@ -705,7 +724,7 @@ fn get_includes(path: &PathBuf) -> Vec<crate::core::hdlparam::Include> {
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn update_module_range(path: &PathBuf, hdlparam: &mut FastHdlparam) {
|
||||
fn update_module_range(path: &PathBuf, fast: &mut FastHdlparam) {
|
||||
let file = File::open(path).unwrap();
|
||||
let reader = BufReader::new(file);
|
||||
|
||||
@ -725,7 +744,7 @@ fn update_module_range(path: &PathBuf, hdlparam: &mut FastHdlparam) {
|
||||
module_stack.push(module_name.clone());
|
||||
} else if re_endmodule.is_match(&line) {
|
||||
if let Some(module_name) = module_stack.pop() {
|
||||
hdlparam.update_module_range(&module_name, (line_number + 1) as u32, current_offset as u32);
|
||||
fast.update_module_range(&module_name, (line_number + 1) as u32, current_offset as u32);
|
||||
// println!("Module {} ends.", module_name);
|
||||
}
|
||||
}
|
||||
|
@ -33,16 +33,26 @@ pub fn inlay_hint(server: &LspServer, params: &InlayHintParams) -> Option<Vec<In
|
||||
for module in &fast.content {
|
||||
for instance in &module.instances {
|
||||
// 根据在可见视图外面的 range 就不管了
|
||||
if is_visible_range(&instance.instparams, &visible_range) {
|
||||
if let Some(range) = &instance.instparams {
|
||||
if is_visible_range(&range, &visible_range) {
|
||||
hints.extend(make_instparam_hints(server, params, instance, rope));
|
||||
}
|
||||
|
||||
if is_visible_range(&instance.instports, &visible_range) {
|
||||
}
|
||||
if let Some(range) = &instance.instports {
|
||||
if is_visible_range(range, &visible_range) {
|
||||
hints.extend(make_instport_hints(server, params, instance, rope));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 在 endmodule 后面添加 module xxx
|
||||
if is_visible_range(&module.range, &visible_range) {
|
||||
hints.extend(make_endmodule_hints(module));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return Some(hints);
|
||||
}
|
||||
|
||||
@ -50,16 +60,46 @@ pub fn inlay_hint(server: &LspServer, params: &InlayHintParams) -> Option<Vec<In
|
||||
}
|
||||
|
||||
fn is_visible_range(
|
||||
target_range: &Option<core::hdlparam::Range>,
|
||||
target_range: &core::hdlparam::Range,
|
||||
visible_range: &core::hdlparam::Range
|
||||
) -> bool {
|
||||
if let Some(target_range) = target_range {
|
||||
if target_range.before(visible_range) || target_range.after(visible_range) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn make_endmodule_hints(
|
||||
module: &core::hdlparam::Module
|
||||
) -> Vec<InlayHint> {
|
||||
let mut hints = Vec::<InlayHint>::new();
|
||||
let end_pos = &module.range.end;
|
||||
let start_pos = &module.range.start;
|
||||
if end_pos.character == start_pos.character && end_pos.line == start_pos.line {
|
||||
// 说明解析器没有找到 endmodule
|
||||
return hints;
|
||||
}
|
||||
|
||||
let module_desc = MarkupContent {
|
||||
kind: MarkupKind::Markdown,
|
||||
value: format!("module {}", module.name)
|
||||
};
|
||||
|
||||
let hint = InlayHint {
|
||||
position: end_pos.to_lsp_position(),
|
||||
label: InlayHintLabel::String(format!("module {}", module.name)),
|
||||
padding_left: Some(true),
|
||||
padding_right: Some(true),
|
||||
kind: Some(InlayHintKind::PARAMETER),
|
||||
text_edits: None,
|
||||
tooltip: Some(InlayHintTooltip::MarkupContent(module_desc)),
|
||||
data: None
|
||||
};
|
||||
|
||||
hints.push(hint);
|
||||
|
||||
hints
|
||||
}
|
||||
|
||||
fn make_instparam_hints(
|
||||
@ -112,6 +152,7 @@ fn find_instport_inlay_hints_position(
|
||||
|
||||
fn make_instport_hints(
|
||||
server: &LspServer,
|
||||
#[allow(unused)]
|
||||
params: &InlayHintParams,
|
||||
instance: &core::hdlparam::Instance,
|
||||
rope: &Rope
|
||||
|
Loading…
x
Reference in New Issue
Block a user