完成 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,17 +272,24 @@ fn make_module_completions(
let path_to_files = server.srcs.hdl_param.path_to_hdl_file.read().unwrap();
// 遍历 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 {
if !module.name.to_string().to_lowercase().starts_with(&prefix) {
continue;
}
let insert_text = make_instantiation_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 {
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 {
label: module.name.to_string(),
@ -290,7 +297,10 @@ fn make_module_completions(
documentation: Some(Documentation::MarkupContent(module_profile)),
kind: Some(CompletionItemKind::CLASS),
insert_text: Some(insert_text),
// 给模块例化自动补全附上最高权重
sort_text: Some("0001".to_string()),
insert_text_format: Some(InsertTextFormat::SNIPPET),
insert_text_mode: Some(InsertTextMode::ADJUST_INDENTATION),
..CompletionItem::default()
};
module_completioms.push(item);

View File

@ -9,7 +9,7 @@ use ropey::Rope;
use tower_lsp::lsp_types::Url;
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 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 = "";
// TODO: 搞清楚为什么会出现重复
let mut added_param_names = HashSet::<String>::new();
// TODO: 删除这个 content
let content = syntax_tree.text.text().split('\n')
.map(|s| s.to_string())
.collect::<Vec<String>>();
// println!("{:?}", syntax_tree);
// &SyntaxTree is iterable
let doc = Rope::from_str(syntax_tree.text.text());
for node in syntax_tree {
match node {
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,
param_end_line, param_end_character) = match unwrap_node!(x, ParameterValueAssignment) {
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)
};
let (port_start_line, port_start_character,
port_end_line, port_end_character) = get_port_parameter_range(&content, hier_node);
let (port_start_line, port_start_character, port_end_line, port_end_character) = get_pp_range(&doc, hier_node);
hdlparam.add_instance(name, inst_type, line, character, 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)
}
/// 返回的四元组:(start_line, start_character, end_line, end_character)
fn get_port_parameter_range(content: &[String], node: RefNode) -> (u32, u32, u32, u32) {
let locate = get_first_last_locate(node);
if locate.is_none() {
(0,0,0,0)
( 0, 0, 0, 0 )
} else {
(
locate.unwrap().0.line, get_column_by_offset(&content, locate.unwrap().0.offset) as u32,
locate.unwrap().1.line, (get_column_by_offset(&content, locate.unwrap().1.offset) + locate.unwrap().1.len) as u32
)
let locate = locate.unwrap();
let start_line = locate.0.line;
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
};
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 {
if token_name == param.name {
@ -242,7 +244,9 @@ fn goto_instantiation<'a>(
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 {
if token_name == port.name {
@ -342,38 +346,6 @@ pub fn hover_module_declaration(
token_name: &str,
language_id: &str
) -> 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 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 def_row = module.range.start.line;
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 param_num = module.params.len();
@ -417,7 +389,6 @@ pub fn hover_module_declaration(
let mut markdowns = Vec::<MarkedString>::new();
markdowns.push(MarkedString::String(port_desc));
markdowns.push(MarkedString::String(io_desc));
markdowns.push(MarkedString::String("".to_string()));
markdowns.push(MarkedString::String(define_info));
markdowns.push(MarkedString::String("---".to_string()));
@ -427,7 +398,7 @@ pub fn hover_module_declaration(
value: module_profile
};
markdowns.push(MarkedString::LanguageString(profile_markdown));
let hover = Hover {
contents: HoverContents::Array(markdowns),
range: None
@ -444,15 +415,18 @@ pub fn hover_module_declaration(
pub fn make_module_profile_code(module: &crate::core::hdlparam::Module) -> String {
let mut codes = Vec::<String>::new();
let param_num = module.params.len();
let port_num = module.ports.len();
let port_num = module.ports.len();
if module.params.len() > 0 {
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() {
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" {
param_desc_array.push(param.init.to_string());
param_desc_array.push(format!(" = {}", param.init.to_string()));
}
let param_desc = param_desc_array.join(" ");
@ -468,23 +442,66 @@ pub fn make_module_profile_code(module: &crate::core::hdlparam::Module) -> Strin
}
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() {
let mut port_desc_array = Vec::<String>::new();
// input, output, inout
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" {
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" {
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" {
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());
let port_desc = port_desc_array.join(" ");
let port_desc = port_desc_array.join("");
if i == port_num - 1 {
codes.push(format!("\t{port_desc}"));
} else {

View File

@ -27,18 +27,20 @@ pub fn hover(server: &LSPServer, params: &HoverParams) -> Option<Hover> {
if let Some(hover) = hover_include(doc, &line_text, pos, &language_id) {
return Some(hover);
}
// match macro
if let Some(hover) = hover_macro(server, &line_text, pos, &language_id) {
return Some(hover);
}
// info!("enter hover_position_port_param");
// match positional port param
if let Some(hover) = hover_position_port_param(server, &line_text, doc, pos, &language_id) {
return Some(hover);
}
// info!("enter hover_module_declaration");
// match module name
if let Some(hover) = hover_module_declaration(server, &token, &language_id) {
// 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 path_string = pathbuf.to_str().unwrap().replace("\\", "/");
let hdlparam = server.srcs.hdl_param.clone();
// info!("current pos: {pos:#?}");
let find_instance_range = |_: &Module, instance: &Instance| {
// info!("instance start pos: {:#?}", instance.range.start);
pos.line + 1 == instance.range.start.line
};
let find_module_range = |module: &Module| {