完成 hover 视图对齐
This commit is contained in:
parent
8d733112c4
commit
82a21ccf34
@ -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);
|
||||||
|
@ -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 )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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}"));
|
||||||
|
@ -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| {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user