完成 hover 视图对齐

This commit is contained in:
锦恢 2024-10-28 23:01:37 +08:00
parent 8d733112c4
commit 82a21ccf34
4 changed files with 106 additions and 57 deletions

View File

@ -272,25 +272,35 @@ fn make_module_completions(
let path_to_files = server.srcs.hdl_param.path_to_hdl_file.read().unwrap(); let path_to_files = server.srcs.hdl_param.path_to_hdl_file.read().unwrap();
// 遍历 hdlparam 中所有的 modules // 遍历 hdlparam 中所有的 modules
for (_, hdl_file) in path_to_files.iter() { for (path_string, hdl_file) in path_to_files.iter() {
for module in &hdl_file.fast.content { for module in &hdl_file.fast.content {
if !module.name.to_string().to_lowercase().starts_with(&prefix) { if !module.name.to_string().to_lowercase().starts_with(&prefix) {
continue; continue;
} }
let insert_text = make_instantiation_code(module); let insert_text = make_instantiation_code(module);
let module_profile = make_module_profile_code(module); let module_profile = make_module_profile_code(module);
let path_uri = Url::from_file_path(path_string.to_string()).unwrap().to_string();
let def_row = module.range.start.line;
let def_col = module.range.start.character;
let define_info = format!("Go to [Definition]({path_uri}#L{def_row}:{def_col})");
let module_profile = MarkupContent { let module_profile = MarkupContent {
kind: MarkupKind::Markdown, kind: MarkupKind::Markdown,
value: format!("```{}\n{}\n```", language_id, module_profile) value: format!("```{}\n{}\n```\n{}", language_id, module_profile, define_info)
}; };
let item = CompletionItem { let item = CompletionItem {
label: module.name.to_string(), label: module.name.to_string(),
detail: Some("module instantiation".to_string()), detail: Some("module instantiation".to_string()),
documentation: Some(Documentation::MarkupContent(module_profile)), documentation: Some(Documentation::MarkupContent(module_profile)),
kind: Some(CompletionItemKind::CLASS), kind: Some(CompletionItemKind::CLASS),
insert_text: Some(insert_text), insert_text: Some(insert_text),
// 给模块例化自动补全附上最高权重
sort_text: Some("0001".to_string()),
insert_text_format: Some(InsertTextFormat::SNIPPET), insert_text_format: Some(InsertTextFormat::SNIPPET),
insert_text_mode: Some(InsertTextMode::ADJUST_INDENTATION),
..CompletionItem::default() ..CompletionItem::default()
}; };
module_completioms.push(item); module_completioms.push(item);

View File

@ -9,7 +9,7 @@ use ropey::Rope;
use tower_lsp::lsp_types::Url; use tower_lsp::lsp_types::Url;
use sv_parser::{unwrap_locate, unwrap_node, EventIter, ListOfParamAssignments, Locate, NodeEvent, ParamAssignment, ParameterDeclaration, RefNode, SyntaxTree}; use sv_parser::{unwrap_locate, unwrap_node, EventIter, ListOfParamAssignments, Locate, NodeEvent, ParamAssignment, ParameterDeclaration, RefNode, SyntaxTree};
use crate::sources::recovery_sv_parse_with_retry; use crate::sources::{recovery_sv_parse_with_retry, LSPSupport};
use crate::utils::to_escape_path; use crate::utils::to_escape_path;
use super::hdlparam::{FastHdlparam, Macro}; use super::hdlparam::{FastHdlparam, Macro};
@ -114,14 +114,14 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re
}; };
let mut ansi_port_last_dir = ""; let mut ansi_port_last_dir = "";
// TODO: 搞清楚为什么会出现重复 // TODO: 删除这个 content
let mut added_param_names = HashSet::<String>::new();
let content = syntax_tree.text.text().split('\n') let content = syntax_tree.text.text().split('\n')
.map(|s| s.to_string()) .map(|s| s.to_string())
.collect::<Vec<String>>(); .collect::<Vec<String>>();
// println!("{:?}", syntax_tree); // println!("{:?}", syntax_tree);
// &SyntaxTree is iterable // &SyntaxTree is iterable
let doc = Rope::from_str(syntax_tree.text.text());
for node in syntax_tree { for node in syntax_tree {
match node { match node {
RefNode::TextMacroDefinition(x) => { RefNode::TextMacroDefinition(x) => {
@ -312,13 +312,13 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re
let (param_start_line, param_start_character, let (param_start_line, param_start_character,
param_end_line, param_end_character) = match unwrap_node!(x, ParameterValueAssignment) { param_end_line, param_end_character) = match unwrap_node!(x, ParameterValueAssignment) {
Some(inst_node) => { Some(inst_node) => {
get_port_parameter_range(&content, inst_node) // get_port_parameter_range(&content, inst_node)
get_pp_range(&doc, inst_node)
} }
_ => (0, 0, 0, 0) _ => (0, 0, 0, 0)
}; };
let (port_start_line, port_start_character, let (port_start_line, port_start_character, port_end_line, port_end_character) = get_pp_range(&doc, hier_node);
port_end_line, port_end_character) = get_port_parameter_range(&content, hier_node);
hdlparam.add_instance(name, inst_type, line, character, end_character, hdlparam.add_instance(name, inst_type, line, character, end_character,
param_start_line, param_start_character, param_end_line, param_end_character, param_start_line, param_start_character, param_end_line, param_end_character,
@ -361,15 +361,33 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re
Ok(hdlparam) Ok(hdlparam)
} }
/// 返回的四元组:(start_line, start_character, end_line, end_character)
fn get_port_parameter_range(content: &[String], node: RefNode) -> (u32, u32, u32, u32) { fn get_port_parameter_range(content: &[String], node: RefNode) -> (u32, u32, u32, u32) {
let locate = get_first_last_locate(node); let locate = get_first_last_locate(node);
if locate.is_none() { if locate.is_none() {
( 0, 0, 0, 0 ) ( 0, 0, 0, 0 )
} else { } else {
( let locate = locate.unwrap();
locate.unwrap().0.line, get_column_by_offset(&content, locate.unwrap().0.offset) as u32, let start_line = locate.0.line;
locate.unwrap().1.line, (get_column_by_offset(&content, locate.unwrap().1.offset) + locate.unwrap().1.len) as u32 let start_character = get_column_by_offset(&content, locate.0.offset) as u32;
) let end_line = locate.1.line;
let end_character = get_column_by_offset(&content, locate.1.offset + locate.1.len) as u32;
( start_line, start_character, end_line, end_character )
}
}
// 获取 port 或者 param 的 range
/// 返回的四元组:(start_line, start_character, end_line, end_character)
fn get_pp_range(doc: &Rope, node: RefNode) -> (u32, u32, u32, u32) {
if let Some(locate) = get_first_last_locate(node) {
let start_byte = locate.0.offset;
let end_byte = locate.1.offset + locate.1.len;
let start_pos = doc.byte_to_pos(start_byte);
let end_pos = doc.byte_to_pos(end_byte);
( start_pos.line, start_pos.character, end_pos.line, end_pos.character )
} else {
( 0, 0, 0, 0 )
} }
} }

View File

@ -223,7 +223,9 @@ fn goto_instantiation<'a>(
None => return None None => return None
}; };
info!("position param find belong module: {:?}", module); info!("current pos: {pos:#?}");
info!("param_range: {param_range:#?}");
// info!("position param find belong module: {:?}", module);
for param in &module.params { for param in &module.params {
if token_name == param.name { if token_name == param.name {
@ -242,7 +244,9 @@ fn goto_instantiation<'a>(
None => return None None => return None
}; };
info!("position port find belong module: {:?}", module); info!("current pos: {pos:#?}");
info!("port_range: {port_range:#?}");
// info!("position port find belong module: {:?}", module);
for port in &module.ports { for port in &module.ports {
if token_name == port.name { if token_name == port.name {
@ -342,38 +346,6 @@ pub fn hover_module_declaration(
token_name: &str, token_name: &str,
language_id: &str language_id: &str
) -> Option<Hover> { ) -> Option<Hover> {
// let module_info = match definition.def_type {
// DefinitionType::GenericScope => {
// let pathbuf = PathBuf::from_str(definition.url.path()).unwrap();
// let pathbuf = to_escape_path(&pathbuf);
// let path_string = pathbuf.to_str().unwrap();
// let hdlparam = &server.srcs.hdl_param;
// let search_result = || {
// if let Some(hdl_file) = hdlparam.path_to_hdl_file.read().unwrap().get(path_string) {
// for module in &hdl_file.fast.content {
// if module.name == definition.ident {
// return Some((module.clone(), path_string.to_string()));
// }
// }
// }
// None
// };
// search_result()
// }
// _ => {
// let search_result = || {
// if let Some(module) = server.srcs.hdl_param.find_module_by_name(token_name) {
// let path_string = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap_or("unknown".to_string());
// return Some((module, path_string));
// }
// None
// };
// search_result()
// }
// };
let module_info = { let module_info = {
let search_result = || { let search_result = || {
@ -390,7 +362,7 @@ pub fn hover_module_declaration(
let path_uri = Url::from_file_path(path_string.to_string()).unwrap().to_string(); let path_uri = Url::from_file_path(path_string.to_string()).unwrap().to_string();
let def_row = module.range.start.line; let def_row = module.range.start.line;
let def_col = module.range.start.character; let def_col = module.range.start.character;
let define_info = format!("Definition [{path_string}]({path_uri}#L{def_row}:{def_col})"); let define_info = format!("Go to [Definition]({path_uri}#L{def_row}:{def_col})");
let port_num = module.ports.len(); let port_num = module.ports.len();
let param_num = module.params.len(); let param_num = module.params.len();
@ -417,7 +389,6 @@ pub fn hover_module_declaration(
let mut markdowns = Vec::<MarkedString>::new(); let mut markdowns = Vec::<MarkedString>::new();
markdowns.push(MarkedString::String(port_desc)); markdowns.push(MarkedString::String(port_desc));
markdowns.push(MarkedString::String(io_desc)); markdowns.push(MarkedString::String(io_desc));
markdowns.push(MarkedString::String("".to_string()));
markdowns.push(MarkedString::String(define_info)); markdowns.push(MarkedString::String(define_info));
markdowns.push(MarkedString::String("---".to_string())); markdowns.push(MarkedString::String("---".to_string()));
@ -448,11 +419,14 @@ pub fn make_module_profile_code(module: &crate::core::hdlparam::Module) -> Strin
if module.params.len() > 0 { if module.params.len() > 0 {
codes.push(format!("module {} #(", module.name)); codes.push(format!("module {} #(", module.name));
let max_param_name_length = module.params.iter().map(|param| param.name.len()).max().unwrap_or(0);
for (i, param) in module.params.iter().enumerate() { for (i, param) in module.params.iter().enumerate() {
let mut param_desc_array = Vec::<String>::new(); let mut param_desc_array = Vec::<String>::new();
param_desc_array.push(format!("parameter {}", param.name)); param_desc_array.push(format!("parameter {}{}", param.name, " ".repeat(max_param_name_length - param.name.len())));
if param.init != "unknown" { if param.init != "unknown" {
param_desc_array.push(param.init.to_string()); param_desc_array.push(format!(" = {}", param.init.to_string()));
} }
let param_desc = param_desc_array.join(" "); let param_desc = param_desc_array.join(" ");
@ -468,22 +442,65 @@ pub fn make_module_profile_code(module: &crate::core::hdlparam::Module) -> Strin
} }
if module.ports.len() > 0 { if module.ports.len() > 0 {
let net_mapper = |net_type: &str| {
if net_type == "unknown" {
0
} else {
net_type.len()
}
};
let sign_mapper = |signed: &str| {
if signed == "unsigned" {
0
} else {
"signed".len()
}
};
let width_mapper = |width: &str| {
if width == "1" {
0
} else {
width.len()
}
};
let max_net_length = module.ports.iter().map(|port| net_mapper(&port.net_type)).max().unwrap_or(0);
let max_sign_length = module.ports.iter().map(|port| sign_mapper(&port.signed)).max().unwrap_or(0);
let max_width_length = module.ports.iter().map(|port| width_mapper(&port.width)).max().unwrap_or(0);
let max_dir_length = module.ports.iter().map(|port| port.dir_type.len()).max().unwrap_or(0);
for (i, port) in module.ports.iter().enumerate() { for (i, port) in module.ports.iter().enumerate() {
let mut port_desc_array = Vec::<String>::new(); let mut port_desc_array = Vec::<String>::new();
// input, output, inout
port_desc_array.push(port.dir_type.to_string()); port_desc_array.push(port.dir_type.to_string());
port_desc_array.push(" ".repeat(max_dir_length - port.dir_type.len() + 1));
// reg, wire
if port.net_type != "unknown" { if port.net_type != "unknown" {
port_desc_array.push(port.net_type.to_string()); port_desc_array.push(port.net_type.to_string());
} }
port_desc_array.push(" ".repeat(max_net_length - net_mapper(&port.net_type) + 1));
// signed, unsigned
if port.signed != "unsigned" { if port.signed != "unsigned" {
port_desc_array.push("signed".to_string()); port_desc_array.push("signed".to_string());
} }
port_desc_array.push(" ".repeat(max_sign_length - sign_mapper(&port.signed) + 1));
// [3:0]
if port.width != "1" { if port.width != "1" {
port_desc_array.push(port.width.to_string()); port_desc_array.push(port.width.to_string());
} }
port_desc_array.push(" ".repeat(max_width_length - width_mapper(&port.width) + 1));
// port 的名字
port_desc_array.push(port.name.to_string()); port_desc_array.push(port.name.to_string());
let port_desc = port_desc_array.join(""); let port_desc = port_desc_array.join("");
if i == port_num - 1 { if i == port_num - 1 {
codes.push(format!("\t{port_desc}")); codes.push(format!("\t{port_desc}"));

View File

@ -33,12 +33,14 @@ pub fn hover(server: &LSPServer, params: &HoverParams) -> Option<Hover> {
return Some(hover); return Some(hover);
} }
// info!("enter hover_position_port_param");
// match positional port param // match positional port param
if let Some(hover) = hover_position_port_param(server, &line_text, doc, pos, &language_id) { if let Some(hover) = hover_position_port_param(server, &line_text, doc, pos, &language_id) {
return Some(hover); return Some(hover);
} }
// info!("enter hover_module_declaration");
// match module name // match module name
if let Some(hover) = hover_module_declaration(server, &token, &language_id) { if let Some(hover) = hover_module_declaration(server, &token, &language_id) {
// info!("[LSPServer] in hover: get module hover"); // info!("[LSPServer] in hover: get module hover");
@ -300,7 +302,9 @@ fn hover_for_module(server: &LSPServer, pos: Position, doc: &Url) -> bool {
let pathbuf = to_escape_path(&pathbuf); let pathbuf = to_escape_path(&pathbuf);
let path_string = pathbuf.to_str().unwrap().replace("\\", "/"); let path_string = pathbuf.to_str().unwrap().replace("\\", "/");
let hdlparam = server.srcs.hdl_param.clone(); let hdlparam = server.srcs.hdl_param.clone();
// info!("current pos: {pos:#?}");
let find_instance_range = |_: &Module, instance: &Instance| { let find_instance_range = |_: &Module, instance: &Instance| {
// info!("instance start pos: {:#?}", instance.range.start);
pos.line + 1 == instance.range.start.line pos.line + 1 == instance.range.start.line
}; };
let find_module_range = |module: &Module| { let find_module_range = |module: &Module| {