完成缓存优化
This commit is contained in:
parent
db0156e88f
commit
fcfa4b141a
2
rust_hdl
2
rust_hdl
@ -1 +1 @@
|
|||||||
Subproject commit d3f01fe8ec8d6d48031e3eaf043a65244297ca9c
|
Subproject commit 0a335218d2f8e469ed3f510d168e4cd4ad2c1057
|
@ -1,6 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
|
use log::info;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tower_lsp::lsp_types::Position as LspPosition;
|
use tower_lsp::lsp_types::Position as LspPosition;
|
||||||
use tower_lsp::lsp_types::Range as LspRange;
|
use tower_lsp::lsp_types::Range as LspRange;
|
||||||
@ -323,6 +324,7 @@ impl HdlParam {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 根据 path 更新 fast
|
||||||
pub fn update_fast(&self, path: String, fast: FastHdlparam) {
|
pub fn update_fast(&self, path: String, fast: FastHdlparam) {
|
||||||
let mut fast_map = self.path_to_hdl_file.write().unwrap();
|
let mut fast_map = self.path_to_hdl_file.write().unwrap();
|
||||||
// 构建映射
|
// 构建映射
|
||||||
@ -340,6 +342,7 @@ impl HdlParam {
|
|||||||
fast_map.insert(path, file);
|
fast_map.insert(path, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 根据 module 的名字,找到 module 对象,拷贝返回
|
||||||
pub fn find_module_by_name(&self, name: &str) -> Option<Module> {
|
pub fn find_module_by_name(&self, name: &str) -> Option<Module> {
|
||||||
let module_name_to_path = self.module_name_to_path.read().unwrap();
|
let module_name_to_path = self.module_name_to_path.read().unwrap();
|
||||||
if let Some(path) = module_name_to_path.get(name) {
|
if let Some(path) = module_name_to_path.get(name) {
|
||||||
@ -354,6 +357,7 @@ impl HdlParam {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 输入 module 名字,找到 module 定义的文件的路径
|
||||||
pub fn find_module_definition_path(&self, module_name: &str) -> Option<String> {
|
pub fn find_module_definition_path(&self, module_name: &str) -> Option<String> {
|
||||||
let module_name_to_path = self.module_name_to_path.read().unwrap();
|
let module_name_to_path = self.module_name_to_path.read().unwrap();
|
||||||
if let Some(path) = module_name_to_path.get(module_name) {
|
if let Some(path) = module_name_to_path.get(module_name) {
|
||||||
@ -362,5 +366,20 @@ impl HdlParam {
|
|||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 遍历 path_string 下的所有 instance,并根据条件返回
|
||||||
|
pub fn walk_instantiation(&self, path_string: &str, condition: impl Fn(&Module, &Instance) -> bool) -> Option<Instance> {
|
||||||
|
let path_to_hdl_file = self.path_to_hdl_file.read().unwrap();
|
||||||
|
if let Some(hdl_file) = path_to_hdl_file.get(path_string) {
|
||||||
|
for def_module in &hdl_file.fast.content {
|
||||||
|
for inst in &def_module.instances {
|
||||||
|
if condition(def_module, inst) {
|
||||||
|
return Some(inst.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -182,7 +182,7 @@ fn make_macro_define_content(macro_define: &Define) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn hover_macro(server: &LSPServer, line: &RopeSlice, pos: Position, language_id: &str) -> Option<Hover> {
|
pub fn hover_macro(server: &LSPServer, line: &RopeSlice, pos: Position, language_id: &str) -> Option<Hover> {
|
||||||
let macro_text_regex = Regex::new(r"[`0-9a-zA-Z]").unwrap();
|
let macro_text_regex = Regex::new(r"[`_0-9a-zA-Z]").unwrap();
|
||||||
if let Some((macro_text, range)) = get_word_range_at_position(line, pos, macro_text_regex) {
|
if let Some((macro_text, range)) = get_word_range_at_position(line, pos, macro_text_regex) {
|
||||||
if macro_text.starts_with("`") {
|
if macro_text.starts_with("`") {
|
||||||
if let Some((macro_define, _)) = server.find_macros(¯o_text) {
|
if let Some((macro_define, _)) = server.find_macros(¯o_text) {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
|
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::{server::LSPServer, sources::LSPSupport};
|
use crate::{core::hdlparam::{HdlFile, Instance, Module}, hover::{to_escape_path, BracketMatchResult, BracketMatcher}, server::LSPServer, sources::LSPSupport};
|
||||||
use super::feature::*;
|
use super::feature::*;
|
||||||
use std::sync::RwLockReadGuard;
|
use std::{path::PathBuf, str::FromStr, sync::RwLockReadGuard};
|
||||||
|
|
||||||
use crate::definition::*;
|
use crate::definition::*;
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ pub fn hover(server: &LSPServer, params: &HoverParams) -> Option<Hover> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_hover_with_comment(doc: &Rope, line: usize, language_id: &str) -> Option<Hover> {
|
fn make_hover_with_comment(doc: &Rope, line: usize, language_id: &str, exclude_code: bool) -> Option<Hover> {
|
||||||
if line == 0 {
|
if line == 0 {
|
||||||
let language_string = LanguageString {
|
let language_string = LanguageString {
|
||||||
language: language_id.to_string(),
|
language: language_id.to_string(),
|
||||||
@ -112,6 +113,8 @@ fn make_hover_with_comment(doc: &Rope, line: usize, language_id: &str) -> Option
|
|||||||
|
|
||||||
if line.starts_with("/*") {
|
if line.starts_with("/*") {
|
||||||
line = line.strip_prefix("/*").unwrap().trim().to_string();
|
line = line.strip_prefix("/*").unwrap().trim().to_string();
|
||||||
|
} else if line.starts_with("//") {
|
||||||
|
line = line.strip_prefix("//").unwrap().trim().to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
if line.ends_with("*/") {
|
if line.ends_with("*/") {
|
||||||
@ -165,7 +168,7 @@ fn make_hover_with_comment(doc: &Rope, line: usize, language_id: &str) -> Option
|
|||||||
language: language_id.to_string(),
|
language: language_id.to_string(),
|
||||||
value: code
|
value: code
|
||||||
}));
|
}));
|
||||||
comment_markdowns.insert(0, MarkedString::String(comment));
|
comment_markdowns.insert(0, MarkedString::String(comment.trim().to_string()));
|
||||||
} else {
|
} else {
|
||||||
// 这行只有代码,没有注释
|
// 这行只有代码,没有注释
|
||||||
comment_markdowns.push(MarkedString::LanguageString(LanguageString {
|
comment_markdowns.push(MarkedString::LanguageString(LanguageString {
|
||||||
@ -175,13 +178,34 @@ fn make_hover_with_comment(doc: &Rope, line: usize, language_id: &str) -> Option
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 否则,都是上方的注释
|
// 否则,都是上方的注释
|
||||||
comment_markdowns.push(MarkedString::String(line_hover));
|
comment_markdowns.push(MarkedString::String(line_hover.trim().to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合并其中的 markdown
|
||||||
|
let mut merge_markdowns = Vec::<MarkedString>::new();
|
||||||
|
let mut string_buffer = String::new();
|
||||||
|
for (_, md) in comment_markdowns.iter().enumerate() {
|
||||||
|
match md {
|
||||||
|
MarkedString::String(markdown_string) => {
|
||||||
|
string_buffer.push_str(format!("{}\n", markdown_string.trim()).as_str());
|
||||||
|
}
|
||||||
|
MarkedString::LanguageString(code) => {
|
||||||
|
if !string_buffer.is_empty() {
|
||||||
|
merge_markdowns.push(MarkedString::String(string_buffer.to_string()));
|
||||||
|
string_buffer.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if !exclude_code {
|
||||||
|
merge_markdowns.push(MarkedString::LanguageString(code.to_owned()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if comment_markdowns.len() > 0 {
|
if comment_markdowns.len() > 0 {
|
||||||
return Some(Hover {
|
return Some(Hover {
|
||||||
contents: HoverContents::Array(comment_markdowns),
|
contents: HoverContents::Array(merge_markdowns),
|
||||||
range: None
|
range: None
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -207,8 +231,63 @@ fn hover_common_symbol(
|
|||||||
.get_definition(token, file.text.pos_to_byte(&pos), doc)?;
|
.get_definition(token, file.text.pos_to_byte(&pos), doc)?;
|
||||||
|
|
||||||
// 根据 symbol 的类别进行额外的判断
|
// 根据 symbol 的类别进行额外的判断
|
||||||
|
match symbol_definition.def_type {
|
||||||
|
DefinitionType::ModuleInstantiation => {
|
||||||
|
let hdlparam = server.srcs.hdl_param.clone();
|
||||||
|
let pathbuf = PathBuf::from_str(doc.path()).unwrap();
|
||||||
|
let pathbuf = to_escape_path(&pathbuf);
|
||||||
|
let path_string = pathbuf.to_str().unwrap().replace("\\", "/");
|
||||||
|
|
||||||
|
let find_name_condition = |_: &Module, instance: &Instance| {
|
||||||
|
symbol_definition.ident == instance.name
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if let Some(instance) = hdlparam.walk_instantiation(&path_string, find_name_condition) {
|
||||||
|
info!("instance {:?}", instance);
|
||||||
|
let def_line = file.text.byte_to_line(symbol_definition.byte_idx());
|
||||||
|
let mut markdown_comment = match make_hover_with_comment(&file.text, def_line, &language_id, true) {
|
||||||
|
Some(hover) => {
|
||||||
|
match hover.contents {
|
||||||
|
HoverContents::Array(array) => array,
|
||||||
|
_ => Vec::<MarkedString>::new()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => Vec::<MarkedString>::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
// 扫描到右括号
|
||||||
|
let mut current_line = def_line;
|
||||||
|
let mut buffer = String::new();
|
||||||
|
let len_lines = file.text.len_lines();
|
||||||
|
let mut matcher = BracketMatcher::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if current_line >= len_lines {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let line_text = file.text.line(current_line).to_string();
|
||||||
|
buffer.push_str(&line_text);
|
||||||
|
match matcher.consume_string(&line_text) {
|
||||||
|
BracketMatchResult::Invalid | BracketMatchResult::Complete => break,
|
||||||
|
BracketMatchResult::Valid => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
current_line += 1;
|
||||||
|
}
|
||||||
|
markdown_comment.push(MarkedString::LanguageString(LanguageString {
|
||||||
|
language: language_id.to_string(),
|
||||||
|
value: buffer
|
||||||
|
}));
|
||||||
|
|
||||||
|
return Some(Hover { contents: HoverContents::Array(markdown_comment), range: None });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
let def_line = file.text.byte_to_line(symbol_definition.byte_idx());
|
let def_line = file.text.byte_to_line(symbol_definition.byte_idx());
|
||||||
make_hover_with_comment(&file.text, def_line, &language_id)
|
make_hover_with_comment(&file.text, def_line, &language_id, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_vhdl_fast {
|
mod test_vhdl_fast {
|
||||||
use crate::{core::vhdl_parser::{make_fast_from_design_file, vhdl_parse}, test::TESTFILES_TEMP_DIR, utils::*};
|
use crate::{core::vhdl_parser::{make_fast_from_design_file, vhdl_parse}, test::{DIGTIAL_IDE_TEST, TESTFILES_TEMP_DIR}, utils::*};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_temp() {
|
fn test_temp() {
|
||||||
@ -23,4 +23,25 @@ mod test_vhdl_fast {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_digital_ide_test() {
|
||||||
|
let file_iter = RecursiveFileIterator::new(DIGTIAL_IDE_TEST);
|
||||||
|
for file in file_iter {
|
||||||
|
let language_id = get_language_id_by_pathbuf(&file);
|
||||||
|
if language_id == "vhdl" {
|
||||||
|
println!("test file: {:?}", file);
|
||||||
|
if let Some(design_file) = vhdl_parse(&file) {
|
||||||
|
if let Some(_) = make_fast_from_design_file(&design_file) {
|
||||||
|
println!("<(^-^)>");
|
||||||
|
} else {
|
||||||
|
eprintln!("error happen when make fast {:?}", file);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eprintln!("error happen when parse {:?}", file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
use log::info;
|
||||||
|
|
||||||
use crate::{core::hdlparam::Define, server::LSPServer};
|
use crate::{core::hdlparam::Define, server::LSPServer};
|
||||||
|
|
||||||
impl LSPServer {
|
impl LSPServer {
|
||||||
|
@ -290,4 +290,50 @@ pub fn srcpos_to_location(pos: &SrcPos) -> Location {
|
|||||||
uri,
|
uri,
|
||||||
range: to_lsp_range(pos.range()),
|
range: to_lsp_range(pos.range()),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// 用于判断括号匹配的数据结构
|
||||||
|
pub struct BracketMatcher {
|
||||||
|
stack: Vec<char>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum BracketMatchResult {
|
||||||
|
Valid,
|
||||||
|
Invalid,
|
||||||
|
Complete
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BracketMatcher {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
BracketMatcher { stack: Vec::<char>::new() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 匹配一段字符串内的括号,如果匹配不成功,返回 false
|
||||||
|
pub fn consume_string(&mut self, text: &str) -> BracketMatchResult {
|
||||||
|
for ch in text.chars() {
|
||||||
|
match ch {
|
||||||
|
'(' => {
|
||||||
|
self.stack.push(ch);
|
||||||
|
}
|
||||||
|
')' => {
|
||||||
|
let top = self.stack.pop();
|
||||||
|
if top.is_none() {
|
||||||
|
return BracketMatchResult::Invalid;
|
||||||
|
} else {
|
||||||
|
let top = top.unwrap();
|
||||||
|
if top != '(' {
|
||||||
|
return BracketMatchResult::Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.stack.len() == 0 {
|
||||||
|
return BracketMatchResult::Complete;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BracketMatchResult::Valid
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user