加入 codedoc 部分
This commit is contained in:
parent
3d91cd1ee3
commit
10fbbd8843
2
src/codedoc/mod.rs
Normal file
2
src/codedoc/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod vlog;
|
||||
pub mod vhdl;
|
137
src/codedoc/vhdl.rs
Normal file
137
src/codedoc/vhdl.rs
Normal file
@ -0,0 +1,137 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use ropey::Rope;
|
||||
use sv_parser::{RefNode, SyntaxTree};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use crate::core::sv_parser::{get_identifier, get_position};
|
||||
|
||||
struct CommentSymbol {
|
||||
comment_string: String,
|
||||
start_pos: crate::core::hdlparam::Position,
|
||||
end_pos: crate::core::hdlparam::Position
|
||||
}
|
||||
|
||||
pub fn get_comments_from_ast(doc: &Rope, syntax_tree: &SyntaxTree) {
|
||||
// 创造一个收容 comment 的栈,对连续的注释进行合并
|
||||
let mut comments = Vec::<CommentSymbol>::new();
|
||||
|
||||
for node in syntax_tree {
|
||||
match node {
|
||||
RefNode::Comment(x) => {
|
||||
let locate = x.nodes.0;
|
||||
let comment_string = syntax_tree.get_str(&locate).unwrap();
|
||||
let start_pos = get_position(doc, locate, 0);
|
||||
let end_pos = get_position(doc, locate, locate.len);
|
||||
|
||||
println!("{:?}", comment_string);
|
||||
println!("start {:?}", start_pos);
|
||||
println!("end {:?}", end_pos);
|
||||
|
||||
|
||||
|
||||
if let Some(mut last_comment) = comments.last_mut() {
|
||||
// 判断是否需要合并
|
||||
let last_end_line = last_comment.end_pos.line;
|
||||
let current_start_line = start_pos.line;
|
||||
}
|
||||
|
||||
// 否则,直接加入
|
||||
comments.push(CommentSymbol {
|
||||
comment_string: comment_string.to_string(),
|
||||
start_pos, end_pos
|
||||
});
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 解析第一行 tag
|
||||
/// /* @meta
|
||||
/// *
|
||||
/// */
|
||||
///
|
||||
/// /* @module
|
||||
/// *
|
||||
/// */
|
||||
///
|
||||
/// /* @wavedrom xxx
|
||||
/// *
|
||||
/// */
|
||||
///
|
||||
/// 或者压根儿没有
|
||||
/// /*
|
||||
/// *
|
||||
/// */
|
||||
fn parse_first_line_tag(comment: &str) {
|
||||
|
||||
}
|
||||
|
||||
/// 解析不同的注释块
|
||||
fn codedoc_parse_pipeline(comment: &str) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
fn parse_c_style_comment(comment: &str) -> Result<Value, String> {
|
||||
let mut result = HashMap::new();
|
||||
let mut revision_vec = Vec::new();
|
||||
let mut in_revision = false;
|
||||
|
||||
for line in comment.lines() {
|
||||
let line = line.trim();
|
||||
if line.is_empty() || line.starts_with("/*") || line.starts_with("*/") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if line.starts_with("*") {
|
||||
let line = line[1..].trim();
|
||||
if line.starts_with("@meta") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some((key, value)) = line.split_once(':') {
|
||||
let key = key.trim();
|
||||
let value = value.trim();
|
||||
|
||||
match key {
|
||||
"Tool Versions" => {
|
||||
let tools: Vec<&str> = value.split('&').map(|s| s.trim()).collect();
|
||||
result.insert(key.to_string(), json!(tools));
|
||||
}
|
||||
"Revision" => {
|
||||
in_revision = true;
|
||||
}
|
||||
_ => {
|
||||
if in_revision {
|
||||
if value.matches('&').count() == 2 {
|
||||
let parts: Vec<&str> = value.split('&').map(|s| s.trim()).collect();
|
||||
let revision = json!({
|
||||
"date": parts[0],
|
||||
"version": parts[1],
|
||||
"revision": parts[2]
|
||||
});
|
||||
revision_vec.push(revision);
|
||||
} else {
|
||||
in_revision = false;
|
||||
result.insert(key.to_string(), json!(revision_vec));
|
||||
}
|
||||
} else {
|
||||
result.insert(key.to_string(), json!(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Copyright field
|
||||
if let Some(copyright) = result.get_mut("Copyright") {
|
||||
let copyright_str = copyright.as_str().unwrap_or("");
|
||||
*copyright = json!(format!("Copyright(c) {}", copyright_str));
|
||||
}
|
||||
|
||||
Ok(json!(result))
|
||||
}
|
180
src/codedoc/vlog.rs
Normal file
180
src/codedoc/vlog.rs
Normal file
@ -0,0 +1,180 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use ropey::Rope;
|
||||
use sv_parser::{RefNode, SyntaxTree};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use crate::core::sv_parser::{get_identifier, get_position};
|
||||
|
||||
struct CommentSymbol {
|
||||
comment_string: String,
|
||||
start_pos: crate::core::hdlparam::Position,
|
||||
end_pos: crate::core::hdlparam::Position
|
||||
}
|
||||
|
||||
pub fn get_comments_from_ast(doc: &Rope, syntax_tree: &SyntaxTree) {
|
||||
|
||||
let comments = make_comment_list(doc, syntax_tree);
|
||||
|
||||
for comment in &comments {
|
||||
if let Some(comment_meta) = get_meta_info(comment) {
|
||||
|
||||
} else {
|
||||
// 处理为普通注释
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 创造一个收容 comment 的栈,对连续的注释进行合并
|
||||
fn make_comment_list(doc: &Rope, syntax_tree: &SyntaxTree) -> Vec<CommentSymbol> {
|
||||
let mut comments = Vec::<CommentSymbol>::new();
|
||||
|
||||
for node in syntax_tree {
|
||||
match node {
|
||||
RefNode::Comment(x) => {
|
||||
let locate = x.nodes.0;
|
||||
let comment_string = syntax_tree.get_str(&locate).unwrap();
|
||||
let start_pos = get_position(doc, locate, 0);
|
||||
let end_pos = get_position(doc, locate, locate.len);
|
||||
|
||||
println!("{:?}", comment_string);
|
||||
println!("start {:?}", start_pos);
|
||||
println!("end {:?}", end_pos);
|
||||
|
||||
if let Some(last_comment) = comments.last_mut() {
|
||||
// 判断是否需要合并
|
||||
// vlog 只合并单行注释
|
||||
let last_end_line = last_comment.end_pos.line;
|
||||
let current_start_line = start_pos.line;
|
||||
|
||||
if current_start_line - last_end_line <= 1
|
||||
&& last_comment.comment_string.starts_with("//")
|
||||
&& comment_string.starts_with("//") {
|
||||
last_comment.comment_string += comment_string;
|
||||
last_comment.end_pos = end_pos;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 否则,直接加入
|
||||
comments.push(CommentSymbol {
|
||||
comment_string: comment_string.to_string(),
|
||||
start_pos, end_pos
|
||||
});
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
comments
|
||||
}
|
||||
|
||||
struct CommentMeta<'a> {
|
||||
comment_type: &'a str,
|
||||
argruments: Vec::<&'a str>
|
||||
}
|
||||
|
||||
/// 解析第一行 tag
|
||||
/// /* @meta
|
||||
/// *
|
||||
/// */
|
||||
///
|
||||
/// /* @module
|
||||
/// *
|
||||
/// */
|
||||
///
|
||||
/// /* @wavedrom xxx
|
||||
/// *
|
||||
/// */
|
||||
///
|
||||
/// 或者压根儿没有
|
||||
/// /*
|
||||
/// *
|
||||
/// */
|
||||
fn get_meta_info(comment: &str) -> Option<CommentMeta> {
|
||||
let first_line = comment.lines().next().unwrap_or("").trim();
|
||||
// 注释开头都是 // 或者 /* ,都是两个字符
|
||||
let comment_meta = &first_line[2..];
|
||||
if comment_meta.trim().starts_with("@") {
|
||||
let arguments: Vec<&str> = comment_meta.split_whitespace().collect();
|
||||
if arguments.len() > 0 {
|
||||
let comment_type = arguments[0];
|
||||
let arguments = &arguments[1..];
|
||||
Some(CommentMeta {
|
||||
comment_type,
|
||||
argruments: arguments.to_vec()
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// 解析不同的注释块
|
||||
fn codedoc_parse_pipeline(comment: &str) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
fn parse_c_style_comment(comment: &str) -> Result<Value, String> {
|
||||
let mut result = HashMap::new();
|
||||
let mut revision_vec = Vec::new();
|
||||
let mut in_revision = false;
|
||||
|
||||
for line in comment.lines() {
|
||||
let line = line.trim();
|
||||
if line.is_empty() || line.starts_with("/*") || line.starts_with("*/") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if line.starts_with("*") {
|
||||
let line = line[1..].trim();
|
||||
if line.starts_with("@meta") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some((key, value)) = line.split_once(':') {
|
||||
let key = key.trim();
|
||||
let value = value.trim();
|
||||
|
||||
match key {
|
||||
"Tool Versions" => {
|
||||
let tools: Vec<&str> = value.split('&').map(|s| s.trim()).collect();
|
||||
result.insert(key.to_string(), json!(tools));
|
||||
}
|
||||
"Revision" => {
|
||||
in_revision = true;
|
||||
}
|
||||
_ => {
|
||||
if in_revision {
|
||||
if value.matches('&').count() == 2 {
|
||||
let parts: Vec<&str> = value.split('&').map(|s| s.trim()).collect();
|
||||
let revision = json!({
|
||||
"date": parts[0],
|
||||
"version": parts[1],
|
||||
"revision": parts[2]
|
||||
});
|
||||
revision_vec.push(revision);
|
||||
} else {
|
||||
in_revision = false;
|
||||
result.insert(key.to_string(), json!(revision_vec));
|
||||
}
|
||||
} else {
|
||||
result.insert(key.to_string(), json!(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Copyright field
|
||||
if let Some(copyright) = result.get_mut("Copyright") {
|
||||
let copyright_str = copyright.as_str().unwrap_or("");
|
||||
*copyright = json!(format!("Copyright(c) {}", copyright_str));
|
||||
}
|
||||
|
||||
Ok(json!(result))
|
||||
}
|
16
src/execute_command/codedoc.rs
Normal file
16
src/execute_command/codedoc.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use std::{path::PathBuf, str::FromStr};
|
||||
|
||||
use log::info;
|
||||
use serde_json::Value;
|
||||
use tower_lsp::lsp_types::{Diagnostic, Url};
|
||||
|
||||
use crate::{diagnostics::provide_diagnostics, server::Backend, utils::{from_uri_to_escape_path_string, open_doc_as_rope}};
|
||||
|
||||
// /// 前端请求,发布诊断结果,仅在初始化和修改配置时触发
|
||||
// /// 参数为 [file_path: string]
|
||||
// pub async fn publish_diagnostics(
|
||||
// backend: &Backend,
|
||||
// arguments: Vec<Value>
|
||||
// ) -> tower_lsp::jsonrpc::Result<Option<Value>> {
|
||||
|
||||
// }
|
@ -4,6 +4,9 @@ use tower_lsp::lsp_types::*;
|
||||
use crate::server::Backend;
|
||||
mod diagnostics;
|
||||
|
||||
pub use codedoc::*;
|
||||
mod codedoc;
|
||||
|
||||
pub async fn execute_command(
|
||||
backend: &Backend,
|
||||
params: ExecuteCommandParams
|
||||
@ -17,6 +20,8 @@ pub async fn execute_command(
|
||||
diagnostics::clear_diagnostics(backend, params.arguments).await
|
||||
}
|
||||
|
||||
|
||||
|
||||
_ => {
|
||||
Ok(None)
|
||||
}
|
||||
|
@ -30,6 +30,9 @@ pub mod diagnostics;
|
||||
// 格式化
|
||||
pub mod format;
|
||||
|
||||
// 格式化
|
||||
pub mod codedoc;
|
||||
|
||||
// 基础工具
|
||||
pub mod utils;
|
||||
|
||||
|
@ -24,6 +24,7 @@ mod document_highlight;
|
||||
mod inlay_hint;
|
||||
mod code_lens;
|
||||
mod utils;
|
||||
mod codedoc;
|
||||
mod diagnostics;
|
||||
mod format;
|
||||
mod server;
|
||||
|
@ -702,7 +702,7 @@ pub fn sv_parser_pipeline(
|
||||
}
|
||||
|
||||
let escape_path_string = from_uri_to_escape_path_string(uri).unwrap();
|
||||
let escape_path = PathBuf::from_str(&escape_path_string).unwrap();
|
||||
// let escape_path = PathBuf::from_str(&escape_path_string).unwrap();
|
||||
|
||||
let ast = recovery_sv_parse_with_retry(
|
||||
doc,
|
||||
|
@ -486,4 +486,37 @@ mod test_file {
|
||||
assert!(is_character_ordered_match("car", "careful"));
|
||||
assert!(!is_character_ordered_match("suprt", "super"));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_code_doc {
|
||||
use std::{env, fs, path::PathBuf};
|
||||
|
||||
use ropey::Rope;
|
||||
use tower_lsp::lsp_types::Url;
|
||||
|
||||
use crate::sources::recovery_sv_parse_with_retry;
|
||||
use crate::codedoc;
|
||||
|
||||
#[test]
|
||||
fn dev_code_doc() {
|
||||
match env::current_dir() {
|
||||
Ok(path) => println!("当前工作目录: {}", path.display()),
|
||||
Err(e) => println!("获取当前工作目录失败: {}", e),
|
||||
}
|
||||
let path = PathBuf::from("E:/Project/Digital-IDE/digital-lsp-server/test/vlog/codedoc.v");
|
||||
let includes: Vec<PathBuf> = Vec::new();
|
||||
|
||||
let text = match fs::read_to_string(&path) {
|
||||
Ok(text) => text,
|
||||
Err(_) => return
|
||||
};
|
||||
|
||||
let doc = Rope::from_str(&text);
|
||||
let uri = Url::from_file_path(&path).unwrap();
|
||||
let result = recovery_sv_parse_with_retry(&doc, &uri, &None, &includes);
|
||||
if let Some((syntax_tree, _)) = result {
|
||||
codedoc::vlog::get_comments_from_ast(&doc, &syntax_tree);
|
||||
}
|
||||
}
|
||||
}
|
57
test/vlog/codedoc.v
Normal file
57
test/vlog/codedoc.v
Normal file
@ -0,0 +1,57 @@
|
||||
/* @meta
|
||||
* Create Date : 2/6/2025 14:58
|
||||
* Author : nitcloud
|
||||
* Target Device : [Target FPGA and ASIC Device]
|
||||
* Tool Versions : vivado 18.3 & DC 2016
|
||||
* Revision Historyc :
|
||||
* Revision :
|
||||
* 04/12 0.01 - File Created
|
||||
* Description :
|
||||
* Company : ncai Technology .Inc
|
||||
* Copyright : 1999, ncai Technology Inc, All right reserved
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* @module
|
||||
* Netlist : level-1
|
||||
* FSMView : on
|
||||
* Overview: 4-stage pipelined accumulator.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 这是一些简单的文字,可以随意渲染
|
||||
* :::info
|
||||
* 请注意版权问题
|
||||
* :::
|
||||
*
|
||||
* 使用 C 语言如此进行简单的编译
|
||||
* ```c
|
||||
* int main() {
|
||||
* return 0;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
|
||||
/* @wavedrom accuml this is accuml wavedrom
|
||||
{signal: [
|
||||
{name: 'clock', wave: '10101010101010101'},
|
||||
{name: 'reset', wave: '10...............'},
|
||||
{name: 'clr', wave: '01.0.............'},
|
||||
{name: 'idata', wave: 'x3...............', data: ['5']},
|
||||
{name: 'odata', wave: 'x........5.5.5.5.', data: ['5','10','25','30']},
|
||||
]}
|
||||
*/
|
||||
|
||||
module adder(
|
||||
// 这是一个简单的注释
|
||||
// 这是它们的第二行注释
|
||||
input a,
|
||||
input b,
|
||||
|
||||
// 这是输出信号
|
||||
output c,
|
||||
);
|
||||
// 具体的代码实现
|
||||
meta_add u_meta_add(a, b, c);
|
||||
endmodule
|
Loading…
x
Reference in New Issue
Block a user