去除 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),
|
file.text.pos_to_byte(&doc.position),
|
||||||
&doc.text_document.uri,
|
&doc.text_document.uri,
|
||||||
)?;
|
)?;
|
||||||
|
info!("current completion token: {}", token);
|
||||||
|
|
||||||
comps.items.extend::<Vec<CompletionItem>>(
|
comps.items.extend::<Vec<CompletionItem>>(
|
||||||
server.key_comps
|
server.key_comps
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -420,4 +420,18 @@ impl HdlParam {
|
|||||||
None
|
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::fs::{self, File};
|
||||||
use std::io::BufRead;
|
use std::io::BufRead;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use log::info;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use ropey::Rope;
|
use ropey::Rope;
|
||||||
use tower_lsp::lsp_types::Url;
|
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 = "";
|
let mut ansi_port_last_dir = "";
|
||||||
|
|
||||||
|
// TODO: 搞清楚为什么会出现重复
|
||||||
|
let mut added_param_names = HashSet::<String>::new();
|
||||||
|
|
||||||
let content = syntax_tree.text.text().split('\n')
|
let content = syntax_tree.text.text().split('\n')
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect::<Vec<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) {
|
if let Some(id) = unwrap_node!(x, ParameterIdentifier) {
|
||||||
let id = get_identifier(id).unwrap();
|
let id = get_identifier(id).unwrap();
|
||||||
let name = syntax_tree.get_str(&id).unwrap();
|
let name = syntax_tree.get_str(&id).unwrap();
|
||||||
match unwrap_node!(x, ParameterDeclarationParam, ParameterPortDeclarationParamList) {
|
if !added_param_names.contains(name) {
|
||||||
Some(RefNode::ParameterDeclarationParam(param_node)) => {
|
added_param_names.insert(name.to_string());
|
||||||
// println!("{:?}", param_node);
|
match unwrap_node!(x, ParameterDeclarationParam, ParameterPortDeclarationParamList) {
|
||||||
let keyword_locate = param_node.nodes.0.nodes.0;
|
Some(RefNode::ParameterDeclarationParam(param_node)) => {
|
||||||
// println!("keyword {:#?}", keyword_locate);
|
// println!("{:?}", param_node);
|
||||||
let (start_line, start_character) = (id.line, get_column_by_offset(&content, keyword_locate.offset) as u32);
|
let keyword_locate = param_node.nodes.0.nodes.0;
|
||||||
let (mut end_line, mut end_character) = (id.line, start_character + id.len as u32);
|
// println!("keyword {:#?}", keyword_locate);
|
||||||
let net_type = match unwrap_node!(param_node, DataType) {
|
let (start_line, start_character) = (id.line, get_column_by_offset(&content, keyword_locate.offset) as u32);
|
||||||
Some(RefNode::DataType(data_type)) => {
|
let (mut end_line, mut end_character) = (id.line, start_character + id.len as u32);
|
||||||
let id = unwrap_node!(data_type, SimpleIdentifier, Keyword);
|
let net_type = match unwrap_node!(param_node, DataType) {
|
||||||
if id == None {
|
Some(RefNode::DataType(data_type)) => {
|
||||||
"wire"
|
let id = unwrap_node!(data_type, SimpleIdentifier, Keyword);
|
||||||
} else {
|
if id == None {
|
||||||
let id = get_identifier(id.unwrap()).unwrap();
|
"wire"
|
||||||
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 {
|
} else {
|
||||||
(end_line, end_character)
|
let id = get_identifier(id.unwrap()).unwrap();
|
||||||
};
|
syntax_tree.get_str(&id).unwrap()
|
||||||
// println!("end pos {} {}", end_line, end_character);
|
}
|
||||||
exp
|
|
||||||
}
|
}
|
||||||
_ => "unknown".to_string()
|
_ => "wire"
|
||||||
}
|
};
|
||||||
} else {
|
let init = if let Some(init) = unwrap_node!(param_node, ConstantMintypmaxExpression) {
|
||||||
"unknown".to_string()
|
match init {
|
||||||
};
|
RefNode::ConstantMintypmaxExpression(expression) => {
|
||||||
hdlparam.add_parameter(name, net_type, init.as_str(), start_line, start_character, end_line, end_character);
|
// 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()
|
||||||
|
}
|
||||||
|
} 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) {
|
if let Some(id) = unwrap_node!(x, ParameterIdentifier) {
|
||||||
let id = get_identifier(id).unwrap();
|
let id = get_identifier(id).unwrap();
|
||||||
let name = syntax_tree.get_str(&id).unwrap();
|
let name = syntax_tree.get_str(&id).unwrap();
|
||||||
match unwrap_node!(x, ParameterDeclarationParam, ParameterPortDeclarationParamList) {
|
if !added_param_names.contains(name) {
|
||||||
Some(RefNode::ParameterDeclarationParam(param_node)) => {
|
added_param_names.insert(name.to_string());
|
||||||
// println!("{:?}", param_node);
|
match unwrap_node!(x, ParameterDeclarationParam, ParameterPortDeclarationParamList) {
|
||||||
let keyword_locate = param_node.nodes.0.nodes.0;
|
Some(RefNode::ParameterDeclarationParam(param_node)) => {
|
||||||
// println!("keyword {:#?}", keyword_locate);
|
// println!("{:?}", param_node);
|
||||||
let (start_line, start_character) = (id.line, get_column_by_offset(&content, keyword_locate.offset) as u32);
|
let keyword_locate = param_node.nodes.0.nodes.0;
|
||||||
let (mut end_line, mut end_character) = (id.line, start_character + id.len as u32);
|
// println!("keyword {:#?}", keyword_locate);
|
||||||
let net_type = match unwrap_node!(param_node, DataType) {
|
let (start_line, start_character) = (id.line, get_column_by_offset(&content, keyword_locate.offset) as u32);
|
||||||
Some(RefNode::DataType(data_type)) => {
|
let (mut end_line, mut end_character) = (id.line, start_character + id.len as u32);
|
||||||
let id = unwrap_node!(data_type, SimpleIdentifier, Keyword);
|
let net_type = match unwrap_node!(param_node, DataType) {
|
||||||
if id == None {
|
Some(RefNode::DataType(data_type)) => {
|
||||||
"wire"
|
let id = unwrap_node!(data_type, SimpleIdentifier, Keyword);
|
||||||
} else {
|
if id == None {
|
||||||
let id = get_identifier(id.unwrap()).unwrap();
|
"wire"
|
||||||
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 {
|
} else {
|
||||||
(end_line, end_character)
|
let id = get_identifier(id.unwrap()).unwrap();
|
||||||
};
|
syntax_tree.get_str(&id).unwrap()
|
||||||
// println!("end pos {} {}", end_line, end_character);
|
}
|
||||||
exp
|
|
||||||
}
|
}
|
||||||
_ => "unknown".to_string()
|
_ => "wire"
|
||||||
}
|
};
|
||||||
} else {
|
let init = if let Some(init) = unwrap_node!(param_node, ConstantMintypmaxExpression) {
|
||||||
"unknown".to_string()
|
match init {
|
||||||
};
|
RefNode::ConstantMintypmaxExpression(expression) => {
|
||||||
hdlparam.add_parameter(name, net_type, init.as_str(), start_line, start_character, end_line, end_character);
|
// 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()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"unknown".to_string()
|
||||||
|
};
|
||||||
|
hdlparam.add_parameter(name, net_type, init.as_str(), start_line, start_character, end_line, end_character);
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
}
|
}
|
||||||
_ => ()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RefNode::PortDeclaration(x) => {
|
RefNode::PortDeclaration(x) => {
|
||||||
|
@ -340,40 +340,50 @@ fn make_param_desc_hover(param: &crate::core::hdlparam::Parameter, range: &Range
|
|||||||
pub fn hover_module_declaration(
|
pub fn hover_module_declaration(
|
||||||
server: &LSPServer,
|
server: &LSPServer,
|
||||||
token_name: &str,
|
token_name: &str,
|
||||||
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 pathbuf = to_escape_path(&pathbuf);
|
// let pathbuf = to_escape_path(&pathbuf);
|
||||||
let path_string = pathbuf.to_str().unwrap();
|
// let path_string = pathbuf.to_str().unwrap();
|
||||||
|
|
||||||
let hdlparam = &server.srcs.hdl_param;
|
// let hdlparam = &server.srcs.hdl_param;
|
||||||
let search_result = || {
|
// let search_result = || {
|
||||||
if let Some(hdl_file) = hdlparam.path_to_hdl_file.read().unwrap().get(path_string) {
|
// if let Some(hdl_file) = hdlparam.path_to_hdl_file.read().unwrap().get(path_string) {
|
||||||
for module in &hdl_file.fast.content {
|
// for module in &hdl_file.fast.content {
|
||||||
if module.name == definition.ident {
|
// if module.name == definition.ident {
|
||||||
return Some((module.clone(), path_string.to_string()));
|
// return Some((module.clone(), path_string.to_string()));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
None
|
// None
|
||||||
};
|
// };
|
||||||
search_result()
|
// search_result()
|
||||||
}
|
// }
|
||||||
|
|
||||||
_ => {
|
// _ => {
|
||||||
let 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());
|
// let path_string = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap_or("unknown".to_string());
|
||||||
return Some((module, path_string));
|
// return Some((module, path_string));
|
||||||
}
|
// }
|
||||||
None
|
// None
|
||||||
};
|
// };
|
||||||
search_result()
|
// 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 {
|
if let Some((module, path_string)) = module_info {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#[allow(unused)]
|
||||||
use log::info;
|
use log::info;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use ropey::Rope;
|
use ropey::Rope;
|
||||||
@ -32,11 +33,6 @@ pub fn hover(server: &LSPServer, params: &HoverParams) -> Option<Hover> {
|
|||||||
return Some(hover);
|
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
|
// match positional port param
|
||||||
if let Some(hover) = hover_position_port_param(server, &line_text, doc, pos, &language_id) {
|
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
|
// match module name
|
||||||
if let Some(hover) = hover_module_declaration(server, &token, &symbol_definition, &language_id) {
|
if let Some(hover) = hover_module_declaration(server, &token, &language_id) {
|
||||||
return Some(hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
// match 正常 symbol
|
|
||||||
if let Some(hover) = hover_common_symbol(server, &token, &symbol_definition, &file, doc, pos, &language_id) {
|
|
||||||
return Some(hover);
|
return Some(hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,6 +49,17 @@ pub fn hover(server: &LSPServer, params: &HoverParams) -> Option<Hover> {
|
|||||||
return Some(hover);
|
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
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +244,6 @@ fn hover_common_symbol(
|
|||||||
|
|
||||||
|
|
||||||
if let Some(instance) = hdlparam.walk_instantiation(&path_string, find_name_condition) {
|
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 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) {
|
let mut markdown_comment = match make_hover_with_comment(&file.text, def_line, &language_id, true) {
|
||||||
Some(hover) => {
|
Some(hover) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
use request::{ CustomParamRequest, CustomRequest, DoFastApi };
|
use request::{ CustomParamRequest, CustomRequest, DoFastApi, UpdateFastApi };
|
||||||
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -45,6 +45,7 @@ async fn main() {
|
|||||||
.custom_method("custom/request", CustomRequest)
|
.custom_method("custom/request", CustomRequest)
|
||||||
.custom_method("custom/paramRequest", CustomParamRequest)
|
.custom_method("custom/paramRequest", CustomParamRequest)
|
||||||
.custom_method("api/fast", DoFastApi)
|
.custom_method("api/fast", DoFastApi)
|
||||||
|
.custom_method("api/update-fast", UpdateFastApi)
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
Server::new(stdin, stdout, socket)
|
Server::new(stdin, stdout, socket)
|
||||||
|
@ -5,7 +5,6 @@ use std::path::PathBuf;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use notification::Notification;
|
|
||||||
use ropey::Rope;
|
use ropey::Rope;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tower_lsp::jsonrpc::Result;
|
use tower_lsp::jsonrpc::Result;
|
||||||
@ -20,6 +19,7 @@ use crate::utils::*;
|
|||||||
use crate::server::Backend;
|
use crate::server::Backend;
|
||||||
use crate::sources::recovery_sv_parse;
|
use crate::sources::recovery_sv_parse;
|
||||||
|
|
||||||
|
pub mod notification;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CustomRequest;
|
pub struct CustomRequest;
|
||||||
@ -89,7 +89,7 @@ fn make_textdocumenitem_from_path(path_buf: &PathBuf) -> Option<TextDocumentItem
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 前端交互接口: do_fast,输入文件路径,计算出对应的 fast 结构
|
/// 前端交互接口: 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);
|
info!("parse fast \"{}\"", path);
|
||||||
|
|
||||||
let language_id = get_language_id_by_path_str(&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;
|
||||||
|
|
||||||
// 下面是服务端发送给客户端的
|
impl <'a>tower_lsp::jsonrpc::Method<&'a Arc<Backend>, (DoFastApiRequestParams, ), Result<FastHdlparam>> for UpdateFastApi {
|
||||||
#[derive(Serialize, Deserialize)]
|
type Future = future::Ready<Result<FastHdlparam>>;
|
||||||
pub struct StringNotification {
|
|
||||||
pub content: String
|
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 {
|
pub fn update_fast(path: String, backend: &Arc<Backend>) -> Result<FastHdlparam> {
|
||||||
const METHOD: &'static str = "update/string";
|
{
|
||||||
type Params = Self;
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去缓存中寻找
|
||||||
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[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;
|
|
||||||
// }
|
|
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;
|
use flexi_logger::LoggerHandle;
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
use log::{debug, info, warn};
|
use log::{debug, info, warn};
|
||||||
|
use notification::DidDeleteFiles;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
use std::sync::{Mutex, RwLock};
|
use std::sync::{Mutex, RwLock};
|
||||||
@ -248,6 +249,10 @@ impl LanguageServer for Backend {
|
|||||||
self.server.did_change(params);
|
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) {
|
async fn did_save(&self, params: DidSaveTextDocumentParams) {
|
||||||
let diagnostics = self.server.did_save(params);
|
let diagnostics = self.server.did_save(params);
|
||||||
self.client
|
self.client
|
||||||
|
109
src/sources.rs
109
src/sources.rs
@ -108,6 +108,40 @@ impl LSPServer {
|
|||||||
&self.conf.read().unwrap(),
|
&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
|
/// The Source struct holds all file specific information
|
||||||
@ -176,14 +210,14 @@ pub struct Sources {
|
|||||||
pub meta: Arc<RwLock<Vec<Arc<RwLock<SourceMeta>>>>>,
|
pub meta: Arc<RwLock<Vec<Arc<RwLock<SourceMeta>>>>>,
|
||||||
/// scope tree 类型的树形结构,用于提供 sv 的 lsp
|
/// scope tree 类型的树形结构,用于提供 sv 的 lsp
|
||||||
pub scope_tree: Arc<RwLock<Option<GenericScope>>>,
|
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
|
// include directories, passed to parser to resolve `include
|
||||||
pub include_dirs: Arc<RwLock<Vec<PathBuf>>>,
|
pub include_dirs: Arc<RwLock<Vec<PathBuf>>>,
|
||||||
// source directories
|
// source directories
|
||||||
pub source_dirs: Arc<RwLock<Vec<PathBuf>>>,
|
pub source_dirs: Arc<RwLock<Vec<PathBuf>>>,
|
||||||
/// hdlparam 后端实现
|
/// hdlparam 后端实现
|
||||||
pub hdl_param: Arc<HdlParam>,
|
pub hdl_param: Arc<HdlParam>,
|
||||||
|
// 同步解析线程和发送 fast 请求的
|
||||||
|
pub fast_sync_controller: Arc<RwLock<HashMap<String, Arc<RwLock<bool>>>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::default::Default for Sources {
|
impl std::default::Default for Sources {
|
||||||
@ -199,10 +233,10 @@ impl Sources {
|
|||||||
names: Arc::new(RwLock::new(HashMap::new())),
|
names: Arc::new(RwLock::new(HashMap::new())),
|
||||||
meta: Arc::new(RwLock::new(Vec::new())),
|
meta: Arc::new(RwLock::new(Vec::new())),
|
||||||
scope_tree: Arc::new(RwLock::new(None)),
|
scope_tree: Arc::new(RwLock::new(None)),
|
||||||
design_file_map: Arc::new(RwLock::new(HashMap::new())),
|
|
||||||
include_dirs: Arc::new(RwLock::new(Vec::new())),
|
include_dirs: Arc::new(RwLock::new(Vec::new())),
|
||||||
source_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) {
|
pub fn init(&self) {
|
||||||
@ -254,6 +288,15 @@ impl Sources {
|
|||||||
info!("launch worker to parse {:?}", doc.uri.to_string());
|
info!("launch worker to parse {:?}", doc.uri.to_string());
|
||||||
let language_id = doc.language_id.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
|
// spawn parse thread
|
||||||
let parse_handle = thread::spawn(move || {
|
let parse_handle = thread::spawn(move || {
|
||||||
let (lock, cvar) = &*valid_parse2;
|
let (lock, cvar) = &*valid_parse2;
|
||||||
@ -266,28 +309,32 @@ impl Sources {
|
|||||||
|
|
||||||
info!("do parse in {:?}, language_id: {:?}", uri.to_string(), language_id);
|
info!("do parse in {:?}, language_id: {:?}", uri.to_string(), language_id);
|
||||||
|
|
||||||
match language_id.as_str() {
|
// 此时 update fast 的地方为 write 会进行阻塞
|
||||||
"vhdl" => {
|
{
|
||||||
vhdl_parser_pipeline(
|
let _unused = fast_lock.read().unwrap();
|
||||||
&source_handle,
|
match language_id.as_str() {
|
||||||
&scope_handle,
|
"vhdl" => {
|
||||||
&hdl_param_handle,
|
vhdl_parser_pipeline(
|
||||||
&text,
|
&source_handle,
|
||||||
uri,
|
&scope_handle,
|
||||||
);
|
&hdl_param_handle,
|
||||||
},
|
&text,
|
||||||
"verilog" | "systemverilog" => {
|
uri,
|
||||||
sv_parser_pipeline(
|
);
|
||||||
&source_handle,
|
},
|
||||||
&scope_handle,
|
"verilog" | "systemverilog" => {
|
||||||
&hdl_param_handle,
|
sv_parser_pipeline(
|
||||||
&text,
|
&source_handle,
|
||||||
uri,
|
&scope_handle,
|
||||||
range,
|
&hdl_param_handle,
|
||||||
&inc_dirs.read().unwrap()
|
&text,
|
||||||
);
|
uri,
|
||||||
},
|
range,
|
||||||
_ => {}
|
&inc_dirs.read().unwrap()
|
||||||
|
);
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 通过条件锁进行控制
|
// 通过条件锁进行控制
|
||||||
@ -535,6 +582,10 @@ pub fn sv_parser_pipeline(
|
|||||||
last_change_range: &Option<Range>,
|
last_change_range: &Option<Range>,
|
||||||
include_dirs: &Vec<PathBuf>
|
include_dirs: &Vec<PathBuf>
|
||||||
) {
|
) {
|
||||||
|
if doc.len_chars() == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let path = match PathBuf::from_str(uri.path()) {
|
let path = match PathBuf::from_str(uri.path()) {
|
||||||
Ok(path) => path,
|
Ok(path) => path,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
@ -608,6 +659,10 @@ pub fn vhdl_parser_pipeline(
|
|||||||
doc: &Rope,
|
doc: &Rope,
|
||||||
uri: &Url
|
uri: &Url
|
||||||
) {
|
) {
|
||||||
|
if doc.len_chars() == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let path = match PathBuf::from_str(uri.path()) {
|
let path = match PathBuf::from_str(uri.path()) {
|
||||||
Ok(path) => path,
|
Ok(path) => path,
|
||||||
Err(error) => {
|
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);
|
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 {
|
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)));
|
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 {
|
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)
|
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 {
|
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)))
|
self.char_to_pos(self.byte_to_char(min(byte_idx, self.len_bytes() - 1)))
|
||||||
}
|
}
|
||||||
fn char_to_pos(&self, char_idx: usize) -> Position {
|
fn char_to_pos(&self, char_idx: usize) -> Position {
|
||||||
|
@ -59,6 +59,13 @@ mod test_fast {
|
|||||||
println!("{:#?}", fast.content);
|
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]
|
#[test]
|
||||||
fn test_testfiles() {
|
fn test_testfiles() {
|
||||||
let ws_path = env::current_dir().unwrap();
|
let ws_path = env::current_dir().unwrap();
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit e8e746628785df31545fd465489dc75eba5a6c10
|
Subproject commit a058a7c6411afa7543953bb93a098d9657c408b4
|
Loading…
x
Reference in New Issue
Block a user