From aad333783e4bbd4ed6cb3b3aacc83981c653da78 Mon Sep 17 00:00:00 2001 From: LSTM-Kirigaya <1193466151@qq.com> Date: Fri, 13 Dec 2024 01:56:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20system=20task=20=E4=B8=AD?= =?UTF-8?q?=E5=87=A0=E4=B8=AA=E6=9C=AA=E8=BD=AC=E4=B9=89=E7=9A=84=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=20|=20=E6=89=80=E6=9C=89=E8=87=AA=E5=8A=A8=E8=A1=A5?= =?UTF-8?q?=E5=85=A8=E5=A2=9E=E5=8A=A0=20label=5Fdetails?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/lsp.code-snippets | 10 ++++ src/completion/feature.rs | 88 ++++++++++++++++++++++++++++++----- src/completion/keyword.rs | 6 +++ src/completion/sv.rs | 19 ++++++-- src/completion/sys_tasks.rs | 41 +++++++++------- src/completion/vhdl.rs | 2 +- src/core/scope_tree/common.rs | 72 ++++++++++++---------------- src/core/scope_tree/parse.rs | 2 + src/diagnostics/vivado.rs | 47 ++----------------- src/sources.rs | 17 ------- 10 files changed, 165 insertions(+), 139 deletions(-) diff --git a/.vscode/lsp.code-snippets b/.vscode/lsp.code-snippets index 1d545db..50c7cff 100644 --- a/.vscode/lsp.code-snippets +++ b/.vscode/lsp.code-snippets @@ -44,5 +44,15 @@ "\t$2", "}" ] + }, + "CompletionItemLabelDetails Snippet": { + "prefix": "label_details", + "body": [ + "let label_details = CompletionItemLabelDetails {", + " description: Some(\"${1:port description}\".to_string()),", + " ..Default::default()", + "};" + ], + "description": "Create a CompletionItemLabelDetails with description." } } \ No newline at end of file diff --git a/src/completion/feature.rs b/src/completion/feature.rs index bb7f1ce..84954a9 100644 --- a/src/completion/feature.rs +++ b/src/completion/feature.rs @@ -2,7 +2,7 @@ use std::{fs, path::PathBuf, str::FromStr}; use log::info; use ropey::RopeSlice; -use tower_lsp::lsp_types::{CompletionItem, CompletionItemKind, CompletionItemLabelDetails, CompletionList, Position, Url}; +use tower_lsp::lsp_types::{CompletionItem, CompletionItemKind, CompletionItemLabelDetails, CompletionList, Documentation, MarkupContent, Position, Url}; use crate::{server::LspServer, utils::{is_character_ordered_match, resolve_path, to_escape_path}}; @@ -63,16 +63,26 @@ pub fn include_path_completion( let file_name = file_name.unwrap(); if path.is_dir() { + let label_details = CompletionItemLabelDetails { + description: Some("directory".to_string()), + ..Default::default() + }; completion_items.push(CompletionItem { label: file_name.to_string(), + label_details: Some(label_details), kind: Some(CompletionItemKind::FOLDER), ..CompletionItem::default() }); } if path.is_file() { + let label_details = CompletionItemLabelDetails { + description: Some("file".to_string()), + ..Default::default() + }; completion_items.push(CompletionItem { label: file_name.to_string(), + label_details: Some(label_details), kind: Some(CompletionItemKind::FILE), ..CompletionItem::default() }); @@ -92,6 +102,7 @@ pub fn include_path_completion( None } + /// 补全宏 pub fn vlog_directives_completion( token: &str, @@ -108,11 +119,22 @@ pub fn vlog_directives_completion( for hdl_file in path_to_hdl_file.values() { for define in &hdl_file.fast.fast_macro.defines { if is_character_ordered_match(token, &define.name) { + let label_details = CompletionItemLabelDetails { + description: Some("`define".to_string()), + ..Default::default() + }; + let documentation = Documentation::MarkupContent(MarkupContent { + kind: tower_lsp::lsp_types::MarkupKind::Markdown, + value: format!("```verilog\n`define {} {}\n```", define.name, define.replacement) + }); completion_items.push(CompletionItem { label: define.name.to_string(), kind: Some(CompletionItemKind::CONSTANT), + detail: Some("macro".to_string()), // 用户定义的宏默认最高优先级 - sort_text: Some("0001".to_string()), + sort_text: Some("0".to_string()), + label_details: Some(label_details), + documentation: Some(documentation), ..CompletionItem::default() }); } @@ -125,6 +147,48 @@ pub fn vlog_directives_completion( }) } +/// 不是由 ` 触发的宏补全 +pub fn vlog_directives_completion_without_prefix( + token: &str, + server: &LspServer +) -> Vec { + // 先把固定宏定义比如 include, define 这种的放入其中 + let mut completion_items = server.vlog_directives.clone(); + + // 再从每个文件中搜集定义的宏 + let hdl_param = server.srcs.hdl_param.clone(); + let path_to_hdl_file = hdl_param.path_to_hdl_file.read().unwrap(); + + // 遍历所有的 defines + for hdl_file in path_to_hdl_file.values() { + for define in &hdl_file.fast.fast_macro.defines { + if is_character_ordered_match(token, &define.name) { + let label_details = CompletionItemLabelDetails { + description: Some("`define".to_string()), + ..Default::default() + }; + let documentation = Documentation::MarkupContent(MarkupContent { + kind: tower_lsp::lsp_types::MarkupKind::Markdown, + value: format!("```verilog\n`define {} {}\n```", define.name, define.replacement) + }); + completion_items.push(CompletionItem { + label: define.name.to_string(), + kind: Some(CompletionItemKind::CONSTANT), + insert_text: Some(format!("`{}", define.name)), + detail: Some("macro".to_string()), + label_details: Some(label_details), + documentation: Some(documentation), + // 用户定义的宏默认最高优先级 + sort_text: Some("0".to_string()), + ..CompletionItem::default() + }); + } + } + } + + completion_items +} + pub fn get_dot_completion( server: &LspServer, line: &RopeSlice, @@ -209,14 +273,14 @@ fn get_position_port_param_completion( "primitives" => { if let Some(primitives_inst) = inst_module.instances.first() { for param_assignment in &primitives_inst.intstparam_assignments { - let label_details = CompletionItemLabelDetails { - detail: None, - ..CompletionItemLabelDetails::default() - }; - let name = param_assignment.parameter.clone().unwrap(); let param_desc = format!("parameter {}", name); + let label_details = CompletionItemLabelDetails { + description: Some("parameter".to_string()), + ..Default::default() + }; + let c_item = CompletionItem { label: name, detail: Some(param_desc), @@ -231,8 +295,8 @@ fn get_position_port_param_completion( _ => { for param in inst_module.params { let label_details = CompletionItemLabelDetails { - detail: None, - ..CompletionItemLabelDetails::default() + description: Some("parameter".to_string()), + ..Default::default() }; let param_desc = match file_type.as_str() { @@ -276,7 +340,7 @@ fn get_position_port_param_completion( if let Some(primitives_inst) = inst_module.instances.first() { for port_assignment in &primitives_inst.intstport_assignments { let label_details = CompletionItemLabelDetails { - detail: None, + detail: Some("port".to_string()), ..CompletionItemLabelDetails::default() }; @@ -297,8 +361,8 @@ fn get_position_port_param_completion( _ => { for port in inst_module.ports { let label_details = CompletionItemLabelDetails { - detail: None, - ..CompletionItemLabelDetails::default() + description: Some("port".to_string()), + ..Default::default() }; let port_desc = match file_type.as_str() { diff --git a/src/completion/keyword.rs b/src/completion/keyword.rs index 09fc4f0..b42d2f6 100644 --- a/src/completion/keyword.rs +++ b/src/completion/keyword.rs @@ -4,9 +4,14 @@ use tower_lsp::lsp_types::*; pub fn keyword_completions(keywords: &[(&str, &str)]) -> Vec { let mut items: Vec = Vec::new(); for key in keywords { + let label_details = CompletionItemLabelDetails { + description: Some("keyword".to_string()), + ..Default::default() + }; if key.1.is_empty() { items.push(CompletionItem { label: key.0.to_string(), + label_details: Some(label_details), kind: Some(CompletionItemKind::KEYWORD), ..CompletionItem::default() }); @@ -14,6 +19,7 @@ pub fn keyword_completions(keywords: &[(&str, &str)]) -> Vec { items.push(CompletionItem { label: key.0.to_string(), kind: Some(CompletionItemKind::KEYWORD), + label_details: Some(label_details), insert_text: Some(key.1.to_string()), insert_text_format: Some(InsertTextFormat::SNIPPET), ..CompletionItem::default() diff --git a/src/completion/sv.rs b/src/completion/sv.rs index 023b999..ae039fa 100644 --- a/src/completion/sv.rs +++ b/src/completion/sv.rs @@ -1,9 +1,8 @@ use crate::{completion::feature::{get_dot_completion, include_path_completion}, core, hover::feature::make_module_profile_code, server::LspServer, sources::LSPSupport, utils::{get_definition_token, get_language_id_by_uri, is_character_ordered_match}}; use log::info; -use ropey::{Rope, RopeSlice}; use tower_lsp::lsp_types::*; -use super::feature::vlog_directives_completion; +use super::feature::{vlog_directives_completion, vlog_directives_completion_without_prefix}; pub fn completion(server: &LspServer, params: &CompletionParams) -> Option { @@ -62,13 +61,14 @@ pub fn completion(server: &LspServer, params: &CompletionParams) -> Option { // 1. 先根据 AST 获取上下文补全项 + // 去除如下几种情况:module textmacro let mut completion_items = server.srcs.get_completions( &token, file.text.pos_to_byte(&doc.position), &doc.text_document.uri, )?; - info!("current completion token: {}", token); + // info!("current completion token: {}", token); // 2. 根据 token 加入关键词 // TODO: 考虑使用前缀树进行优化 @@ -95,6 +95,11 @@ pub fn completion(server: &LspServer, params: &CompletionParams) -> Option>( + vlog_directives_completion_without_prefix(&token, server) + ); + // 不知道为什么会有重复,去重就完事 completion_items.items.dedup_by_key(|i| i.label.clone()); @@ -260,15 +265,19 @@ fn make_module_completions( }; let detail = format!("module instantiation ({})", file_type); - + let label_details = CompletionItemLabelDetails { + description: Some("module instantiation".to_string()), + ..Default::default() + }; let item = CompletionItem { label: module.name.to_string(), detail: Some(detail), + label_details: Some(label_details), documentation: Some(Documentation::MarkupContent(module_profile)), kind: Some(CompletionItemKind::CLASS), insert_text: Some(insert_text), // 给模块例化自动补全附上最高权重 - sort_text: Some("0001".to_string()), + sort_text: Some("0".to_string()), insert_text_format: Some(InsertTextFormat::SNIPPET), insert_text_mode: Some(InsertTextMode::ADJUST_INDENTATION), ..CompletionItem::default() diff --git a/src/completion/sys_tasks.rs b/src/completion/sys_tasks.rs index f37f47d..1513256 100644 --- a/src/completion/sys_tasks.rs +++ b/src/completion/sys_tasks.rs @@ -187,27 +187,27 @@ pub const VLOG_STOP_TASKS: &[(&str, &str, &str)] = &[ /// Array types tasks IEEE 1364-2005 17.5.1 /// (&str, &str, &str): (label, snippet, description) pub const VLOG_ARRAY_TYPES_TASKS: &[(&str, &str, &str)] = &[ - ("async$and$array", "\\$async$and$array($1, $2);", "对数组进行异步与操作。\n```verilog\n$async$and$array(array1, array2);\n```"), - ("async$nand$array", "\\$async$nand$array($1, $2);", "对数组进行异步与非操作。\n```verilog\n$async$nand$array(array1, array2);\n```"), - ("async$or$array", "\\$async$or$array($1, $2);", "对数组进行异步或操作。\n```verilog\n$async$or$array(array1, array2);\n```"), - ("async$nor$array", "\\$async$nor$array($1, $2);", "对数组进行异步或非操作。\n```verilog\n$async$nor$array(array1, array2);\n```"), - ("sync$and$array", "\\$sync$and$array($1, $2);", "对数组进行同步与操作。\n```verilog\n$sync$and$array(array1, array2);\n```"), - ("sync$nand$array", "\\$sync$nand$array($1, $2);", "对数组进行同步与非操作。\n```verilog\n$sync$nand$array(array1, array2);\n```"), - ("sync$or$array", "\\$sync$or$array($1, $2);", "对数组进行同步或操作。\n```verilog\n$sync$or$array(array1, array2);\n```"), - ("sync$nor$array", "\\$sync$nor$array($1, $2);", "对数组进行同步或非操作。\n```verilog\n$sync$nor$array(array1, array2);\n```"), + ("async$and$array", "\\$async\\$and\\$array($1, $2);", "对数组进行异步与操作。\n```verilog\n$async$and$array(array1, array2);\n```"), + ("async$nand$array", "\\$async\\$nand\\$array($1, $2);", "对数组进行异步与非操作。\n```verilog\n$async$nand$array(array1, array2);\n```"), + ("async$or$array", "\\$async\\$or\\$array($1, $2);", "对数组进行异步或操作。\n```verilog\n$async$or$array(array1, array2);\n```"), + ("async$nor$array", "\\$async\\$nor\\$array($1, $2);", "对数组进行异步或非操作。\n```verilog\n$async$nor$array(array1, array2);\n```"), + ("sync$and$array", "\\$sync\\$and\\$array($1, $2);", "对数组进行同步与操作。\n```verilog\n$sync$and$array(array1, array2);\n```"), + ("sync$nand$array", "\\$sync\\$nand\\$array($1, $2);", "对数组进行同步与非操作。\n```verilog\n$sync$nand$array(array1, array2);\n```"), + ("sync$or$array", "\\$sync\\$or\\$array($1, $2);", "对数组进行同步或操作。\n```verilog\n$sync$or$array(array1, array2);\n```"), + ("sync$nor$array", "\\$sync\\$nor\\$array($1, $2);", "对数组进行同步或非操作。\n```verilog\n$sync$nor$array(array1, array2);\n```"), ]; /// Array logic types tasks IEEE 1364-2005 17.5.2 /// (&str, &str, &str): (label, snippet, description) pub const VLOG_ARRAY_LOGIC_TYPES_TASKS: &[(&str, &str, &str)] = &[ - ("async$and$plane", "\\$async$and$plane($1, $2);", "对数组平面进行异步与操作。\n```verilog\n$async$and$plane(plane1, plane2);\n```"), - ("async$nand$plane", "\\$async$nand$plane($1, $2);", "对数组平面进行异步与非操作。\n```verilog\n$async$nand$plane(plane1, plane2);\n```"), - ("async$or$plane", "\\$async$or$plane($1, $2);", "对数组平面进行异步或操作。\n```verilog\n$async$or$plane(plane1, plane2);\n```"), - ("async$nor$plane", "\\$async$nor$plane($1, $2);", "对数组平面进行异步或非操作。\n```verilog\n$async$nor$plane(plane1, plane2);\n```"), - ("sync$and$plane", "\\$sync$and$plane($1, $2);", "对数组平面进行同步与操作。\n```verilog\n$sync$and$plane(plane1, plane2);\n```"), - ("sync$nand$plane", "\\$sync$nand$plane($1, $2);", "对数组平面进行同步与非操作。\n```verilog\n$sync$nand$plane(plane1, plane2);\n```"), - ("sync$or$plane", "\\$sync$or$plane($1, $2);", "对数组平面进行同步或操作。\n```verilog\n$sync$or$plane(plane1, plane2);\n```"), - ("sync$nor$plane", "\\$sync$nor$plane($1, $2);", "对数组平面进行同步或非操作。\n```verilog\n$sync$nor$plane(plane1, plane2);\n```"), + ("async$and$plane", "\\$async\\$and\\$plane($1, $2);", "对数组平面进行异步与操作。\n```verilog\n$async$and$plane(plane1, plane2);\n```"), + ("async$nand$plane", "\\$async\\$nand\\$plane($1, $2);", "对数组平面进行异步与非操作。\n```verilog\n$async$nand$plane(plane1, plane2);\n```"), + ("async$or$plane", "\\$async\\$or\\$plane($1, $2);", "对数组平面进行异步或操作。\n```verilog\n$async$or$plane(plane1, plane2);\n```"), + ("async$nor$plane", "\\$async\\$nor\\$plane($1, $2);", "对数组平面进行异步或非操作。\n```verilog\n$async$nor$plane(plane1, plane2);\n```"), + ("sync$and$plane", "\\$sync\\$and\\$plane($1, $2);", "对数组平面进行同步与操作。\n```verilog\n$sync$and$plane(plane1, plane2);\n```"), + ("sync$nand$plane", "\\$sync\\$nand\\$plane($1, $2);", "对数组平面进行同步与非操作。\n```verilog\n$sync$nand$plane(plane1, plane2);\n```"), + ("sync$or$plane", "\\$sync\\$or\\$plane($1, $2);", "对数组平面进行同步或操作。\n```verilog\n$sync$or$plane(plane1, plane2);\n```"), + ("sync$nor$plane", "\\$sync\\$nor\\$plane($1, $2);", "对数组平面进行同步或非操作。\n```verilog\n$sync$nor$plane(plane1, plane2);\n```"), ]; /// $q_initialize tasks IEEE 1364-2005 17.6.1 @@ -291,13 +291,13 @@ pub const VLOG_DIST_FUNCTIONS_TASKS: &[(&str, &str, &str)] = &[ /// $test$plusargs (string) tasks IEEE 1364-2005 17.10.1 /// (&str, &str, &str): (label, snippet, description) pub const VLOG_TEST_PLUSARGS_TASKS: &[(&str, &str, &str)] = &[ - ("test$plusargs", "\\$test$plusargs($1);", "检查仿真命令行参数中是否包含指定的字符串。\n```verilog\ninteger result;\nresult = $test$plusargs(\"test_string\");\n```\n\n示例代码:\n```verilog\ninitial begin\n\tif ($test$plusargs(\"HELLO\")) $display(\"Hello argument found.\");\n\tif ($test$plusargs(\"HE\")) $display(\"The HE subset string is detected.\");\n\tif ($test$plusargs(\"H\")) $display(\"Argument starting with H found.\");\n\tif ($test$plusargs(\"HELLO_HERE\")) $display(\"Long argument.\");\n\tif ($test$plusargs(\"HI\")) $display(\"Simple greeting.\");\n\tif ($test$plusargs(\"LO\")) $display(\"Does not match.\");\nend\n```"), + ("test$plusargs", "\\$test\\$plusargs($1);", "检查仿真命令行参数中是否包含指定的字符串。\n```verilog\ninteger result;\nresult = $test$plusargs(\"test_string\");\n```\n\n示例代码:\n```verilog\ninitial begin\n\tif ($test$plusargs(\"HELLO\")) $display(\"Hello argument found.\");\n\tif ($test$plusargs(\"HE\")) $display(\"The HE subset string is detected.\");\n\tif ($test$plusargs(\"H\")) $display(\"Argument starting with H found.\");\n\tif ($test$plusargs(\"HELLO_HERE\")) $display(\"Long argument.\");\n\tif ($test$plusargs(\"HI\")) $display(\"Simple greeting.\");\n\tif ($test$plusargs(\"LO\")) $display(\"Does not match.\");\nend\n```"), ]; /// $value$plusargs (user_string, variable) tasks IEEE 1364-2005 17.10.2 /// (&str, &str, &str): (label, snippet, description) pub const VLOG_VALUE_PLUSARGS_TASKS: &[(&str, &str, &str)] = &[ - ("value$plusargs", "\\$value$plusargs($1, $2);", "从仿真命令行参数中提取值并赋给变量。\n```verilog\ninteger result;\nresult = $value$plusargs(\"test_string=\", value);\n```\n\n示例代码:\n```verilog\n`define STRING reg [1024 * 8:1]\nmodule goodtasks;\n\t`STRING str;\n\tinteger int;\n\treg [31:0] vect;\n\treal realvar;\n\tinitial\n\tbegin\n\t\tif ($value$plusargs(\"TEST=%d\", int))\n\t\t\t$display(\"value was %d\", int);\n\t\telse\n\t\t\t$display(\"+TEST= not found\");\n\t\t#100 $finish;\n\tend\nendmodule\n```"), + ("value$plusargs", "\\$value\\$plusargs($1, $2);", "从仿真命令行参数中提取值并赋给变量。\n```verilog\ninteger result;\nresult = $value$plusargs(\"test_string=\", value);\n```\n\n示例代码:\n```verilog\n`define STRING reg [1024 * 8:1]\nmodule goodtasks;\n\t`STRING str;\n\tinteger int;\n\treg [31:0] vect;\n\treal realvar;\n\tinitial\n\tbegin\n\t\tif ($value$plusargs(\"TEST=%d\", int))\n\t\t\t$display(\"value was %d\", int);\n\t\telse\n\t\t\t$display(\"+TEST= not found\");\n\t\t#100 $finish;\n\tend\nendmodule\n```"), ]; /// Integer math functions tasks IEEE 1364-2005 17.11.1 @@ -449,9 +449,14 @@ fn update_task_completions( ) { for (label, snippet_code, description) in tasks { let function_profile = make_function_profile(section, description); + let label_details = CompletionItemLabelDetails { + description: Some("system task".to_string()), + ..Default::default() + }; items.push(CompletionItem { label: label.to_string(), detail: Some(section.to_string()), + label_details: Some(label_details), documentation: Some(Documentation::MarkupContent(function_profile)), kind: Some(CompletionItemKind::FUNCTION), insert_text: Some(snippet_code.to_string()), diff --git a/src/completion/vhdl.rs b/src/completion/vhdl.rs index 6989915..c09b6a4 100644 --- a/src/completion/vhdl.rs +++ b/src/completion/vhdl.rs @@ -262,7 +262,7 @@ fn make_module_completions( kind: Some(CompletionItemKind::CLASS), insert_text: Some(insert_text), // 给模块例化自动补全附上最高权重 - sort_text: Some("0001".to_string()), + sort_text: Some("0".to_string()), insert_text_format: Some(InsertTextFormat::SNIPPET), insert_text_mode: Some(InsertTextMode::ADJUST_INDENTATION), ..CompletionItem::default() diff --git a/src/core/scope_tree/common.rs b/src/core/scope_tree/common.rs index 7c0a9e9..c4651ee 100644 --- a/src/core/scope_tree/common.rs +++ b/src/core/scope_tree/common.rs @@ -4,7 +4,7 @@ use ropey::Rope; use tower_lsp::lsp_types::*; use vhdl_lang::Project; -use crate::sources::LSPSupport; +use crate::{sources::LSPSupport, utils::is_character_ordered_match}; /// cleanup the text of a definition so it can be included in completions pub fn clean_type_str(type_str: &str, ident: &str) -> String { @@ -122,14 +122,31 @@ pub trait Scope: std::fmt::Debug + Definition + Sync + Send { } } - // 自动补全时,忽略大小写 - let lower_case_token = token.to_lowercase(); - let completion_idents: Vec = completions.iter().map(|x| x.label.clone()).collect(); + // let completion_idents: Vec = completions.iter().map(|x| x.label.clone()).collect(); // 寻找前缀相同的 symbol - for def in self.defs() { - if !completion_idents.contains(&def.ident()) && def.ident().to_lowercase().starts_with(&lower_case_token) { - completions.push(def.completion()); + // 这里面并没有 macro + for symbol in self.defs() { + // 此处的去重会在外部完成 + let symbol_name = symbol.ident(); + // 此处仍然会给出 module 的补全,但是此处的只是名字的补全,而不是自动例化 + match &symbol.def_type() { + DefinitionType::Port => {}, + DefinitionType::Net => {}, + DefinitionType::Macro => { + // 对于 TextMacro 类型的,因为是全局属性的,不进行补全 + // 对于它的补全请参考 vlog_directives_completion & vlog_directives_completion_without_prefix + continue; + }, + DefinitionType::Data => {}, + DefinitionType::Modport => {}, + DefinitionType::Subroutine => {}, + DefinitionType::ModuleInstantiation => {}, + DefinitionType::GenericScope => {}, + DefinitionType::Class => {}, + }; + if is_character_ordered_match(token, &symbol_name) { + completions.push(symbol.completion()); } } // 寻找前缀相同的 scope @@ -142,42 +159,6 @@ pub trait Scope: std::fmt::Debug + Definition + Sync + Send { } - /// return a dot completion from the scope tree, this function should be called on the global - /// scope - fn get_dot_completion( - &self, - token: &str, - byte_idx: usize, - url: &Url, - scope_tree: &GenericScope, - ) -> Vec { - // first we need to go down the scope tree, to the scope the user is invoking a completion - // in - for scope in self.scopes() { - if &scope.url() == url && scope.start() <= byte_idx && byte_idx <= scope.end() { - let result = scope.get_dot_completion(token, byte_idx, url, scope_tree); - if !result.is_empty() { - return result; - } - } - } - // now that we are in the users scope, we can attempt to find the relevant definition - // we proceed back upwards through the scope tree, and if a definition matches our token, - // we invoke dot completion on that definition and pass it the syntax tree - for def in self.defs() { - if def.starts_with(token) { - return def.dot_completion(scope_tree); - } - } - for scope in self.scopes() { - if scope.starts_with(token) { - return scope.dot_completion(scope_tree); - } - } - Vec::new() - } - - /// 根据输入的 token,计算出这个 token 在 scope 中的定义 /// 比如输入 clock,则返回 clock 这个变量在哪里被定义,没有则返回 None /// - `token`: 需要查找定义的完整的单词 @@ -360,9 +341,14 @@ impl Definition for PortDec { self.ident.starts_with(token) } fn completion(&self) -> CompletionItem { + let label_details = CompletionItemLabelDetails { + description: Some("port desciption".to_string()), + ..Default::default() + }; CompletionItem { label: self.ident.clone(), detail: Some(clean_type_str(&self.type_str, &self.ident)), + label_details: Some(label_details), kind: Some(self.completion_kind), ..CompletionItem::default() } diff --git a/src/core/scope_tree/parse.rs b/src/core/scope_tree/parse.rs index 76b17e9..3d10caa 100644 --- a/src/core/scope_tree/parse.rs +++ b/src/core/scope_tree/parse.rs @@ -1,7 +1,9 @@ use super::common::*; use super::match_definitions; +#[allow(unused)] use log::info; + use sv_parser::*; use tower_lsp::lsp_types::*; diff --git a/src/diagnostics/vivado.rs b/src/diagnostics/vivado.rs index 801ca47..38288ad 100644 --- a/src/diagnostics/vivado.rs +++ b/src/diagnostics/vivado.rs @@ -71,6 +71,9 @@ impl AbstractLinterConfiguration for VivadoConfiguration { } }; + // vivado 比较特殊,需要先分析出当前文件用了哪些其他文件的宏,然后把那部分宏所在的文件加入编译参数中 + + let child = Command::new(&invoke_name) .current_dir(cwd) .stdin(Stdio::piped()) @@ -184,35 +187,9 @@ fn find_vivado_suitable_range( } -/// 过滤 vivado 给出的一些报错 -fn filter_diagnostic_result( - diagnostics: Vec, - server: &LspServer, - language_id: &str -) -> Vec { - match language_id { - // vhdl - "vhdl" => { - filter_xvhdl_diagnostic_result(diagnostics, server) - } - // vlog & svlog - _ => { - filter_xvlog_diagnostic_result(diagnostics, server) - } - } -} - - -fn filter_xvhdl_diagnostic_result( - diagnostics: Vec, - #[allow(unused)] - server: &LspServer, -) -> Vec { - diagnostics -} - /// 判断是否为类似于 xxx ignored 的错误 /// ERROR: [VRFC 10-8530] module 'main' is ignored due to previous errors [/home/dide/project/Digital-Test/Digital-macro/user/src/main.v:1] +#[allow(unused)] fn is_ignore_type(diag: &Diagnostic) -> bool { // 获取 vrfc 编码 let vrfc_code = if let Some(NumberOrString::String(code)) = &diag.code { @@ -231,19 +208,3 @@ fn is_ignore_type(diag: &Diagnostic) -> bool { } } } - -fn filter_xvlog_diagnostic_result( - diagnostics: Vec, - #[allow(unused)] - server: &LspServer, -) -> Vec { - // 第一级过滤, 去除所有的 ignore 类型的 - let diagnostics = diagnostics.into_iter().filter(|diag| !is_ignore_type(diag)).collect(); - - - // 第二级过滤, 对于 xxx not found, 需要先根据 fast 查看是否存在, 如果存在,还需要把同一行的某些特定错误一并去除 - - - - diagnostics -} \ No newline at end of file diff --git a/src/sources.rs b/src/sources.rs index 2557df2..9de09dc 100644 --- a/src/sources.rs +++ b/src/sources.rs @@ -465,7 +465,6 @@ impl Sources { byte_idx: usize, url: &Url, ) -> Option { - debug!("retrieving identifier completion for token: {}", &token); Some(CompletionList { is_incomplete: false, items: self @@ -477,22 +476,6 @@ impl Sources { }) } - /// compute dot completions - pub fn get_dot_completions( - &self, - token: &str, - byte_idx: usize, - url: &Url, - ) -> Option { - debug!("retrieving dot completion for token: {}", &token); - let tree = self.scope_tree.read().ok()?; - Some(CompletionList { - is_incomplete: false, - items: tree - .as_ref()? - .get_dot_completion(token, byte_idx, url, tree.as_ref()?), - }) - } #[allow(unused)] pub fn get_lsp_configuration_string_value(&self, name: &str) -> Option {