This commit is contained in:
锦恢 2024-10-05 00:12:36 +08:00
parent c8761d2910
commit 92be4bfbd4
20 changed files with 190 additions and 127 deletions

6
.gitmodules vendored
View File

@ -1,6 +1,6 @@
[submodule "sv-parser"] [submodule "sv-parser"]
path = sv-parser path = sv-parser
url = https://github.com/Digital-EDA/sv-parser url = https://github.com/Digital-EDA/sv-parser
[submodule "rust_hdl"] [submodule "vhdl-parser"]
path = rust_hdl path = vhdl-parser
url = https://github.com/Digital-EDA/rust_hdl url = https://github.com/Digital-EDA/vhdl-parser

View File

@ -6,7 +6,7 @@ edition = "2018"
[dependencies] [dependencies]
sv-parser = { version = "0.13.3", path = "sv-parser/sv-parser"} sv-parser = { version = "0.13.3", path = "sv-parser/sv-parser"}
vhdl_lang = { version = "^0.83.0", path = "rust_hdl/vhdl_lang" } vhdl_lang = { version = "^0.83.0", path = "vhdl-parser/vhdl_lang" }
dirs-next = "2.0" dirs-next = "2.0"
bincode = "1.3" bincode = "1.3"
percent-encoding = "2.1.0" percent-encoding = "2.1.0"

@ -1 +0,0 @@
Subproject commit 69fba9af8cb981ce1aaeacd20ca74771f12d9aa1

View File

