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"]
path = sv-parser
url = https://github.com/Digital-EDA/sv-parser
[submodule "rust_hdl"]
path = rust_hdl
url = https://github.com/Digital-EDA/rust_hdl
[submodule "vhdl-parser"]
path = vhdl-parser
url = https://github.com/Digital-EDA/vhdl-parser

View File

@ -6,7 +6,7 @@ edition = "2018"
[dependencies]
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"
bincode = "1.3"
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> {
let language_id = get_language_id_by_uri(&params.text_document_position.text_document.uri);
match language_id.as_str() {
"vhdl" => vhdl::completion(self, &params),
"verilog" | "systemverilog" => sv::completion(self, &params),
"vhdl" => vhdl::completion(
self,
&params
),
"verilog" | "systemverilog" => sv::completion(
self,
&params
),
_ => None
}
}

View File

@ -1,5 +1,4 @@
use core::hash;
use std::{borrow::{Borrow, Cow}, collections::HashMap, fs::{self}, hash::{DefaultHasher, Hash, Hasher}, os::unix::thread, path::PathBuf, sync::{Arc, RwLock}};
use std::{collections::HashMap, fs::{self}, hash::{DefaultHasher, Hash, Hasher}, path::PathBuf, sync::{Arc, RwLock}};
use log::info;
use serde::{Deserialize, Serialize};
@ -11,10 +10,7 @@ use super::hdlparam::FastHdlparam;
pub enum CacheResult<T> {
Ok(T),
NotNeedCache,
CacheNotFound,
NotHit,
FailDeserialize,
Error(String)
CacheNotFound
}
#[derive(Debug, Serialize, Deserialize, Clone)]
@ -139,10 +135,10 @@ impl CacheManager {
std::thread::spawn(move || {
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:?}");
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 result = recovery_sv_parse(&doc, &uri, &None, &includes);
println!("result: {result:?}");
// println!("result: {result:?}");
if let Some(syntax_tree) = result {
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 mod feature;
pub use feature::*;
pub mod extract_defs;
pub use extract_defs::*;
@ -22,8 +21,16 @@ impl LSPServer {
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);
match language_id.as_str() {
"vhdl" => vhdl::goto_vhdl_definition(self, &params),
"verilog" | "systemverilog" => sv::goto_definition(self, &params),
"vhdl" => vhdl::goto_vhdl_definition(
self,
&params
),
"verilog" | "systemverilog" => sv::goto_definition(
self,
&params
),
_ => 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 log::info;
use sv_parser::{RefNode, SyntaxTree};
use vhdl::vhdl_document_highlight;
use crate::definition::extract_defs::get_ident;
use crate::{server::LSPServer, utils::{get_definition_token, get_language_id_by_uri}};
use tower_lsp::lsp_types::*;
pub mod vhdl;
mod sv;
mod vhdl;
impl LSPServer {
pub fn document_highlight(
@ -24,8 +21,12 @@ impl LSPServer {
let language_id = get_language_id_by_uri(&uri);
match language_id.as_str() {
"vhdl" => vhdl_document_highlight(self, &params.text_document_position_params),
"verilog" | "systemverilog" => sv_document_highlight(
"vhdl" => vhdl::document_highlight(
self,
&params.text_document_position_params
),
"verilog" | "systemverilog" => sv::document_highlight(
self,
&token,
&file,
@ -35,56 +36,4 @@ impl LSPServer {
_ => None
}
}
}
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}};
pub fn vhdl_document_highlight(
pub fn document_highlight(
server: &LSPServer,
params: &TextDocumentPositionParams
) -> Option<Vec<DocumentHighlight>> {

View File

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

View File

@ -5,7 +5,7 @@ use regex::Regex;
use ropey::RopeSlice;
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};
@ -343,28 +343,49 @@ pub fn hover_module_declaration(
definition: &GenericDec,
language_id: &str
) -> Option<Hover> {
// let module_info = match definition.def_type {
// DefinitionType::GenericScope => {
// let pathbuf = PathBuf::from_str(definition.url.path()).unwrap();
// let path_string = to_escape_path(&pathbuf).to_str().unwrap();
// let hdlparam = &server.srcs.hdl_param;
// let mut result: Option<(Module, String)> = None;
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()
}
};
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})");
// 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
// }
// _ => None
// };
if let Some(module) = server.srcs.hdl_param.find_module_by_name(token_name) {
let port_num = module.ports.len();
let param_num = module.params.len();
let instance_num = module.instances.len();
let port_desc = format!("`port` {port_num}, `param` {param_num}, `instantiation` {instance_num}");
// 统计 dir
@ -382,9 +403,6 @@ pub fn hover_module_declaration(
}
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();
markdowns.push(MarkedString::String(port_desc));

View File

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

View File

@ -2,7 +2,7 @@ use log::info;
use regex::Regex;
use ropey::Rope;
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 std::{path::PathBuf, str::FromStr, sync::RwLockReadGuard};

View File

@ -127,7 +127,7 @@ pub struct Source {
}
pub enum ParseIR {
/// 基于 rust_hdl 的IR存放 VHDL
/// 基于 vhdl-parser 的IR存放 VHDL
#[allow(unused)]
VHDLProject(vhdl_lang::Project),
/// 存放 sv 的 IR
@ -487,7 +487,7 @@ pub fn recovery_sv_parse(
let com_define = Define {
identifier: not_found_macro_name.to_string(),
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));
parse_iterations += 1;

View File

@ -54,7 +54,7 @@ mod test_fast {
#[test]
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();
println!("{:#?}", fast.content);
}
@ -427,7 +427,6 @@ mod test_file {
#[test]
fn test_cache() {
let test_path = "/home/dide/project/digital-lsp-server/.cache";
fs::create_dir_all("/home/dide/project/digital-lsp-server/.cache");
let _ = fs::create_dir_all("/home/dide/project/digital-lsp-server/.cache");
}
}

View File

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

1
vhdl-parser Submodule

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