去除 fast 计算中 params 重复的问题

This commit is contained in:
锦恢 2024-10-09 17:30:08 +08:00
parent ca13b39c16
commit e0753a25f9
13 changed files with 330 additions and 182 deletions

0
build_all.sh Normal file → Executable file
View File

View 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()

View File

@ -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 机制
}
}

View File

@ -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, &param_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, &param_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, &param_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, &param_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) => {

View File

@ -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 {

View File

@ -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) => {

View File

@ -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)

View File

@ -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)
}
}

View 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;
// }

View File

@ -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

View File

@ -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 {

View File

@ -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