更新 directives
This commit is contained in:
parent
aad333783e
commit
1090face1e
419
src/completion/directives.rs
Normal file
419
src/completion/directives.rs
Normal file
@ -0,0 +1,419 @@
|
|||||||
|
use tower_lsp::lsp_types::*;
|
||||||
|
|
||||||
|
/// 文档:IEEE 1364-2005
|
||||||
|
/// author: LSTM-Kirigaya
|
||||||
|
/// date: 2024.12.13
|
||||||
|
|
||||||
|
pub const VLOG_DIRECTIVES: &[(&str, &str, &str)] = &[
|
||||||
|
(
|
||||||
|
"__FILE__",
|
||||||
|
"`__FILE__",
|
||||||
|
r#"用于获取当前文件名
|
||||||
|
```verilog
|
||||||
|
// 文件名: /path/to/your/project/test.v
|
||||||
|
`timescale 1ns/1ps
|
||||||
|
|
||||||
|
module test;
|
||||||
|
initial begin
|
||||||
|
// 输出 当前文件名:/path/to/your/project/test.v
|
||||||
|
$display("当前文件名: %s", `__FILE__);
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
```
|
||||||
|
"#),
|
||||||
|
(
|
||||||
|
"__LINE__",
|
||||||
|
"`__LINE__",
|
||||||
|
r#"用于获取当前行号
|
||||||
|
```verilog
|
||||||
|
// 文件名: /path/to/your/project/test.v
|
||||||
|
`timescale 1ns/1ps
|
||||||
|
|
||||||
|
module test;
|
||||||
|
initial begin
|
||||||
|
// 使用 __FILE__ 和 __LINE__ 宏输出当前文件名和行号
|
||||||
|
$display("当前文件名: %s, 当前行号: %0d", `__FILE__, `__LINE__);
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
```
|
||||||
|
"#),
|
||||||
|
(
|
||||||
|
"begin_keywords",
|
||||||
|
"`begin_keywords\n$1\n`end_keywords ",
|
||||||
|
r#"`begin_keywords` 和 `end_keywords` 是用于指定 Verilog 语言版本的编译指令。它们允许设计者在同一个文件中使用不同版本的 Verilog 语法,从而实现兼容性或逐步迁移到新版本。
|
||||||
|
|
||||||
|
`begin_keywords` 支持以下 Verilog 版本:
|
||||||
|
|
||||||
|
- `1364-1995`:Verilog-1995 标准。
|
||||||
|
- `1364-2001`:Verilog-2001 标准。
|
||||||
|
- `1364-2005`:Verilog-2005 标准。
|
||||||
|
- `1800-2009`:SystemVerilog-2009 标准。
|
||||||
|
- `1800-2012`:SystemVerilog-2012 标准。
|
||||||
|
|
||||||
|
```verilog
|
||||||
|
// 使用 begin_keywords 和 end_keywords 指定 Verilog 版本
|
||||||
|
`begin_keywords "1364-2001" // 指定 Verilog-2001 语法
|
||||||
|
|
||||||
|
module my_module;
|
||||||
|
reg [7:0] data;
|
||||||
|
initial begin
|
||||||
|
data = 8'hFF; // 使用 Verilog-2001 的语法
|
||||||
|
$display("Verilog-2001 语法: data = %h", data);
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`end_keywords // 结束 Verilog-2001 语法
|
||||||
|
|
||||||
|
// 恢复默认的 Verilog 语法
|
||||||
|
module another_module;
|
||||||
|
reg [7:0] data;
|
||||||
|
initial begin
|
||||||
|
data = 8'hAA; // 使用默认的 Verilog 语法
|
||||||
|
$display("默认语法: data = %h", data);
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
```
|
||||||
|
"#),
|
||||||
|
(
|
||||||
|
"celldefine",
|
||||||
|
"`celldefine\n$1\n`endcelldefine",
|
||||||
|
r#"开始定义单元格
|
||||||
|
`celldefine` 和 `endcelldefine` 是用于定义单元库模块的编译指令。它们通常用于定义可重用的硬件模块(如标准单元库),并控制这些模块的编译行为。
|
||||||
|
```verilog
|
||||||
|
// 使用 celldefine 和 endcelldefine 定义一个单元库模块
|
||||||
|
`celldefine
|
||||||
|
module my_cell (
|
||||||
|
input a,
|
||||||
|
input b,
|
||||||
|
output out
|
||||||
|
);
|
||||||
|
assign out = a & b; // 简单的与门逻辑
|
||||||
|
endmodule
|
||||||
|
`endcelldefine
|
||||||
|
|
||||||
|
// 测试模块
|
||||||
|
module test;
|
||||||
|
reg a, b;
|
||||||
|
wire out;
|
||||||
|
|
||||||
|
// 实例化单元库模块
|
||||||
|
my_cell uut (
|
||||||
|
.a(a),
|
||||||
|
.b(b),
|
||||||
|
.out(out)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// 初始化输入
|
||||||
|
a = 0;
|
||||||
|
b = 0;
|
||||||
|
|
||||||
|
// 仿真逻辑
|
||||||
|
#10;
|
||||||
|
a = 1;
|
||||||
|
#10;
|
||||||
|
b = 1;
|
||||||
|
#10;
|
||||||
|
$display("输出结果: %b", out);
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
```
|
||||||
|
|
||||||
|
使用 `celldefine` 的优势:
|
||||||
|
- 编译器可以将 `celldefine` 模块视为标准单元库的一部分,从而进行更高效的编译优化。例如,编译器可以提前处理这些模块的逻辑,减少仿真时的计算开销。
|
||||||
|
- 在大型设计中,标准单元库模块可能会被多次实例化。使用 celldefine 可以避免重复编译相同的模块,从而减少编译时间和内存占用。
|
||||||
|
"#),
|
||||||
|
(
|
||||||
|
"default_nettype",
|
||||||
|
"`default_nettype $1",
|
||||||
|
"设置默认的网络类型"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"define",
|
||||||
|
"`define $1 $2",
|
||||||
|
r#"定义一个宏
|
||||||
|
|
||||||
|
### 语法
|
||||||
|
|
||||||
|
```verilog
|
||||||
|
`define MACRO_NAME value
|
||||||
|
```
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```verilog
|
||||||
|
// 使用 `define 定义常量和代码片段
|
||||||
|
`define PORT_NUM 8 // 定义常量 PORT_NUM 为 8
|
||||||
|
`define ADD_ONE(x) (x + 1) // 定义带参数的宏 ADD_ONE
|
||||||
|
|
||||||
|
module test;
|
||||||
|
reg [(`PORT_NUM - 1):0] data; // 使用常量 PORT_NUM
|
||||||
|
integer value;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// 使用宏 ADD_ONE
|
||||||
|
value = 5;
|
||||||
|
$display("原始值: %0d", value);
|
||||||
|
value = `ADD_ONE(value);
|
||||||
|
$display("加一后的值: %0d", value);
|
||||||
|
|
||||||
|
// 使用常量 PORT_NUM
|
||||||
|
data = 8'hFF;
|
||||||
|
$display("数据宽度: %0d 位", `PORT_NUM);
|
||||||
|
$display("数据值: %h", data);
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
```
|
||||||
|
"#),
|
||||||
|
(
|
||||||
|
"else",
|
||||||
|
"`else",
|
||||||
|
"条件编译的 else 分支"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"elsif",
|
||||||
|
"`elsif $1",
|
||||||
|
"条件编译的 elsif 分支"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"end_keywords",
|
||||||
|
"`end_keywords",
|
||||||
|
"结束关键字版本指定"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"endcelldefine",
|
||||||
|
"`endcelldefine",
|
||||||
|
"结束单元格定义"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"endif",
|
||||||
|
"`endif",
|
||||||
|
"结束条件编译"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ifdef",
|
||||||
|
"`ifdef $1\n\t//ifdef\n\t$2\n`else\n//else\n\t$3\n`endif",
|
||||||
|
r#"ifdef、else 和 endif 是条件编译指令,用于根据宏定义的存在与否来选择性地编译代码。它们通常用于实现条件编译逻辑,以便在不同的编译环境下生成不同的代码。
|
||||||
|
|
||||||
|
### 语法
|
||||||
|
|
||||||
|
```verilog
|
||||||
|
`ifdef MACRO_NAME
|
||||||
|
// 如果 MACRO_NAME 已定义,编译此段代码
|
||||||
|
`else
|
||||||
|
// 如果 MACRO_NAME 未定义,编译此段代码
|
||||||
|
`endif
|
||||||
|
```
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```verilog
|
||||||
|
// 使用 `ifdef 和 `else 进行条件编译
|
||||||
|
`define DEBUG // 定义 DEBUG 宏
|
||||||
|
|
||||||
|
module test;
|
||||||
|
reg [7:0] data;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
data = 8'hFF;
|
||||||
|
|
||||||
|
// 使用 `ifdef 和 `else 进行条件编译
|
||||||
|
`ifdef DEBUG
|
||||||
|
$display("调试模式: 数据值 = %h", data);
|
||||||
|
`else
|
||||||
|
$display("发布模式: 数据值 = %h", data);
|
||||||
|
`endif
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
```
|
||||||
|
|
||||||
|
假设上述代码保存在文件 test.v 中,仿真输出可能如下:
|
||||||
|
|
||||||
|
```
|
||||||
|
调试模式: 数据值 = FF
|
||||||
|
```
|
||||||
|
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ifndef",
|
||||||
|
"`ifndef $1",
|
||||||
|
"如果未定义宏,则编译代码"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"include",
|
||||||
|
"`include $1",
|
||||||
|
"包含一个外部文件"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"line",
|
||||||
|
"`line $1 $2 $3",
|
||||||
|
r#"`line` 用于指定当前代码的行号和文件名。它通常用于调试或日志记录,以便在仿真或编译时能够追踪代码的来源。
|
||||||
|
|
||||||
|
### 语法
|
||||||
|
```verilog
|
||||||
|
`line line_number "filename" level
|
||||||
|
```
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
```verilog
|
||||||
|
// 使用 `line 指令指定行号和文件名
|
||||||
|
`line 10 "example.v" 0
|
||||||
|
|
||||||
|
module test;
|
||||||
|
initial begin
|
||||||
|
$display("当前行号: %0d", `__LINE__);
|
||||||
|
$display("当前文件名: %s", `__FILE__);
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
```
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"unconnected_drive",
|
||||||
|
"`unconnected_drive ${1:pull1}\n$2\n`nounconnected_drive\n",
|
||||||
|
r#"`nounconnected_drive` 和 `unconnected_drive` 是配合使用的编译指令,用于控制未连接端口的驱动行为。它们通常成对出现,分别用于禁用和启用未连接端口的驱动处理。
|
||||||
|
### 语法
|
||||||
|
```verilog
|
||||||
|
`unconnected_drive (pull1 | pull0) // 启用未连接端口的驱动,若为 pull1,则默认驱动为高电平,若为 pull0,则默认为低电平
|
||||||
|
// 你的 verilog 代码
|
||||||
|
`nounconnected_drive // 禁用未连接端口的驱动
|
||||||
|
```
|
||||||
|
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"nounconnected_drive",
|
||||||
|
"`nounconnected_drive",
|
||||||
|
r#"`nounconnected_drive` 和 `unconnected_drive` 是配合使用的编译指令,用于控制未连接端口的驱动行为。它们通常成对出现,分别用于禁用和启用未连接端口的驱动处理。
|
||||||
|
### 语法
|
||||||
|
```verilog
|
||||||
|
`unconnected_drive (pull1 | pull0) // 启用未连接端口的驱动,若为 pull1,则默认驱动为高电平,若为 pull0,则默认为低电平
|
||||||
|
// 你的 verilog 代码
|
||||||
|
`nounconnected_drive // 禁用未连接端口的驱动
|
||||||
|
```
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"pragma",
|
||||||
|
"`pragma $1",
|
||||||
|
"编译指示,用于传递编译器指令"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"resetall",
|
||||||
|
"`resetall",
|
||||||
|
r#"`resetall` 用于重置所有编译器设置为默认值。它通常用于在模块或文件的末尾清除所有编译器设置,以确保后续代码不受之前设置的影响。
|
||||||
|
|
||||||
|
```verilog
|
||||||
|
`timescale 1ns/1ps // 设置时间单位和精度
|
||||||
|
|
||||||
|
module test;
|
||||||
|
// 一些 verilog 代码
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`resetall // 重置所有编译器设置,上文的 timescale 设置自此开始无效
|
||||||
|
```
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"timescale",
|
||||||
|
"`timescale ${1:1ns}/${2:1ps}",
|
||||||
|
r#"设置时间单位和精度,设置时间单位和精度,格式为 <code> `timescale </code> 仿真时间单位/时间精度,<code>仿真时间单位</code> 必须大于 <code>时间精度</code>,例如
|
||||||
|
```verilog
|
||||||
|
`timescale 1ns/1ps
|
||||||
|
|
||||||
|
module test;
|
||||||
|
initial begin
|
||||||
|
$display("当前时间单位: %0t", $time); // 输出当前时间
|
||||||
|
#10; // 延迟 10 纳秒
|
||||||
|
$display("延迟 10 纳秒后的时间: %0t", $time);
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
```
|
||||||
|
如果延迟是 #10.5,仿真器会将其解释为 10.5 纳秒,但精度会精确到皮秒级别。
|
||||||
|
|
||||||
|
在编译过程中,`timescale` 指令影响这一编译器指令后面所有模块中的时延值,直至遇到另一个 `timescale` 指令 `resetall` 指令。
|
||||||
|
"#),
|
||||||
|
(
|
||||||
|
"undef",
|
||||||
|
"`undef $1",
|
||||||
|
"取消定义一个宏"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"undefineall",
|
||||||
|
"`undefineall",
|
||||||
|
"取消定义所有宏"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"default_decay_time",
|
||||||
|
"`default_decay_time $1",
|
||||||
|
r#"`default_decay_time` 用于设置电荷衰减时间(decay time)的默认值。它通常用于模拟电荷存储元件(如电容或寄生电容)的行为。
|
||||||
|
|
||||||
|
### 语法
|
||||||
|
```verilog
|
||||||
|
`default_decay_time time_value
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"default_trireg_strength",
|
||||||
|
"`default_trireg_strength $1",
|
||||||
|
r#"`default_trireg_strength ` 用于设置三态寄存器(trireg)的默认驱动强度(strength)。三态寄存器是一种特殊的寄存器,可以存储电荷,并且在未被驱动时会衰减。"#
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"delay_mode_distributed",
|
||||||
|
"`delay_mode_distributed",
|
||||||
|
r#"`delay_mode_distributed` 用于设置延迟模式的类型。它通常用于控制逻辑门和网络的延迟分布方式。"#
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"delay_mode_path",
|
||||||
|
"`delay_mode_path",
|
||||||
|
r#"`delay_mode_path` 用于设置延迟模式的类型。它通常用于控制路径延迟(path delay)的计算方式,特别是在时序逻辑电路中。"#
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"delay_mode_unit",
|
||||||
|
"`delay_mode_unit",
|
||||||
|
r#"`delay_mode_unit` 用于设置延迟模式的类型。它通常用于控制逻辑门和网络的延迟计算方式,特别是在仿真中需要精确控制延迟时。"#
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"delay_mode_zero",
|
||||||
|
"`delay_mode_zero",
|
||||||
|
r#"`delay_mode_zero` 用于设置延迟模式的类型。它通常用于控制逻辑门和网络的延迟计算方式,特别是在仿真中需要忽略延迟时。"#
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn make_function_profile(
|
||||||
|
description: &str
|
||||||
|
) -> MarkupContent {
|
||||||
|
MarkupContent {
|
||||||
|
kind: MarkupKind::Markdown,
|
||||||
|
value: format!("{}", description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn provide_vlog_directives_completions() -> Vec<CompletionItem> {
|
||||||
|
let mut completion_items: Vec<CompletionItem> = Vec::new();
|
||||||
|
|
||||||
|
for (label, snippet_code, description) in VLOG_DIRECTIVES {
|
||||||
|
let function_profile = make_function_profile(description);
|
||||||
|
let label_details = CompletionItemLabelDetails {
|
||||||
|
description: Some("directive".to_string()),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
completion_items.push(CompletionItem {
|
||||||
|
label: label.to_string(),
|
||||||
|
detail: Some("directive".to_string()),
|
||||||
|
label_details: Some(label_details),
|
||||||
|
documentation: Some(Documentation::MarkupContent(function_profile)),
|
||||||
|
kind: Some(CompletionItemKind::FUNCTION),
|
||||||
|
insert_text: Some(snippet_code.to_string()),
|
||||||
|
insert_text_format: Some(InsertTextFormat::SNIPPET),
|
||||||
|
insert_text_mode: Some(InsertTextMode::ADJUST_INDENTATION),
|
||||||
|
..CompletionItem::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
completion_items
|
||||||
|
}
|
@ -125,7 +125,7 @@ pub fn vlog_directives_completion(
|
|||||||
};
|
};
|
||||||
let documentation = Documentation::MarkupContent(MarkupContent {
|
let documentation = Documentation::MarkupContent(MarkupContent {
|
||||||
kind: tower_lsp::lsp_types::MarkupKind::Markdown,
|
kind: tower_lsp::lsp_types::MarkupKind::Markdown,
|
||||||
value: format!("```verilog\n`define {} {}\n```", define.name, define.replacement)
|
value: format!("```verilog\n`define {} {}\n```", define.name.trim(), define.replacement.trim())
|
||||||
});
|
});
|
||||||
completion_items.push(CompletionItem {
|
completion_items.push(CompletionItem {
|
||||||
label: define.name.to_string(),
|
label: define.name.to_string(),
|
||||||
@ -169,7 +169,7 @@ pub fn vlog_directives_completion_without_prefix(
|
|||||||
};
|
};
|
||||||
let documentation = Documentation::MarkupContent(MarkupContent {
|
let documentation = Documentation::MarkupContent(MarkupContent {
|
||||||
kind: tower_lsp::lsp_types::MarkupKind::Markdown,
|
kind: tower_lsp::lsp_types::MarkupKind::Markdown,
|
||||||
value: format!("```verilog\n`define {} {}\n```", define.name, define.replacement)
|
value: format!("```verilog\n`define {} {}\n```", define.name.trim(), define.replacement.trim())
|
||||||
});
|
});
|
||||||
completion_items.push(CompletionItem {
|
completion_items.push(CompletionItem {
|
||||||
label: define.name.to_string(),
|
label: define.name.to_string(),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
|
|
||||||
|
|
||||||
pub fn keyword_completions(keywords: &[(&str, &str)]) -> Vec<CompletionItem> {
|
pub fn provide_keyword_completions(keywords: &[(&str, &str)]) -> Vec<CompletionItem> {
|
||||||
let mut items: Vec<CompletionItem> = Vec::new();
|
let mut items: Vec<CompletionItem> = Vec::new();
|
||||||
for key in keywords {
|
for key in keywords {
|
||||||
let label_details = CompletionItemLabelDetails {
|
let label_details = CompletionItemLabelDetails {
|
||||||
@ -29,17 +29,6 @@ pub fn keyword_completions(keywords: &[(&str, &str)]) -> Vec<CompletionItem> {
|
|||||||
items
|
items
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn other_completions(tasks: &[&str]) -> Vec<CompletionItem> {
|
|
||||||
tasks
|
|
||||||
.iter()
|
|
||||||
.map(|x| CompletionItem {
|
|
||||||
label: x.to_string(),
|
|
||||||
kind: Some(CompletionItemKind::FUNCTION),
|
|
||||||
..CompletionItem::default()
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// (&str, &str, &str): (label, snippet, description)
|
/// (&str, &str, &str): (label, snippet, description)
|
||||||
pub const VLOG_KEYWORDS: &[(&str, &str)] = &[
|
pub const VLOG_KEYWORDS: &[(&str, &str)] = &[
|
||||||
("accept_on", ""),
|
("accept_on", ""),
|
||||||
@ -292,37 +281,6 @@ pub const VLOG_KEYWORDS: &[(&str, &str)] = &[
|
|||||||
("xor", ""),
|
("xor", ""),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub const DIRECTIVES: &[&str] = &[
|
|
||||||
"__FILE__",
|
|
||||||
"__LINE__",
|
|
||||||
"begin_keywords",
|
|
||||||
"celldefine",
|
|
||||||
"default_nettype",
|
|
||||||
"define",
|
|
||||||
"else",
|
|
||||||
"elsif",
|
|
||||||
"end_keywords",
|
|
||||||
"endcelldefine",
|
|
||||||
"endif",
|
|
||||||
"ifdef",
|
|
||||||
"ifndef",
|
|
||||||
"include",
|
|
||||||
"line",
|
|
||||||
"nounconnected_drive",
|
|
||||||
"pragma",
|
|
||||||
"resetall",
|
|
||||||
"timescale",
|
|
||||||
"unconnected_drive",
|
|
||||||
"undef",
|
|
||||||
"undefineall",
|
|
||||||
"default_decay_time",
|
|
||||||
"default_trireg_strength",
|
|
||||||
"delay_mode_distributed",
|
|
||||||
"delay_mode_path",
|
|
||||||
"delay_mode_unit",
|
|
||||||
"delay_mode_zero",
|
|
||||||
];
|
|
||||||
|
|
||||||
pub const VHDL_KEYWORDS: &[(&str, &str)] = &[
|
pub const VHDL_KEYWORDS: &[(&str, &str)] = &[
|
||||||
("abs", ""),
|
("abs", ""),
|
||||||
("access", ""),
|
("access", ""),
|
||||||
|
@ -4,6 +4,7 @@ use tower_lsp::lsp_types::*;
|
|||||||
pub mod keyword;
|
pub mod keyword;
|
||||||
pub mod feature;
|
pub mod feature;
|
||||||
pub mod sys_tasks;
|
pub mod sys_tasks;
|
||||||
|
pub mod directives;
|
||||||
|
|
||||||
pub use sys_tasks::provide_vlog_sys_tasks_completions;
|
pub use sys_tasks::provide_vlog_sys_tasks_completions;
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
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 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}};
|
||||||
|
#[allow(unused)]
|
||||||
use log::info;
|
use log::info;
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ impl CacheManager {
|
|||||||
|
|
||||||
fn check_dir(dir: &PathBuf) {
|
fn check_dir(dir: &PathBuf) {
|
||||||
if !dir.exists() {
|
if !dir.exists() {
|
||||||
fs::create_dir_all(dir);
|
let _ = fs::create_dir_all(dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,6 +118,7 @@ impl CacheManager {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn uri_is_big_file(uri: &Url) -> bool {
|
pub fn uri_is_big_file(uri: &Url) -> bool {
|
||||||
let path = PathBuf::from_str(uri.path()).unwrap();
|
let path = PathBuf::from_str(uri.path()).unwrap();
|
||||||
let path = to_escape_path(&path);
|
let path = to_escape_path(&path);
|
||||||
|
@ -65,9 +65,23 @@ pub fn copy_scopes(scopes: &[Box<dyn Scope>]) -> Vec<Box<dyn Scope>> {
|
|||||||
scope_decs
|
scope_decs
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 用于定义一个 Symbol 或者 Scope 的内部变量
|
/// Definition 是所有非 scope 类型 symbol 的父类
|
||||||
pub trait Definition: std::fmt::Debug + Sync + Send {
|
pub trait Definition: std::fmt::Debug + Sync + Send {
|
||||||
/// symbol 或者 scope 的名字,identity 的缩写
|
/// symbol 或者 scope 的名字,identity 的缩写
|
||||||
|
///
|
||||||
|
/// 对于 definition,而言 ident 就是它的字面量,比如
|
||||||
|
/// ```verilog
|
||||||
|
/// parameter wire_size = 12;
|
||||||
|
/// ```
|
||||||
|
/// 上面的 `wire_size` 这个 symbol 的 name 就是 `wire_size`
|
||||||
|
///
|
||||||
|
/// 对于 scope 而言
|
||||||
|
/// ```verilog
|
||||||
|
/// module beginner();
|
||||||
|
/// adwadwa
|
||||||
|
/// endmodule
|
||||||
|
/// 上面这个 module scope 的 ident 就是 `beginner`
|
||||||
|
/// ```
|
||||||
fn ident(&self) -> String;
|
fn ident(&self) -> String;
|
||||||
/// 相对于文本的偏移量,可以利用 Rope 的 `byte_to_pos` 函数转换成 Position
|
/// 相对于文本的偏移量,可以利用 Rope 的 `byte_to_pos` 函数转换成 Position
|
||||||
fn byte_idx(&self) -> usize;
|
fn byte_idx(&self) -> usize;
|
||||||
@ -85,9 +99,9 @@ pub trait Definition: std::fmt::Debug + Sync + Send {
|
|||||||
fn starts_with(&self, token: &str) -> bool;
|
fn starts_with(&self, token: &str) -> bool;
|
||||||
/// 构造 completion 的 item
|
/// 构造 completion 的 item
|
||||||
fn completion(&self) -> CompletionItem;
|
fn completion(&self) -> CompletionItem;
|
||||||
fn dot_completion(&self, scope_tree: &GenericScope) -> Vec<CompletionItem>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Scope 是所有 scope 类型 symbol 的父类
|
||||||
pub trait Scope: std::fmt::Debug + Definition + Sync + Send {
|
pub trait Scope: std::fmt::Debug + Definition + Sync + Send {
|
||||||
// the start byte of this scope
|
// the start byte of this scope
|
||||||
fn start(&self) -> usize;
|
fn start(&self) -> usize;
|
||||||
@ -342,7 +356,7 @@ impl Definition for PortDec {
|
|||||||
}
|
}
|
||||||
fn completion(&self) -> CompletionItem {
|
fn completion(&self) -> CompletionItem {
|
||||||
let label_details = CompletionItemLabelDetails {
|
let label_details = CompletionItemLabelDetails {
|
||||||
description: Some("port desciption".to_string()),
|
description: Some("module port".to_string()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
CompletionItem {
|
CompletionItem {
|
||||||
@ -353,31 +367,6 @@ impl Definition for PortDec {
|
|||||||
..CompletionItem::default()
|
..CompletionItem::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn dot_completion(&self, scope_tree: &GenericScope) -> Vec<CompletionItem> {
|
|
||||||
for scope in &scope_tree.scopes {
|
|
||||||
if let Some(interface) = &self.interface {
|
|
||||||
if &scope.ident() == interface {
|
|
||||||
return match &self.modport {
|
|
||||||
Some(modport) => {
|
|
||||||
for def in scope.defs() {
|
|
||||||
if def.starts_with(modport) {
|
|
||||||
return def.dot_completion(scope_tree);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
None => scope
|
|
||||||
.defs()
|
|
||||||
.iter()
|
|
||||||
.filter(|x| !x.starts_with(&scope.ident()))
|
|
||||||
.map(|x| x.completion())
|
|
||||||
.collect(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -439,9 +428,6 @@ impl Definition for GenericDec {
|
|||||||
..CompletionItem::default()
|
..CompletionItem::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn dot_completion(&self, _: &GenericScope) -> Vec<CompletionItem> {
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -506,9 +492,6 @@ impl Definition for PackageImport {
|
|||||||
..CompletionItem::default()
|
..CompletionItem::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn dot_completion(&self, _: &GenericScope) -> Vec<CompletionItem> {
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -577,9 +560,6 @@ impl Definition for SubDec {
|
|||||||
..CompletionItem::default()
|
..CompletionItem::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn dot_completion(&self, _: &GenericScope) -> Vec<CompletionItem> {
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scope for SubDec {
|
impl Scope for SubDec {
|
||||||
@ -659,9 +639,6 @@ impl Definition for ModportDec {
|
|||||||
..CompletionItem::default()
|
..CompletionItem::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn dot_completion(&self, _: &GenericScope) -> Vec<CompletionItem> {
|
|
||||||
self.ports.iter().map(|x| x.completion()).collect()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -724,19 +701,6 @@ impl Definition for ModInst {
|
|||||||
..CompletionItem::default()
|
..CompletionItem::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn dot_completion(&self, scope_tree: &GenericScope) -> Vec<CompletionItem> {
|
|
||||||
for scope in &scope_tree.scopes {
|
|
||||||
if scope.ident() == self.mod_ident {
|
|
||||||
return scope
|
|
||||||
.defs()
|
|
||||||
.iter()
|
|
||||||
.filter(|x| !x.starts_with(&scope.ident()))
|
|
||||||
.map(|x| x.completion())
|
|
||||||
.collect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VhdlProject {
|
pub struct VhdlProject {
|
||||||
@ -811,19 +775,6 @@ impl Definition for GenericScope {
|
|||||||
..CompletionItem::default()
|
..CompletionItem::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn dot_completion(&self, scope_tree: &GenericScope) -> Vec<CompletionItem> {
|
|
||||||
for scope in scope_tree.scopes() {
|
|
||||||
if scope.ident() == self.ident {
|
|
||||||
return scope
|
|
||||||
.defs()
|
|
||||||
.iter()
|
|
||||||
.filter(|x| !x.starts_with(&scope.ident()))
|
|
||||||
.map(|x| x.completion())
|
|
||||||
.collect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scope for GenericScope {
|
impl Scope for GenericScope {
|
||||||
@ -916,19 +867,6 @@ impl Definition for ClassDec {
|
|||||||
..CompletionItem::default()
|
..CompletionItem::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn dot_completion(&self, scope_tree: &GenericScope) -> Vec<CompletionItem> {
|
|
||||||
for scope in scope_tree.scopes() {
|
|
||||||
if scope.ident() == self.ident {
|
|
||||||
return scope
|
|
||||||
.defs()
|
|
||||||
.iter()
|
|
||||||
.filter(|x| !x.starts_with(&scope.ident()))
|
|
||||||
.map(|x| x.completion())
|
|
||||||
.collect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scope for ClassDec {
|
impl Scope for ClassDec {
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
use super::common::*;
|
use super::common::*;
|
||||||
use super::match_definitions;
|
use super::match_definitions;
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use sv_parser::*;
|
use sv_parser::*;
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
|
|
||||||
@ -2347,7 +2345,7 @@ pub fn text_macro_def(
|
|||||||
let ident = get_ident(tree, RefNode::TextMacroIdentifier(&node.nodes.2.nodes.0));
|
let ident = get_ident(tree, RefNode::TextMacroIdentifier(&node.nodes.2.nodes.0));
|
||||||
text_macro.ident = ident.0;
|
text_macro.ident = ident.0;
|
||||||
text_macro.byte_idx = ident.1;
|
text_macro.byte_idx = ident.1;
|
||||||
let type_str = &mut text_macro.type_str;
|
let mut type_str = &mut text_macro.type_str;
|
||||||
|
|
||||||
advance_until_enter!(
|
advance_until_enter!(
|
||||||
type_str,
|
type_str,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::server::LspServer;
|
use crate::server::LspServer;
|
||||||
use crate::sources::LSPSupport;
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use ropey::Rope;
|
use ropey::Rope;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::{borrow::Cow, sync::Arc};
|
use std::{borrow::Cow, sync::Arc};
|
||||||
use std::future;
|
use std::future;
|
||||||
|
#[allow(unused)]
|
||||||
use log::info;
|
use log::info;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tower_lsp::jsonrpc::Result;
|
use tower_lsp::jsonrpc::Result;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::future;
|
use std::future;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
#[allow(unused)]
|
||||||
use log::info;
|
use log::info;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tower_lsp::jsonrpc::Result;
|
use tower_lsp::jsonrpc::Result;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
use crate::completion::directives::provide_vlog_directives_completions;
|
||||||
use crate::core::cache_storage::CacheManager;
|
use crate::core::cache_storage::CacheManager;
|
||||||
use crate::diagnostics::{DigitalLinterConfiguration, DigitalLinterMode, ModelsimConfiguration, VeribleConfiguration, VerilatorConfiguration, VivadoConfiguration};
|
use crate::diagnostics::{DigitalLinterConfiguration, DigitalLinterMode};
|
||||||
use crate::sources::*;
|
use crate::sources::*;
|
||||||
use crate::completion::{keyword::*, provide_vlog_sys_tasks_completions};
|
use crate::completion::{keyword::*, provide_vlog_sys_tasks_completions};
|
||||||
use flexi_logger::LoggerHandle;
|
use flexi_logger::LoggerHandle;
|
||||||
@ -38,10 +39,10 @@ impl LspServer {
|
|||||||
LspServer {
|
LspServer {
|
||||||
srcs: Sources::new(),
|
srcs: Sources::new(),
|
||||||
cache: CacheManager::new(dide_home),
|
cache: CacheManager::new(dide_home),
|
||||||
vlog_keyword_completion_items: keyword_completions(VLOG_KEYWORDS),
|
vlog_keyword_completion_items: provide_keyword_completions(VLOG_KEYWORDS),
|
||||||
vhdl_keyword_completiom_items: keyword_completions(VHDL_KEYWORDS),
|
vhdl_keyword_completiom_items: provide_keyword_completions(VHDL_KEYWORDS),
|
||||||
vlog_sys_tasks_completion_items: provide_vlog_sys_tasks_completions(),
|
vlog_sys_tasks_completion_items: provide_vlog_sys_tasks_completions(),
|
||||||
vlog_directives: other_completions(DIRECTIVES),
|
vlog_directives: provide_vlog_directives_completions(),
|
||||||
configuration: Arc::new(RwLock::new(LspConfiguration::default())),
|
configuration: Arc::new(RwLock::new(LspConfiguration::default())),
|
||||||
log_handle: Mutex::new(log_handle),
|
log_handle: Mutex::new(log_handle),
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user