去除 fast 计算中 params 重复的问题
This commit is contained in:
parent
ca13b39c16
commit
e0753a25f9
0
build_all.sh
Normal file → Executable file
0
build_all.sh
Normal file → Executable file
@ -94,6 +94,8 @@ pub fn completion(server: &LSPServer, params: &CompletionParams) -> Option<Compl
|
||||
file.text.pos_to_byte(&doc.position),
|
||||
&doc.text_document.uri,
|
||||
)?;
|
||||
info!("current completion token: {}", token);
|
||||
|
||||
comps.items.extend::<Vec<CompletionItem>>(
|
||||
server.key_comps
|
||||
.iter()
|
||||
|
@ -419,5 +419,19 @@ impl HdlParam {
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// 跟随一个路径进行删除
|
||||
pub fn delete_file(&self, path_string: &str) {
|
||||
let mut path_to_hdl_file = self.path_to_hdl_file.write().unwrap();
|
||||
if let Some(hdl_file) = path_to_hdl_file.get(path_string) {
|
||||
// 根据 hdl_file.fast.content 删除 self.module_name_to_path
|
||||
let mut module_name_to_path = self.module_name_to_path.write().unwrap();
|
||||
for module_info in &hdl_file.fast.content {
|
||||
module_name_to_path.remove(&module_info.name);
|
||||
}
|
||||
}
|
||||
path_to_hdl_file.remove(path_string);
|
||||
// TODO: 引入前端的 solve unhandled instance 机制
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
use std::collections::HashSet;
|
||||
use std::fs::{self, File};
|
||||
use std::io::BufRead;
|
||||
use std::io::BufReader;
|
||||
use std::path::PathBuf;
|
||||
use log::info;
|
||||
use regex::Regex;
|
||||
use ropey::Rope;
|
||||
use tower_lsp::lsp_types::Url;
|
||||
@ -54,6 +56,9 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re
|
||||
};
|
||||
let mut ansi_port_last_dir = "";
|
||||
|
||||
// TODO: 搞清楚为什么会出现重复
|
||||
let mut added_param_names = HashSet::<String>::new();
|
||||
|
||||
let content = syntax_tree.text.text().split('\n')
|
||||
.map(|s| s.to_string())
|
||||
.collect::<Vec<String>>();
|
||||
@ -114,48 +119,51 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re
|
||||
if let Some(id) = unwrap_node!(x, ParameterIdentifier) {
|
||||
let id = get_identifier(id).unwrap();
|
||||
let name = syntax_tree.get_str(&id).unwrap();
|
||||
match unwrap_node!(x, ParameterDeclarationParam, ParameterPortDeclarationParamList) {
|
||||
Some(RefNode::ParameterDeclarationParam(param_node)) => {
|
||||
// println!("{:?}", param_node);
|
||||
let keyword_locate = param_node.nodes.0.nodes.0;
|
||||
// println!("keyword {:#?}", keyword_locate);
|
||||
let (start_line, start_character) = (id.line, get_column_by_offset(&content, keyword_locate.offset) as u32);
|
||||
let (mut end_line, mut end_character) = (id.line, start_character + id.len as u32);
|
||||
let net_type = match unwrap_node!(param_node, DataType) {
|
||||
Some(RefNode::DataType(data_type)) => {
|
||||
let id = unwrap_node!(data_type, SimpleIdentifier, Keyword);
|
||||
if id == None {
|
||||
"wire"
|
||||
} else {
|
||||
let id = get_identifier(id.unwrap()).unwrap();
|
||||
syntax_tree.get_str(&id).unwrap()
|
||||
if !added_param_names.contains(name) {
|
||||
added_param_names.insert(name.to_string());
|
||||
match unwrap_node!(x, ParameterDeclarationParam, ParameterPortDeclarationParamList) {
|
||||
Some(RefNode::ParameterDeclarationParam(param_node)) => {
|
||||
// println!("{:?}", param_node);
|
||||
let keyword_locate = param_node.nodes.0.nodes.0;
|
||||
// println!("keyword {:#?}", keyword_locate);
|
||||
let (start_line, start_character) = (id.line, get_column_by_offset(&content, keyword_locate.offset) as u32);
|
||||
let (mut end_line, mut end_character) = (id.line, start_character + id.len as u32);
|
||||
let net_type = match unwrap_node!(param_node, DataType) {
|
||||
Some(RefNode::DataType(data_type)) => {
|
||||
let id = unwrap_node!(data_type, SimpleIdentifier, Keyword);
|
||||
if id == None {
|
||||
"wire"
|
||||
} else {
|
||||
let id = get_identifier(id.unwrap()).unwrap();
|
||||
syntax_tree.get_str(&id).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => "wire"
|
||||
};
|
||||
let init = if let Some(init) = unwrap_node!(param_node, ConstantMintypmaxExpression) {
|
||||
match init {
|
||||
RefNode::ConstantMintypmaxExpression(expression) => {
|
||||
// println!("expression {:?}", x);
|
||||
let param_init = sv_parser::NeedParseExpression::Parameter(expression.clone());
|
||||
let (exp, last_locate) = parse_expression(&syntax_tree, ¶m_init);
|
||||
(end_line, end_character) = if last_locate != None {
|
||||
// println!("param {:?} lastlocate {:?}", name, last_locate);
|
||||
(last_locate.unwrap().line, (get_column_by_offset(&content, last_locate.unwrap().offset) + last_locate.unwrap().len) as u32)
|
||||
} else {
|
||||
(end_line, end_character)
|
||||
};
|
||||
// println!("end pos {} {}", end_line, end_character);
|
||||
exp
|
||||
_ => "wire"
|
||||
};
|
||||
let init = if let Some(init) = unwrap_node!(param_node, ConstantMintypmaxExpression) {
|
||||
match init {
|
||||
RefNode::ConstantMintypmaxExpression(expression) => {
|
||||
// println!("expression {:?}", x);
|
||||
let param_init = sv_parser::NeedParseExpression::Parameter(expression.clone());
|
||||
let (exp, last_locate) = parse_expression(&syntax_tree, ¶m_init);
|
||||
(end_line, end_character) = if last_locate != None {
|
||||
// println!("param {:?} lastlocate {:?}", name, last_locate);
|
||||
(last_locate.unwrap().line, (get_column_by_offset(&content, last_locate.unwrap().offset) + last_locate.unwrap().len) as u32)
|
||||
} else {
|
||||
(end_line, end_character)
|
||||
};
|
||||
// println!("end pos {} {}", end_line, end_character);
|
||||
exp
|
||||
}
|
||||
_ => "unknown".to_string()
|
||||
}
|
||||
_ => "unknown".to_string()
|
||||
}
|
||||
} else {
|
||||
"unknown".to_string()
|
||||
};
|
||||
hdlparam.add_parameter(name, net_type, init.as_str(), start_line, start_character, end_line, end_character);
|
||||
} else {
|
||||
"unknown".to_string()
|
||||
};
|
||||
hdlparam.add_parameter(name, net_type, init.as_str(), start_line, start_character, end_line, end_character);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -163,49 +171,53 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re
|
||||
if let Some(id) = unwrap_node!(x, ParameterIdentifier) {
|
||||
let id = get_identifier(id).unwrap();
|
||||
let name = syntax_tree.get_str(&id).unwrap();
|
||||
match unwrap_node!(x, ParameterDeclarationParam, ParameterPortDeclarationParamList) {
|
||||
Some(RefNode::ParameterDeclarationParam(param_node)) => {
|
||||
// println!("{:?}", param_node);
|
||||
let keyword_locate = param_node.nodes.0.nodes.0;
|
||||
// println!("keyword {:#?}", keyword_locate);
|
||||
let (start_line, start_character) = (id.line, get_column_by_offset(&content, keyword_locate.offset) as u32);
|
||||
let (mut end_line, mut end_character) = (id.line, start_character + id.len as u32);
|
||||
let net_type = match unwrap_node!(param_node, DataType) {
|
||||
Some(RefNode::DataType(data_type)) => {
|
||||
let id = unwrap_node!(data_type, SimpleIdentifier, Keyword);
|
||||
if id == None {
|
||||
"wire"
|
||||
} else {
|
||||
let id = get_identifier(id.unwrap()).unwrap();
|
||||
syntax_tree.get_str(&id).unwrap()
|
||||
if !added_param_names.contains(name) {
|
||||
added_param_names.insert(name.to_string());
|
||||
match unwrap_node!(x, ParameterDeclarationParam, ParameterPortDeclarationParamList) {
|
||||
Some(RefNode::ParameterDeclarationParam(param_node)) => {
|
||||
// println!("{:?}", param_node);
|
||||
let keyword_locate = param_node.nodes.0.nodes.0;
|
||||
// println!("keyword {:#?}", keyword_locate);
|
||||
let (start_line, start_character) = (id.line, get_column_by_offset(&content, keyword_locate.offset) as u32);
|
||||
let (mut end_line, mut end_character) = (id.line, start_character + id.len as u32);
|
||||
let net_type = match unwrap_node!(param_node, DataType) {
|
||||
Some(RefNode::DataType(data_type)) => {
|
||||
let id = unwrap_node!(data_type, SimpleIdentifier, Keyword);
|
||||
if id == None {
|
||||
"wire"
|
||||
} else {
|
||||
let id = get_identifier(id.unwrap()).unwrap();
|
||||
syntax_tree.get_str(&id).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => "wire"
|
||||
};
|
||||
let init = if let Some(init) = unwrap_node!(param_node, ConstantMintypmaxExpression) {
|
||||
match init {
|
||||
RefNode::ConstantMintypmaxExpression(expression) => {
|
||||
// println!("expression {:?}", x);
|
||||
let param_init = sv_parser::NeedParseExpression::Parameter(expression.clone());
|
||||
let (exp, last_locate) = parse_expression(&syntax_tree, ¶m_init);
|
||||
(end_line, end_character) = if last_locate != None {
|
||||
// println!("param {:?} lastlocate {:?}", name, last_locate);
|
||||
(last_locate.unwrap().line, (get_column_by_offset(&content, last_locate.unwrap().offset) + last_locate.unwrap().len) as u32)
|
||||
} else {
|
||||
(end_line, end_character)
|
||||
};
|
||||
// println!("end pos {} {}", end_line, end_character);
|
||||
exp
|
||||
_ => "wire"
|
||||
};
|
||||
let init = if let Some(init) = unwrap_node!(param_node, ConstantMintypmaxExpression) {
|
||||
match init {
|
||||
RefNode::ConstantMintypmaxExpression(expression) => {
|
||||
// println!("expression {:?}", x);
|
||||
let param_init = sv_parser::NeedParseExpression::Parameter(expression.clone());
|
||||
let (exp, last_locate) = parse_expression(&syntax_tree, ¶m_init);
|
||||
(end_line, end_character) = if last_locate != None {
|
||||
// println!("param {:?} lastlocate {:?}", name, last_locate);
|
||||
(last_locate.unwrap().line, (get_column_by_offset(&content, last_locate.unwrap().offset) + last_locate.unwrap().len) as u32)
|
||||
} else {
|
||||
(end_line, end_character)
|
||||
};
|
||||
// println!("end pos {} {}", end_line, end_character);
|
||||
exp
|
||||
}
|
||||
_ => "unknown".to_string()
|
||||
}
|
||||
_ => "unknown".to_string()
|
||||
}
|
||||
} else {
|
||||
"unknown".to_string()
|
||||
};
|
||||
hdlparam.add_parameter(name, net_type, init.as_str(), start_line, start_character, end_line, end_character);
|
||||
} else {
|
||||
"unknown".to_string()
|
||||
};
|
||||
hdlparam.add_parameter(name, net_type, init.as_str(), start_line, start_character, end_line, end_character);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
RefNode::PortDeclaration(x) => {
|
||||
|
@ -340,40 +340,50 @@ fn make_param_desc_hover(param: &crate::core::hdlparam::Parameter, range: &Range
|
||||
pub fn hover_module_declaration(
|
||||
server: &LSPServer,
|
||||
token_name: &str,
|
||||
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 pathbuf = to_escape_path(&pathbuf);
|
||||
let path_string = pathbuf.to_str().unwrap();
|
||||
// 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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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()
|
||||
}
|
||||
// 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()
|
||||
}
|
||||
// _ => {
|
||||
// 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()
|
||||
// }
|
||||
// };
|
||||
|
||||
let module_info = {
|
||||
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 {
|
||||
|
@ -1,3 +1,4 @@
|
||||
#[allow(unused)]
|
||||
use log::info;
|
||||
use regex::Regex;
|
||||
use ropey::Rope;
|
||||
@ -31,12 +32,7 @@ pub fn hover(server: &LSPServer, params: &HoverParams) -> Option<Hover> {
|
||||
if let Some(hover) = hover_macro(server, &line_text, pos, &language_id) {
|
||||
return Some(hover);
|
||||
}
|
||||
|
||||
let scope_tree = server.srcs.scope_tree.read().ok()?;
|
||||
let global_scope = scope_tree.as_ref().unwrap();
|
||||
|
||||
let symbol_definition: GenericDec = global_scope
|
||||
.get_definition(&token, file.text.pos_to_byte(&pos), doc)?;
|
||||
|
||||
// match positional port param
|
||||
if let Some(hover) = hover_position_port_param(server, &line_text, doc, pos, &language_id) {
|
||||
@ -44,12 +40,7 @@ pub fn hover(server: &LSPServer, params: &HoverParams) -> Option<Hover> {
|
||||
}
|
||||
|
||||
// match module name
|
||||
if let Some(hover) = hover_module_declaration(server, &token, &symbol_definition, &language_id) {
|
||||
return Some(hover);
|
||||
}
|
||||
|
||||
// match 正常 symbol
|
||||
if let Some(hover) = hover_common_symbol(server, &token, &symbol_definition, &file, doc, pos, &language_id) {
|
||||
if let Some(hover) = hover_module_declaration(server, &token, &language_id) {
|
||||
return Some(hover);
|
||||
}
|
||||
|
||||
@ -57,6 +48,17 @@ pub fn hover(server: &LSPServer, params: &HoverParams) -> Option<Hover> {
|
||||
if let Some(hover) = hover_format_digit(&line_text, pos, &language_id) {
|
||||
return Some(hover);
|
||||
}
|
||||
|
||||
let scope_tree = server.srcs.scope_tree.read().ok()?;
|
||||
let global_scope = scope_tree.as_ref().unwrap();
|
||||
|
||||
let symbol_definition: GenericDec = global_scope
|
||||
.get_definition(&token, file.text.pos_to_byte(&pos), doc)?;
|
||||
|
||||
// match 正常 symbol
|
||||
if let Some(hover) = hover_common_symbol(server, &token, &symbol_definition, &file, doc, pos, &language_id) {
|
||||
return Some(hover);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
@ -242,7 +244,6 @@ fn hover_common_symbol(
|
||||
|
||||
|
||||
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) => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
use request::{ CustomParamRequest, CustomRequest, DoFastApi };
|
||||
use request::{ CustomParamRequest, CustomRequest, DoFastApi, UpdateFastApi };
|
||||
|
||||
use log::info;
|
||||
use std::sync::Arc;
|
||||
@ -45,6 +45,7 @@ async fn main() {
|
||||
.custom_method("custom/request", CustomRequest)
|
||||
.custom_method("custom/paramRequest", CustomParamRequest)
|
||||
.custom_method("api/fast", DoFastApi)
|
||||
.custom_method("api/update-fast", UpdateFastApi)
|
||||
.finish();
|
||||
|
||||
Server::new(stdin, stdout, socket)
|
||||
|
@ -5,7 +5,6 @@ use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use log::info;
|
||||
use notification::Notification;
|
||||
use ropey::Rope;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tower_lsp::jsonrpc::Result;
|
||||
@ -20,6 +19,7 @@ use crate::utils::*;
|
||||
use crate::server::Backend;
|
||||
use crate::sources::recovery_sv_parse;
|
||||
|
||||
pub mod notification;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CustomRequest;
|
||||
@ -89,7 +89,7 @@ fn make_textdocumenitem_from_path(path_buf: &PathBuf) -> Option<TextDocumentItem
|
||||
}
|
||||
|
||||
/// 前端交互接口: do_fast,输入文件路径,计算出对应的 fast 结构
|
||||
pub fn do_fast<'a>(path: String, backend: &Arc<Backend>) -> Result<FastHdlparam> {
|
||||
pub fn do_fast(path: String, backend: &Arc<Backend>) -> Result<FastHdlparam> {
|
||||
info!("parse fast \"{}\"", path);
|
||||
|
||||
let language_id = get_language_id_by_path_str(&path);
|
||||
@ -201,40 +201,37 @@ fn do_vhdl_fast(path: &str, backend: &Arc<Backend>) -> Result<FastHdlparam> {
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct UpdateFastApi;
|
||||
|
||||
// 下面是服务端发送给客户端的
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct StringNotification {
|
||||
pub content: String
|
||||
impl <'a>tower_lsp::jsonrpc::Method<&'a Arc<Backend>, (DoFastApiRequestParams, ), Result<FastHdlparam>> for UpdateFastApi {
|
||||
type Future = future::Ready<Result<FastHdlparam>>;
|
||||
|
||||
fn invoke(&self, _server: &'a Arc<Backend>, _params: (DoFastApiRequestParams, )) -> Self::Future {
|
||||
let request_param = _params.0;
|
||||
let path = request_param.path;
|
||||
let hdlparam = update_fast(path, _server);
|
||||
future::ready(hdlparam)
|
||||
}
|
||||
}
|
||||
|
||||
impl Notification for StringNotification {
|
||||
const METHOD: &'static str = "update/string";
|
||||
type Params = Self;
|
||||
}
|
||||
pub fn update_fast(path: String, backend: &Arc<Backend>) -> Result<FastHdlparam> {
|
||||
{
|
||||
let fast_sync_controller = backend.server.srcs.fast_sync_controller.read().unwrap();
|
||||
if let Some(fast_lock) = fast_sync_controller.get(&path) {
|
||||
let fast_lock = fast_lock.clone();
|
||||
drop(fast_sync_controller);
|
||||
let _unused = fast_lock.write().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct UpdateFastNotification {
|
||||
pub fast: FastHdlparam,
|
||||
pub path: String
|
||||
}
|
||||
|
||||
impl Notification for UpdateFastNotification {
|
||||
const METHOD: &'static str = "update/fast";
|
||||
type Params = Self;
|
||||
}
|
||||
|
||||
// #[allow(unused)]
|
||||
// pub async fn update_fast_to_client(fast: FastHdlparam, path: &PathBuf) {
|
||||
// // info!("send fast to foreend {:?}", fast);
|
||||
|
||||
// info!("send fast to foreend");
|
||||
// let backend = GLOBAL_BACKEND.get().unwrap();
|
||||
// let path = path.to_str().unwrap_or("").to_string();
|
||||
|
||||
// let params = UpdateFastNotification { fast, path };
|
||||
// info!("backend client: {:?}", backend.client);
|
||||
|
||||
// backend.client.send_notification::<UpdateFastNotification>(params).await;
|
||||
// }
|
||||
// 去缓存中寻找
|
||||
let hdl_param = backend.server.srcs.hdl_param.clone();
|
||||
let path_to_hdl_file = hdl_param.path_to_hdl_file.read().unwrap();
|
||||
if let Some(hdl_file) = path_to_hdl_file.get(&path) {
|
||||
let fast = hdl_file.fast.clone();
|
||||
Ok(fast)
|
||||
} else {
|
||||
do_fast(path, backend)
|
||||
}
|
||||
}
|
42
src/request/notification.rs
Normal file
42
src/request/notification.rs
Normal file
@ -0,0 +1,42 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tower_lsp::lsp_types::notification::Notification;
|
||||
|
||||
use crate::core::hdlparam::FastHdlparam;
|
||||
|
||||
|
||||
// 下面是服务端发送给客户端的
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct StringNotification {
|
||||
pub content: String
|
||||
}
|
||||
|
||||
impl Notification for StringNotification {
|
||||
const METHOD: &'static str = "update/string";
|
||||
type Params = Self;
|
||||
}
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct UpdateFastNotification {
|
||||
pub fast: FastHdlparam,
|
||||
pub path: String
|
||||
}
|
||||
|
||||
impl Notification for UpdateFastNotification {
|
||||
const METHOD: &'static str = "update/fast";
|
||||
type Params = Self;
|
||||
}
|
||||
|
||||
// #[allow(unused)]
|
||||
// pub async fn update_fast_to_client(fast: FastHdlparam, path: &PathBuf) {
|
||||
// // info!("send fast to foreend {:?}", fast);
|
||||
|
||||
// info!("send fast to foreend");
|
||||
// let backend = GLOBAL_BACKEND.get().unwrap();
|
||||
// let path = path.to_str().unwrap_or("").to_string();
|
||||
|
||||
// let params = UpdateFastNotification { fast, path };
|
||||
// info!("backend client: {:?}", backend.client);
|
||||
|
||||
// backend.client.send_notification::<UpdateFastNotification>(params).await;
|
||||
// }
|
@ -4,6 +4,7 @@ use crate::completion::keyword::*;
|
||||
use flexi_logger::LoggerHandle;
|
||||
#[allow(unused)]
|
||||
use log::{debug, info, warn};
|
||||
use notification::DidDeleteFiles;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::string::ToString;
|
||||
use std::sync::{Mutex, RwLock};
|
||||
@ -248,6 +249,10 @@ impl LanguageServer for Backend {
|
||||
self.server.did_change(params);
|
||||
}
|
||||
|
||||
async fn did_delete_files(&self, params: DeleteFilesParams) {
|
||||
self.server.did_delete_files(params);
|
||||
}
|
||||
|
||||
async fn did_save(&self, params: DidSaveTextDocumentParams) {
|
||||
let diagnostics = self.server.did_save(params);
|
||||
self.client
|
||||
|
109
src/sources.rs
109
src/sources.rs
@ -108,6 +108,40 @@ impl LSPServer {
|
||||
&self.conf.read().unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn did_delete_files(&self, params: DeleteFilesParams) {
|
||||
// 删除 sources 内对应的文件
|
||||
for file_delete in params.files {
|
||||
let url = Url::parse(&file_delete.uri).unwrap();
|
||||
let pathbuf = PathBuf::from_str(url.path()).unwrap();
|
||||
let pathbuf = to_escape_path(&pathbuf);
|
||||
let path_string = pathbuf.to_str().unwrap();
|
||||
|
||||
{
|
||||
let mut fast_sync_controller = self.srcs.fast_sync_controller.write().unwrap();
|
||||
fast_sync_controller.remove(path_string);
|
||||
}
|
||||
|
||||
self.srcs.hdl_param.delete_file(path_string);
|
||||
|
||||
{
|
||||
let mut names = self.srcs.names.write().unwrap();
|
||||
names.remove(&url);
|
||||
}
|
||||
|
||||
{
|
||||
let mut global_scope = self.srcs.scope_tree.write().unwrap();
|
||||
match &mut *global_scope {
|
||||
Some(scope) => {
|
||||
scope.defs.retain(|x| x.url() != url);
|
||||
scope.scopes.retain(|x| x.url() != url);
|
||||
},
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The Source struct holds all file specific information
|
||||
@ -176,14 +210,14 @@ pub struct Sources {
|
||||
pub meta: Arc<RwLock<Vec<Arc<RwLock<SourceMeta>>>>>,
|
||||
/// scope tree 类型的树形结构,用于提供 sv 的 lsp
|
||||
pub scope_tree: Arc<RwLock<Option<GenericScope>>>,
|
||||
/// 存储 vhdl design file ir 的对象
|
||||
pub design_file_map: Arc<RwLock<HashMap<String, vhdl_lang::Project>>>,
|
||||
// include directories, passed to parser to resolve `include
|
||||
pub include_dirs: Arc<RwLock<Vec<PathBuf>>>,
|
||||
// source directories
|
||||
pub source_dirs: Arc<RwLock<Vec<PathBuf>>>,
|
||||
/// hdlparam 后端实现
|
||||
pub hdl_param: Arc<HdlParam>,
|
||||
// 同步解析线程和发送 fast 请求的
|
||||
pub fast_sync_controller: Arc<RwLock<HashMap<String, Arc<RwLock<bool>>>>>
|
||||
}
|
||||
|
||||
impl std::default::Default for Sources {
|
||||
@ -199,10 +233,10 @@ impl Sources {
|
||||
names: Arc::new(RwLock::new(HashMap::new())),
|
||||
meta: Arc::new(RwLock::new(Vec::new())),
|
||||
scope_tree: Arc::new(RwLock::new(None)),
|
||||
design_file_map: Arc::new(RwLock::new(HashMap::new())),
|
||||
include_dirs: Arc::new(RwLock::new(Vec::new())),
|
||||
source_dirs: Arc::new(RwLock::new(Vec::new())),
|
||||
hdl_param: Arc::new(HdlParam::new())
|
||||
hdl_param: Arc::new(HdlParam::new()),
|
||||
fast_sync_controller: Arc::new(RwLock::new(HashMap::<String, Arc<RwLock<bool>>>::new()))
|
||||
}
|
||||
}
|
||||
pub fn init(&self) {
|
||||
@ -254,6 +288,15 @@ impl Sources {
|
||||
info!("launch worker to parse {:?}", doc.uri.to_string());
|
||||
let language_id = doc.language_id.to_string();
|
||||
|
||||
// 新建一个 fast controller 用于控制下方的解析线程和外部的请求函数
|
||||
let pathbuf = PathBuf::from_str(&doc.uri.path()).unwrap();
|
||||
let pathbuf = to_escape_path(&pathbuf);
|
||||
let path_string = pathbuf.to_str().unwrap();
|
||||
let mut fast_controller = self.fast_sync_controller.write().unwrap();
|
||||
let fast_lock = Arc::new(RwLock::new(true));
|
||||
fast_controller.insert(path_string.to_string(), fast_lock.clone());
|
||||
drop(fast_controller);
|
||||
|
||||
// spawn parse thread
|
||||
let parse_handle = thread::spawn(move || {
|
||||
let (lock, cvar) = &*valid_parse2;
|
||||
@ -266,28 +309,32 @@ impl Sources {
|
||||
|
||||
info!("do parse in {:?}, language_id: {:?}", uri.to_string(), language_id);
|
||||
|
||||
match language_id.as_str() {
|
||||
"vhdl" => {
|
||||
vhdl_parser_pipeline(
|
||||
&source_handle,
|
||||
&scope_handle,
|
||||
&hdl_param_handle,
|
||||
&text,
|
||||
uri,
|
||||
);
|
||||
},
|
||||
"verilog" | "systemverilog" => {
|
||||
sv_parser_pipeline(
|
||||
&source_handle,
|
||||
&scope_handle,
|
||||
&hdl_param_handle,
|
||||
&text,
|
||||
uri,
|
||||
range,
|
||||
&inc_dirs.read().unwrap()
|
||||
);
|
||||
},
|
||||
_ => {}
|
||||
// 此时 update fast 的地方为 write 会进行阻塞
|
||||
{
|
||||
let _unused = fast_lock.read().unwrap();
|
||||
match language_id.as_str() {
|
||||
"vhdl" => {
|
||||
vhdl_parser_pipeline(
|
||||
&source_handle,
|
||||
&scope_handle,
|
||||
&hdl_param_handle,
|
||||
&text,
|
||||
uri,
|
||||
);
|
||||
},
|
||||
"verilog" | "systemverilog" => {
|
||||
sv_parser_pipeline(
|
||||
&source_handle,
|
||||
&scope_handle,
|
||||
&hdl_param_handle,
|
||||
&text,
|
||||
uri,
|
||||
range,
|
||||
&inc_dirs.read().unwrap()
|
||||
);
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// 通过条件锁进行控制
|
||||
@ -535,6 +582,10 @@ pub fn sv_parser_pipeline(
|
||||
last_change_range: &Option<Range>,
|
||||
include_dirs: &Vec<PathBuf>
|
||||
) {
|
||||
if doc.len_chars() == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let path = match PathBuf::from_str(uri.path()) {
|
||||
Ok(path) => path,
|
||||
Err(error) => {
|
||||
@ -608,6 +659,10 @@ pub fn vhdl_parser_pipeline(
|
||||
doc: &Rope,
|
||||
uri: &Url
|
||||
) {
|
||||
if doc.len_chars() == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let path = match PathBuf::from_str(uri.path()) {
|
||||
Ok(path) => path,
|
||||
Err(error) => {
|
||||
@ -698,6 +753,7 @@ impl LSPSupport for Rope {
|
||||
return self.line_to_char(pos.line as usize) + line_slice.utf16_cu_to_char(pos.character as usize);
|
||||
}
|
||||
fn byte_to_pos(&self, byte_idx: usize) -> Position {
|
||||
// info!("byte_idx: {byte_idx}");
|
||||
return self.char_to_pos(self.byte_to_char(min(byte_idx, self.len_bytes() - 1)));
|
||||
}
|
||||
fn char_to_pos(&self, char_idx: usize) -> Position {
|
||||
@ -737,6 +793,7 @@ impl<'a> LSPSupport for RopeSlice<'a> {
|
||||
self.line_to_char(pos.line as usize) + line_slice.utf16_cu_to_char(pos.character as usize)
|
||||
}
|
||||
fn byte_to_pos(&self, byte_idx: usize) -> Position {
|
||||
// info!("byte_idx: {byte_idx}");
|
||||
self.char_to_pos(self.byte_to_char(min(byte_idx, self.len_bytes() - 1)))
|
||||
}
|
||||
fn char_to_pos(&self, char_idx: usize) -> Position {
|
||||
|
@ -59,6 +59,13 @@ mod test_fast {
|
||||
println!("{:#?}", fast.content);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_controller() {
|
||||
let fast = sv_parser("/home/dide/project/Digital-Test/MipsDesign/src/Controller/controller.v");
|
||||
let fast = fast.unwrap();
|
||||
println!("{:#?}", fast.content[0].params);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_testfiles() {
|
||||
let ws_path = env::current_dir().unwrap();
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit e8e746628785df31545fd465489dc75eba5a6c10
|
||||
Subproject commit a058a7c6411afa7543953bb93a098d9657c408b4
|
Loading…
x
Reference in New Issue
Block a user