@ -11,8 +11,16 @@ impl LSPServer {
pub fn completion(&self, params: CompletionParams) -> Option<CompletionResponse> { pub fn completion(&self, params: CompletionParams) -> Option<CompletionResponse> {
let language_id = get_language_id_by_uri(&params.text_document_position.text_document.uri); let language_id = get_language_id_by_uri(&params.text_document_position.text_document.uri);
match language_id.as_str() { match language_id.as_str() {
"vhdl" => vhdl::completion(self, &params), "vhdl" => vhdl::completion(
"verilog" | "systemverilog" => sv::completion(self, &params), self,
&params
),
"verilog" | "systemverilog" => sv::completion(
self,
&params
),
_ => None _ => None
} }
} }

View File

@ -1,5 +1,4 @@
use core::hash; use std::{collections::HashMap, fs::{self}, hash::{DefaultHasher, Hash, Hasher}, path::PathBuf, sync::{Arc, RwLock}};
use std::{borrow::{Borrow, Cow}, collections::HashMap, fs::{self}, hash::{DefaultHasher, Hash, Hasher}, os::unix::thread, path::PathBuf, sync::{Arc, RwLock}};
use log::info; use log::info;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -11,10 +10,7 @@ use super::hdlparam::FastHdlparam;
pub enum CacheResult<T> { pub enum CacheResult<T> {
Ok(T), Ok(T),
NotNeedCache, NotNeedCache,
CacheNotFound, CacheNotFound
NotHit,
FailDeserialize,
Error(String)
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
@ -139,10 +135,10 @@ impl CacheManager {
std::thread::spawn(move || { std::thread::spawn(move || {
info!("save meta to {meta_save_path:?}"); info!("save meta to {meta_save_path:?}");
k_serialize(&meta_save_path, meta); let _ = k_serialize(&meta_save_path, meta);
info!("save index to {cache_save_path:?}"); info!("save index to {cache_save_path:?}");
k_serialize(&cache_save_path, fast); let _ = k_serialize(&cache_save_path, fast);
}); });
} }

View File

@ -28,7 +28,7 @@ pub fn sv_parser(path: &str) -> Option<FastHdlparam> {
let uri = Url::from_file_path(&path).unwrap(); let uri = Url::from_file_path(&path).unwrap();
let result = recovery_sv_parse(&doc, &uri, &None, &includes); let result = recovery_sv_parse(&doc, &uri, &None, &includes);
println!("result: {result:?}"); // println!("result: {result:?}");
if let Some(syntax_tree) = result { if let Some(syntax_tree) = result {
if let Ok(hdlparam) = make_fast_from_syntaxtree(&syntax_tree, &path) { if let Ok(hdlparam) = make_fast_from_syntaxtree(&syntax_tree, &path) {

View File

@ -10,7 +10,6 @@ pub mod def_types;
pub use def_types::*; pub use def_types::*;
pub mod feature; pub mod feature;
pub use feature::*;
pub mod extract_defs; pub mod extract_defs;
pub use extract_defs::*; pub use extract_defs::*;
@ -22,8 +21,16 @@ impl LSPServer {
pub fn goto_definition(&self, params: GotoDefinitionParams) -> Option<GotoDefinitionResponse> { pub fn goto_definition(&self, params: GotoDefinitionParams) -> Option<GotoDefinitionResponse> {
let language_id = get_language_id_by_uri(&params.text_document_position_params.text_document.uri); let language_id = get_language_id_by_uri(&params.text_document_position_params.text_document.uri);
match language_id.as_str() { match language_id.as_str() {
"vhdl" => vhdl::goto_vhdl_definition(self, &params), "vhdl" => vhdl::goto_vhdl_definition(
"verilog" | "systemverilog" => sv::goto_definition(self, &params), self,
&params
),
"verilog" | "systemverilog" => sv::goto_definition(
self,
&params
),
_ => None _ => None
} }
} }

View File

@ -1,11 +1,8 @@
use crate::{definition::Scope, server::LSPServer, sources::{LSPSupport, ParseIR, Source}, utils::{get_definition_token, get_language_id_by_uri}}; use crate::{server::LSPServer, utils::{get_definition_token, get_language_id_by_uri}};
use log::info;
use sv_parser::{RefNode, SyntaxTree};
use vhdl::vhdl_document_highlight;
use crate::definition::extract_defs::get_ident;
use tower_lsp::lsp_types::*; use tower_lsp::lsp_types::*;
pub mod vhdl; mod sv;
mod vhdl;
impl LSPServer { impl LSPServer {
pub fn document_highlight( pub fn document_highlight(
@ -24,8 +21,12 @@ impl LSPServer {
let language_id = get_language_id_by_uri(&uri); let language_id = get_language_id_by_uri(&uri);
match language_id.as_str() { match language_id.as_str() {
"vhdl" => vhdl_document_highlight(self, &params.text_document_position_params), "vhdl" => vhdl::document_highlight(
"verilog" | "systemverilog" => sv_document_highlight( self,
&params.text_document_position_params
),
"verilog" | "systemverilog" => sv::document_highlight(
self, self,
&token, &token,
&file, &file,
@ -36,55 +37,3 @@ impl LSPServer {
} }
} }
} }
fn sv_document_highlight(
server: &LSPServer,
token: &str,
file: &Source,
pos: Position,
uri: &Url
) -> Option<Vec<DocumentHighlight>> {
let scope_tree = server.srcs.scope_tree.read().ok()?;
// use the byte_idx of the definition if possible, otherwise use the cursor
let byte_idx =
match scope_tree
.as_ref()?
.get_definition(token, file.text.pos_to_byte(&pos), uri)
{
Some(def) => def.byte_idx,
None => file.text.pos_to_byte(&pos),
};
let syntax_tree = file.parse_ir.as_ref()?;
match syntax_tree {
ParseIR::SyntaxTree(syntax_tree) => {
let references = all_identifiers(&syntax_tree, &token);
Some(
scope_tree
.as_ref()?
.document_highlights(&uri, &file.text, references, byte_idx),
)
},
_ => {
info!("error happen in [sv_document_highlight]");
None
}
}
}
/// return all identifiers in a syntax tree matching a given token
fn all_identifiers(syntax_tree: &SyntaxTree, token: &str) -> Vec<(String, usize)> {
let mut idents: Vec<(String, usize)> = Vec::new();
for node in syntax_tree {
if let RefNode::Identifier(_) = node {
let (ident, byte_idx) = get_ident(syntax_tree, node);
if ident == token {
idents.push((ident, byte_idx));
}
}
}
idents
}

View File

@ -0,0 +1,58 @@
#[allow(unused)]
use log::info;
use sv_parser::{RefNode, SyntaxTree};
use tower_lsp::lsp_types::*;
use crate::{definition::{get_ident, Scope}, server::LSPServer, sources::{LSPSupport, ParseIR, Source}};
pub fn document_highlight(
server: &LSPServer,
token: &str,
file: &Source,
pos: Position,
uri: &Url
) -> Option<Vec<DocumentHighlight>> {
let scope_tree = server.srcs.scope_tree.read().ok()?;
// use the byte_idx of the definition if possible, otherwise use the cursor
let byte_idx =
match scope_tree
.as_ref()?
.get_definition(token, file.text.pos_to_byte(&pos), uri)
{
Some(def) => def.byte_idx,
None => file.text.pos_to_byte(&pos),
};
let syntax_tree = file.parse_ir.as_ref()?;
match syntax_tree {
ParseIR::SyntaxTree(syntax_tree) => {
let references = all_identifiers(&syntax_tree, &token);
Some(
scope_tree
.as_ref()?
.document_highlights(&uri, &file.text, references, byte_idx),
)
},
_ => {
info!("error happen in [sv_document_highlight]");
None
}
}
}
/// return all identifiers in a syntax tree matching a given token
fn all_identifiers(syntax_tree: &SyntaxTree, token: &str) -> Vec<(String, usize)> {
let mut idents: Vec<(String, usize)> = Vec::new();
for node in syntax_tree {
if let RefNode::Identifier(_) = node {
let (ident, byte_idx) = get_ident(syntax_tree, node);
if ident == token {
idents.push((ident, byte_idx));
}
}
}
idents
}

View File

@ -5,7 +5,7 @@ use tower_lsp::lsp_types::*;
use crate::{server::LSPServer, utils::{from_lsp_pos, to_escape_path, to_lsp_range}}; use crate::{server::LSPServer, utils::{from_lsp_pos, to_escape_path, to_lsp_range}};
pub fn vhdl_document_highlight( pub fn document_highlight(
server: &LSPServer, server: &LSPServer,
params: &TextDocumentPositionParams params: &TextDocumentPositionParams
) -> Option<Vec<DocumentHighlight>> { ) -> Option<Vec<DocumentHighlight>> {

View File

@ -1,22 +1,24 @@
use tower_lsp::lsp_types::*; use tower_lsp::lsp_types::*;
use crate::{definition::Scope, server::LSPServer}; use crate::{server::LSPServer, utils::get_language_id_by_uri};
pub mod vhdl;
mod sv;
mod vhdl;
impl LSPServer { impl LSPServer {
pub fn document_symbol(&self, params: DocumentSymbolParams) -> Option<DocumentSymbolResponse> { pub fn document_symbol(&self, params: DocumentSymbolParams) -> Option<DocumentSymbolResponse> {
let uri = params.text_document.uri; let uri = &params.text_document.uri;
let file_id = self.srcs.get_id(&uri).to_owned(); let language_id = get_language_id_by_uri(uri);
self.srcs.wait_parse_ready(file_id, false); match language_id.as_str() {
let file = self.srcs.get_file(file_id)?; "vhdl" => vhdl::document_symbol(
let file = file.read().ok()?; self,
let scope_tree = self.srcs.scope_tree.read().ok()?; &params
),
"verilog" | "systemverilog" => sv::document_symbol(
self,
Some(DocumentSymbolResponse::Nested( &params
scope_tree.as_ref()?.document_symbols(&uri, &file.text), ),
)) _ => None
}
} }
} }

18
src/document_symbol/sv.rs Normal file
View File

@ -0,0 +1,18 @@
use crate::{definition::Scope, server::LSPServer};
use tower_lsp::lsp_types::*;
pub fn document_symbol(
server: &LSPServer,
params: &DocumentSymbolParams
) -> Option<DocumentSymbolResponse> {
let uri = &params.text_document.uri;
let file_id = server.srcs.get_id(uri).to_owned();
server.srcs.wait_parse_ready(file_id, false);
let file = server.srcs.get_file(file_id)?;
let file = file.read().ok()?;
let scope_tree = server.srcs.scope_tree.read().ok()?;
Some(DocumentSymbolResponse::Nested(
scope_tree.as_ref()?.document_symbols(uri, &file.text),
))
}

View File

@ -7,7 +7,7 @@ use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
use vhdl_lang::{EntHierarchy, Token}; use vhdl_lang::{EntHierarchy, Token};
pub fn vhdl_document_symbol(server: &LSPServer, params: &DocumentSymbolParams) -> Option<DocumentSymbolResponse> { pub fn document_symbol(server: &LSPServer, params: &DocumentSymbolParams) -> Option<DocumentSymbolResponse> {
let uri = &params.text_document.uri; let uri = &params.text_document.uri;
let file_id = server.srcs.get_id(&uri).to_owned(); let file_id = server.srcs.get_id(&uri).to_owned();
server.srcs.wait_parse_ready(file_id, false); server.srcs.wait_parse_ready(file_id, false);

View File

@ -5,7 +5,7 @@ use regex::Regex;
use ropey::RopeSlice; use ropey::RopeSlice;
use tower_lsp::lsp_types::{Hover, HoverContents, LanguageString, MarkedString, Position, Range, Url}; use tower_lsp::lsp_types::{Hover, HoverContents, LanguageString, MarkedString, Position, Range, Url};
use crate::{core::hdlparam::{Define, FastHdlparam, Module}, definition::{DefinitionType, GenericDec}, server::LSPServer}; use crate::{core::hdlparam::{Define, FastHdlparam}, definition::{DefinitionType, GenericDec}, server::LSPServer};
use super::{get_word_range_at_position, resolve_path, to_escape_path}; use super::{get_word_range_at_position, resolve_path, to_escape_path};
@ -343,28 +343,49 @@ pub fn hover_module_declaration(
definition: &GenericDec, definition: &GenericDec,
language_id: &str language_id: &str
) -> Option<Hover> { ) -> Option<Hover> {
// let module_info = match definition.def_type { let module_info = match definition.def_type {
// DefinitionType::GenericScope => { DefinitionType::GenericScope => {
// let pathbuf = PathBuf::from_str(definition.url.path()).unwrap(); let pathbuf = PathBuf::from_str(definition.url.path()).unwrap();
// let path_string = to_escape_path(&pathbuf).to_str().unwrap(); let pathbuf = to_escape_path(&pathbuf);
// let hdlparam = &server.srcs.hdl_param; let path_string = pathbuf.to_str().unwrap();
// let mut result: Option<(Module, String)> = None;
// if let Some(hdl_file) = hdlparam.path_to_hdl_file.read().unwrap().get(path_string) { let hdlparam = &server.srcs.hdl_param;
// for module in &hdl_file.fast.content { let search_result = || {
// if module.name == definition.ident { if let Some(hdl_file) = hdlparam.path_to_hdl_file.read().unwrap().get(path_string) {
// return Some((module.clone(), path_string.to_string())) for module in &hdl_file.fast.content {
// } if module.name == definition.ident {
// } return Some((module.clone(), path_string.to_string()));
// } }
// None }
// } }
// _ => None
// }; None
};
search_result()
}
_ => {
let search_result = || {
if let Some(module) = server.srcs.hdl_param.find_module_by_name(token_name) { 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()
}
};
if let Some((module, path_string)) = module_info {
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 port_num = module.ports.len(); let port_num = module.ports.len();
let param_num = module.params.len(); let param_num = module.params.len();
let instance_num = module.instances.len(); let instance_num = module.instances.len();
let port_desc = format!("`port` {port_num}, `param` {param_num}, `instantiation` {instance_num}"); let port_desc = format!("`port` {port_num}, `param` {param_num}, `instantiation` {instance_num}");
// 统计 dir // 统计 dir
@ -383,9 +404,6 @@ pub fn hover_module_declaration(
let io_desc = format!("`input` {input_count}, `output` {output_count}, `inout` {inout_count}"); let io_desc = format!("`input` {input_count}, `output` {output_count}, `inout` {inout_count}");
let path_string = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap_or("unknown".to_string());
let define_info = format!("define in {path_string}");
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));

View File

@ -13,8 +13,16 @@ impl LSPServer {
pub fn hover(&self, params: HoverParams) -> Option<Hover> { pub fn hover(&self, params: HoverParams) -> Option<Hover> {
let language_id = get_language_id_by_uri(&params.text_document_position_params.text_document.uri); let language_id = get_language_id_by_uri(&params.text_document_position_params.text_document.uri);
match language_id.as_str() { match language_id.as_str() {
"vhdl" => vhdl::hover(self, &params), "vhdl" => vhdl::hover(
"verilog" | "systemverilog" => sv::hover(self, &params), self,
&params
),
"verilog" | "systemverilog" => sv::hover(
self,
&params
),
_ => None _ => None
} }
} }

View File

@ -2,7 +2,7 @@ use log::info;
use regex::Regex; use regex::Regex;
use ropey::Rope; use ropey::Rope;
use tower_lsp::lsp_types::*; use tower_lsp::lsp_types::*;
use crate::{core::hdlparam::{HdlFile, Instance, Module}, hover::{to_escape_path, BracketMatchResult, BracketMatcher}, server::LSPServer, sources::LSPSupport}; use crate::{core::hdlparam::{Instance, Module}, hover::{to_escape_path, BracketMatchResult, BracketMatcher}, server::LSPServer, sources::LSPSupport};
use super::feature::*; use super::feature::*;
use std::{path::PathBuf, str::FromStr, sync::RwLockReadGuard}; use std::{path::PathBuf, str::FromStr, sync::RwLockReadGuard};

View File

@ -127,7 +127,7 @@ pub struct Source {
} }
pub enum ParseIR { pub enum ParseIR {
/// 基于 rust_hdl 的IR存放 VHDL /// 基于 vhdl-parser 的IR存放 VHDL
#[allow(unused)] #[allow(unused)]
VHDLProject(vhdl_lang::Project), VHDLProject(vhdl_lang::Project),
/// 存放 sv 的 IR /// 存放 sv 的 IR
@ -487,7 +487,7 @@ pub fn recovery_sv_parse(
let com_define = Define { let com_define = Define {
identifier: not_found_macro_name.to_string(), identifier: not_found_macro_name.to_string(),
arguments: Vec::new(), arguments: Vec::new(),
text: Some(DefineText {text: "dide-undefined".to_string(), origin: None}) text: Some(DefineText {text: "UNKNOWN_MACRO".to_string(), origin: None})
}; };
defines.insert(not_found_macro_name, Some(com_define)); defines.insert(not_found_macro_name, Some(com_define));
parse_iterations += 1; parse_iterations += 1;

View File

@ -54,7 +54,7 @@ mod test_fast {
#[test] #[test]
fn test_parent() { fn test_parent() {
let fast = sv_parser("/home/dide/project/Digital-Test/Digital-IDE-temp/user/src/vlog/bigfile/axil_crossbar.v"); let fast = sv_parser("/home/dide/project/Digital-Test/Digital-IDE-temp/user/src/svlog/std2017/dependence/parent.sv");
let fast = fast.unwrap(); let fast = fast.unwrap();
println!("{:#?}", fast.content); println!("{:#?}", fast.content);
} }
@ -427,7 +427,6 @@ mod test_file {
#[test] #[test]
fn test_cache() { fn test_cache() {
let test_path = "/home/dide/project/digital-lsp-server/.cache"; let _ = fs::create_dir_all("/home/dide/project/digital-lsp-server/.cache");
fs::create_dir_all("/home/dide/project/digital-lsp-server/.cache");
} }
} }

View File

@ -1,4 +1,4 @@
#[allow(unused)]
use log::info; use log::info;
use crate::{core::hdlparam::Define, server::LSPServer}; use crate::{core::hdlparam::Define, server::LSPServer};

1
vhdl-parser Submodule

@ -0,0 +1 @@
Subproject commit 8593beff8c21bd3d3e417ac893b9f317f5386070