更新文本缓冲区备份的索引模式 | 将 AST 的存储地点从 Sources 中移动到 HdlFile 内部
This commit is contained in:
parent
0cf07fd017
commit
fa7b42f09b
@ -1,4 +1,4 @@
|
|||||||
use crate::{completion::feature::{get_dot_completion, include_path_completion}, core, hover::feature::make_module_profile_code, server::LspServer, sources::LSPSupport, utils::{get_definition_token, get_language_id_by_uri, is_character_ordered_match}};
|
use crate::{completion::feature::{get_dot_completion, include_path_completion}, core, hover::feature::make_module_profile_code, server::LspServer, sources::LSPSupport, utils::{from_uri_to_escape_path_string, get_definition_token, get_language_id_by_uri, is_character_ordered_match}};
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
use log::info;
|
use log::info;
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
@ -12,14 +12,16 @@ pub fn completion(server: &LspServer, params: &CompletionParams) -> Option<Compl
|
|||||||
let pos = doc.position;
|
let pos = doc.position;
|
||||||
let language_id = get_language_id_by_uri(uri);
|
let language_id = get_language_id_by_uri(uri);
|
||||||
|
|
||||||
let file_id = server.srcs.get_id(uri).to_owned();
|
let path_string = from_uri_to_escape_path_string(uri).unwrap();
|
||||||
server.srcs.wait_parse_ready(file_id, false);
|
|
||||||
let file = server.srcs.get_file(file_id)?;
|
|
||||||
let file = file.read().ok()?;
|
|
||||||
let line_text = file.text.line(doc.position.line as usize);
|
|
||||||
let token = get_definition_token(&line_text, doc.position);
|
|
||||||
|
|
||||||
let line_text = file.text.line(pos.line as usize);
|
// 等待解析完成
|
||||||
|
server.srcs.wait_parse_ready(&path_string, false);
|
||||||
|
let source = server.srcs.get_source(&path_string)?;
|
||||||
|
let source = source.read().ok()?;
|
||||||
|
|
||||||
|
// 获取当前这行的结果和当前光标所在的 token
|
||||||
|
let line_text = source.text.line(doc.position.line as usize);
|
||||||
|
let token = get_definition_token(&line_text, doc.position);
|
||||||
|
|
||||||
let response = match ¶ms.context {
|
let response = match ¶ms.context {
|
||||||
Some(context) => match context.trigger_kind {
|
Some(context) => match context.trigger_kind {
|
||||||
@ -65,7 +67,7 @@ pub fn completion(server: &LspServer, params: &CompletionParams) -> Option<Compl
|
|||||||
// 去除如下几种情况:module textmacro
|
// 去除如下几种情况:module textmacro
|
||||||
let mut completion_items = server.srcs.get_completions(
|
let mut completion_items = server.srcs.get_completions(
|
||||||
&token,
|
&token,
|
||||||
file.text.pos_to_byte(&doc.position),
|
source.text.pos_to_byte(&doc.position),
|
||||||
&doc.text_document.uri,
|
&doc.text_document.uri,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use std::{path::PathBuf, str::FromStr};
|
|||||||
use log::info;
|
use log::info;
|
||||||
use ropey::{Rope, RopeSlice};
|
use ropey::{Rope, RopeSlice};
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
use crate::{hover::feature::make_vhdl_module_profile_code, utils::to_escape_path};
|
use crate::{hover::feature::make_vhdl_module_profile_code, utils::{from_uri_to_escape_path_string, to_escape_path}};
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
use crate::{server::LspServer, sources::LSPSupport, utils::get_language_id_by_uri};
|
use crate::{server::LspServer, sources::LSPSupport, utils::get_language_id_by_uri};
|
||||||
|
|
||||||
@ -16,14 +16,16 @@ pub fn completion(server: &LspServer, params: &CompletionParams) -> Option<Compl
|
|||||||
let doc = ¶ms.text_document_position;
|
let doc = ¶ms.text_document_position;
|
||||||
let uri = ¶ms.text_document_position.text_document.uri;
|
let uri = ¶ms.text_document_position.text_document.uri;
|
||||||
let language_id = get_language_id_by_uri(uri);
|
let language_id = get_language_id_by_uri(uri);
|
||||||
|
let path_string = from_uri_to_escape_path_string(uri).unwrap();
|
||||||
|
|
||||||
let file_id = server.srcs.get_id(uri).to_owned();
|
// 等待解析完成
|
||||||
server.srcs.wait_parse_ready(file_id, false);
|
server.srcs.wait_parse_ready(&path_string, false);
|
||||||
let file = server.srcs.get_file(file_id)?;
|
let source = server.srcs.get_source(&path_string)?;
|
||||||
let file = file.read().ok()?;
|
let source = source.read().ok()?;
|
||||||
let line_text = file.text.line(doc.position.line as usize);
|
|
||||||
|
let line_text = source.text.line(doc.position.line as usize);
|
||||||
let token = get_completion_token(
|
let token = get_completion_token(
|
||||||
&file.text,
|
&source.text,
|
||||||
line_text.clone(),
|
line_text.clone(),
|
||||||
doc.position,
|
doc.position,
|
||||||
);
|
);
|
||||||
@ -65,7 +67,7 @@ pub fn completion(server: &LspServer, params: &CompletionParams) -> Option<Compl
|
|||||||
info!("trigger vhdl dot completion");
|
info!("trigger vhdl dot completion");
|
||||||
let mut completion_items = server.srcs.get_completions(
|
let mut completion_items = server.srcs.get_completions(
|
||||||
&token,
|
&token,
|
||||||
file.text.pos_to_byte(&doc.position),
|
source.text.pos_to_byte(&doc.position),
|
||||||
&doc.text_document.uri,
|
&doc.text_document.uri,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -84,7 +86,7 @@ pub fn completion(server: &LspServer, params: &CompletionParams) -> Option<Compl
|
|||||||
// 1. 先根据 AST 获取上下文补全项
|
// 1. 先根据 AST 获取上下文补全项
|
||||||
let mut completion_items = server.srcs.get_completions(
|
let mut completion_items = server.srcs.get_completions(
|
||||||
&token,
|
&token,
|
||||||
file.text.pos_to_byte(&doc.position),
|
source.text.pos_to_byte(&doc.position),
|
||||||
&doc.text_document.uri,
|
&doc.text_document.uri,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -110,43 +112,7 @@ pub fn completion(server: &LspServer, params: &CompletionParams) -> Option<Compl
|
|||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
None => {
|
None => None
|
||||||
let trigger = prev_char(&file.text, &doc.position);
|
|
||||||
match trigger {
|
|
||||||
// '.' => Some(server.srcs.get_dot_completions(
|
|
||||||
// token.trim_end_matches('.'),
|
|
||||||
// file.text.pos_to_byte(&doc.position),
|
|
||||||
// &doc.text_document.uri,
|
|
||||||
// )?),
|
|
||||||
// '$' => Some(CompletionList {
|
|
||||||
// is_incomplete: false,
|
|
||||||
// items: server.sys_tasks.clone(),
|
|
||||||
// }),
|
|
||||||
// '`' => Some(CompletionList {
|
|
||||||
// is_incomplete: false,
|
|
||||||
// items: server.directives.clone(),
|
|
||||||
// }),
|
|
||||||
_ => {
|
|
||||||
let mut comps = server.srcs.get_completions(
|
|
||||||
&token,
|
|
||||||
file.text.pos_to_byte(&doc.position),
|
|
||||||
&doc.text_document.uri,
|
|
||||||
)?;
|
|
||||||
comps.items.extend::<Vec<CompletionItem>>(
|
|
||||||
server.vhdl_keyword_completiom_items
|
|
||||||
.iter()
|
|
||||||
.filter(|x| x.label.starts_with(&token))
|
|
||||||
.cloned()
|
|
||||||
.collect(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// comps.items.extend(vhdl_project_completion_items);
|
|
||||||
|
|
||||||
comps.items.dedup_by_key(|i| i.label.clone());
|
|
||||||
Some(comps)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
// eprintln!("comp response: {}", now.elapsed().as_millis());
|
// eprintln!("comp response: {}", now.elapsed().as_millis());
|
||||||
Some(CompletionResponse::List(response?))
|
Some(CompletionResponse::List(response?))
|
||||||
|
@ -6,6 +6,8 @@ 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;
|
||||||
|
|
||||||
|
use crate::sources::AstLike;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, PartialEq, PartialOrd, Eq, Ord, Deserialize)]
|
#[derive(Debug, Clone, Serialize, PartialEq, PartialOrd, Eq, Ord, Deserialize)]
|
||||||
pub struct Position {
|
pub struct Position {
|
||||||
pub line: u32,
|
pub line: u32,
|
||||||
@ -451,7 +453,9 @@ pub struct HdlFile {
|
|||||||
/// 名字到 module 映射的 map
|
/// 名字到 module 映射的 map
|
||||||
pub name_to_module: HashMap<String, Module>,
|
pub name_to_module: HashMap<String, Module>,
|
||||||
/// 解析器生成的额外信息
|
/// 解析器生成的额外信息
|
||||||
pub parse_result: sv_parser::common::ParseResult
|
pub parse_result: sv_parser::common::ParseResult,
|
||||||
|
/// 解析器生成的 AST 或者类似 AST 的数据结构
|
||||||
|
pub ast_like: Option<AstLike>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HdlParam {
|
pub struct HdlParam {
|
||||||
@ -476,7 +480,8 @@ impl HdlParam {
|
|||||||
&self,
|
&self,
|
||||||
path: String,
|
path: String,
|
||||||
fast: FastHdlparam,
|
fast: FastHdlparam,
|
||||||
parse_result: sv_parser::common::ParseResult
|
parse_result: sv_parser::common::ParseResult,
|
||||||
|
ast_like: Option<AstLike>
|
||||||
) {
|
) {
|
||||||
let mut fast_map = self.path_to_hdl_file.write().unwrap();
|
let mut fast_map = self.path_to_hdl_file.write().unwrap();
|
||||||
// 构建映射
|
// 构建映射
|
||||||
@ -490,7 +495,7 @@ impl HdlParam {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let file = HdlFile { fast, name_to_module, parse_result };
|
let file = HdlFile { fast, name_to_module, parse_result, ast_like };
|
||||||
fast_map.insert(path, file);
|
fast_map.insert(path, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::core::scope_tree::common::{Definition, Scope};
|
use crate::core::scope_tree::common::{Definition, Scope};
|
||||||
use crate::utils::get_definition_token;
|
|
||||||
use crate::server::LspServer;
|
|
||||||
use crate::sources::LSPSupport;
|
use crate::sources::LSPSupport;
|
||||||
|
use crate::utils::{from_uri_to_escape_path_string, get_definition_token};
|
||||||
|
use crate::server::LspServer;
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
use log::info;
|
use log::info;
|
||||||
@ -9,18 +9,21 @@ use tower_lsp::lsp_types::*;
|
|||||||
use super::feature::*;
|
use super::feature::*;
|
||||||
|
|
||||||
pub fn goto_definition(server: &LspServer, params: &GotoDefinitionParams) -> Option<GotoDefinitionResponse> {
|
pub fn goto_definition(server: &LspServer, params: &GotoDefinitionParams) -> Option<GotoDefinitionResponse> {
|
||||||
let doc = ¶ms.text_document_position_params.text_document.uri;
|
let uri = ¶ms.text_document_position_params.text_document.uri;
|
||||||
let pos = params.text_document_position_params.position;
|
let pos = params.text_document_position_params.position;
|
||||||
let file_id = server.srcs.get_id(doc).to_owned();
|
|
||||||
server.srcs.wait_parse_ready(file_id, false);
|
|
||||||
let file = server.srcs.get_file(file_id)?;
|
|
||||||
let file = file.read().ok()?;
|
|
||||||
|
|
||||||
let line_text = file.text.line(pos.line as usize);
|
let path_string = from_uri_to_escape_path_string(uri).unwrap();
|
||||||
|
|
||||||
|
// 等待解析完成
|
||||||
|
server.srcs.wait_parse_ready(&path_string, false);
|
||||||
|
let source = server.srcs.get_source(&path_string)?;
|
||||||
|
let source = source.read().ok()?;
|
||||||
|
|
||||||
|
let line_text = source.text.line(pos.line as usize);
|
||||||
let token: String = get_definition_token(&line_text, pos);
|
let token: String = get_definition_token(&line_text, pos);
|
||||||
|
|
||||||
// match include
|
// match include
|
||||||
if let Some(definition) = goto_include_definition(doc, &line_text, pos) {
|
if let Some(definition) = goto_include_definition(uri, &line_text, pos) {
|
||||||
return Some(definition);
|
return Some(definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +36,7 @@ pub fn goto_definition(server: &LspServer, params: &GotoDefinitionParams) -> Opt
|
|||||||
let scope_tree = server.srcs.scope_tree.read().ok()?;
|
let scope_tree = server.srcs.scope_tree.read().ok()?;
|
||||||
|
|
||||||
// match position port & param
|
// match position port & param
|
||||||
if let Some(definition) = goto_position_port_param_definition(server, &line_text, doc, pos) {
|
if let Some(definition) = goto_position_port_param_definition(server, &line_text, uri, pos) {
|
||||||
return Some(definition);
|
return Some(definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,11 +45,11 @@ pub fn goto_definition(server: &LspServer, params: &GotoDefinitionParams) -> Opt
|
|||||||
return Some(definition);
|
return Some(definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
let byte_idx = file.text.pos_to_byte(&pos);
|
let byte_idx = source.text.pos_to_byte(&pos);
|
||||||
let global_scope = scope_tree.as_ref()?;
|
let global_scope = scope_tree.as_ref()?;
|
||||||
let def = global_scope.get_definition(&token, byte_idx, doc)?;
|
let def = global_scope.get_definition(&token, byte_idx, uri)?;
|
||||||
|
|
||||||
let def_pos = file.text.byte_to_pos(def.byte_idx());
|
let def_pos = source.text.byte_to_pos(def.byte_idx());
|
||||||
Some(GotoDefinitionResponse::Scalar(Location::new(
|
Some(GotoDefinitionResponse::Scalar(Location::new(
|
||||||
def.url(),
|
def.url(),
|
||||||
Range::new(def_pos, def_pos),
|
Range::new(def_pos, def_pos),
|
||||||
|
@ -3,22 +3,28 @@ use std::{path::PathBuf, str::FromStr};
|
|||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
use log::info;
|
use log::info;
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
use crate::{server::LspServer, utils::{from_lsp_pos, get_definition_token, srcpos_to_location, to_escape_path}};
|
use crate::{server::LspServer, utils::{from_lsp_pos, from_uri_to_escape_path_string, get_definition_token, srcpos_to_location, to_escape_path}};
|
||||||
|
|
||||||
pub fn goto_vhdl_definition(server: &LspServer, params: &GotoDefinitionParams) -> Option<GotoDefinitionResponse> {
|
pub fn goto_vhdl_definition(server: &LspServer, params: &GotoDefinitionParams) -> Option<GotoDefinitionResponse> {
|
||||||
let doc = ¶ms.text_document_position_params.text_document.uri;
|
let uri = ¶ms.text_document_position_params.text_document.uri;
|
||||||
let pos = params.text_document_position_params.position;
|
let pos = params.text_document_position_params.position;
|
||||||
let file_id = server.srcs.get_id(doc).to_owned();
|
|
||||||
server.srcs.wait_parse_ready(file_id, false);
|
|
||||||
let file = server.srcs.get_file(file_id)?;
|
|
||||||
let file = file.read().ok()?;
|
|
||||||
|
|
||||||
let line_text = file.text.line(pos.line as usize);
|
let path_string = from_uri_to_escape_path_string(uri).unwrap();
|
||||||
|
|
||||||
|
// 等待解析完成
|
||||||
|
server.srcs.wait_parse_ready(&path_string, false);
|
||||||
|
let source = server.srcs.get_source(&path_string)?;
|
||||||
|
let source = source.read().ok()?;
|
||||||
|
|
||||||
|
let line_text = source.text.line(pos.line as usize);
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
let token: String = get_definition_token(&line_text, pos);
|
let token: String = get_definition_token(&line_text, pos);
|
||||||
|
|
||||||
let project = server.srcs.vhdl_project.read().ok()?;
|
let project = server.srcs.vhdl_project.read().ok()?;
|
||||||
let global_project = project.as_ref().unwrap();
|
let global_project = project.as_ref().unwrap();
|
||||||
let path = match PathBuf::from_str(doc.path()) {
|
|
||||||
|
let path = match PathBuf::from_str(uri.path()) {
|
||||||
Ok(path) => path,
|
Ok(path) => path,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
info!("error happen in vhdl <hover>: {:?}", error);
|
info!("error happen in vhdl <hover>: {:?}", error);
|
||||||
|
@ -35,8 +35,6 @@ pub use modelsim::*;
|
|||||||
pub fn provide_diagnostics(
|
pub fn provide_diagnostics(
|
||||||
uri: Url,
|
uri: Url,
|
||||||
rope: &Rope,
|
rope: &Rope,
|
||||||
#[allow(unused_variables)]
|
|
||||||
files: Vec<Url>,
|
|
||||||
configuration: &LspConfiguration,
|
configuration: &LspConfiguration,
|
||||||
server: &LspServer
|
server: &LspServer
|
||||||
) -> PublishDiagnosticsParams {
|
) -> PublishDiagnosticsParams {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{server::LspServer, utils::{get_definition_token, get_language_id_by_uri}};
|
use crate::{server::LspServer, utils::{from_uri_to_escape_path_string, get_definition_token, get_language_id_by_uri}};
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
|
|
||||||
mod sv;
|
mod sv;
|
||||||
@ -11,11 +11,15 @@ impl LspServer {
|
|||||||
) -> Option<Vec<DocumentHighlight>> {
|
) -> Option<Vec<DocumentHighlight>> {
|
||||||
let uri = ¶ms.text_document_position_params.text_document.uri;
|
let uri = ¶ms.text_document_position_params.text_document.uri;
|
||||||
let pos = params.text_document_position_params.position;
|
let pos = params.text_document_position_params.position;
|
||||||
let file_id = self.srcs.get_id(&uri).to_owned();
|
|
||||||
self.srcs.wait_parse_ready(file_id, false);
|
let path_string = from_uri_to_escape_path_string(uri).unwrap();
|
||||||
let file = self.srcs.get_file(file_id)?;
|
|
||||||
let file = file.read().ok()?;
|
// 等待解析完成
|
||||||
let line_text = file.text.line(pos.line as usize);
|
self.srcs.wait_parse_ready(&path_string, false);
|
||||||
|
let source = self.srcs.get_source(&path_string)?;
|
||||||
|
let source = source.read().ok()?;
|
||||||
|
|
||||||
|
let line_text = source.text.line(pos.line as usize);
|
||||||
let token = get_definition_token(&line_text, pos);
|
let token = get_definition_token(&line_text, pos);
|
||||||
|
|
||||||
let language_id = get_language_id_by_uri(&uri);
|
let language_id = get_language_id_by_uri(&uri);
|
||||||
@ -32,7 +36,7 @@ impl LspServer {
|
|||||||
"verilog" | "systemverilog" => sv::document_highlight(
|
"verilog" | "systemverilog" => sv::document_highlight(
|
||||||
self,
|
self,
|
||||||
&token,
|
&token,
|
||||||
&file,
|
&source,
|
||||||
pos,
|
pos,
|
||||||
&uri
|
&uri
|
||||||
),
|
),
|
||||||
|
@ -3,7 +3,7 @@ use log::info;
|
|||||||
use sv_parser::{RefNode, SyntaxTree};
|
use sv_parser::{RefNode, SyntaxTree};
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
|
|
||||||
use crate::{server::LspServer, sources::{LSPSupport, ParseIR, Source}};
|
use crate::{server::LspServer, sources::{AstLike, LSPSupport, Source}, utils::from_uri_to_escape_path_string};
|
||||||
use crate::core::scope_tree::parse::get_ident;
|
use crate::core::scope_tree::parse::get_ident;
|
||||||
use crate::core::scope_tree::common::Scope;
|
use crate::core::scope_tree::common::Scope;
|
||||||
|
|
||||||
@ -16,29 +16,26 @@ pub fn document_highlight(
|
|||||||
) -> Option<Vec<DocumentHighlight>> {
|
) -> Option<Vec<DocumentHighlight>> {
|
||||||
let scope_tree = server.srcs.scope_tree.read().ok()?;
|
let scope_tree = server.srcs.scope_tree.read().ok()?;
|
||||||
|
|
||||||
|
let path_string = from_uri_to_escape_path_string(uri).unwrap();
|
||||||
|
|
||||||
// use the byte_idx of the definition if possible, otherwise use the cursor
|
// use the byte_idx of the definition if possible, otherwise use the cursor
|
||||||
let byte_idx =
|
let byte_idx = match scope_tree.as_ref()?.get_definition(token, file.text.pos_to_byte(&pos), uri) {
|
||||||
match scope_tree
|
|
||||||
.as_ref()?
|
|
||||||
.get_definition(token, file.text.pos_to_byte(&pos), uri)
|
|
||||||
{
|
|
||||||
Some(def) => def.byte_idx,
|
Some(def) => def.byte_idx,
|
||||||
None => file.text.pos_to_byte(&pos),
|
None => file.text.pos_to_byte(&pos),
|
||||||
};
|
};
|
||||||
let syntax_tree = file.parse_ir.as_ref()?;
|
|
||||||
match syntax_tree {
|
// 获取对应的 AST
|
||||||
ParseIR::SyntaxTree(syntax_tree) => {
|
let path_to_hdl_file = server.srcs.hdl_param.path_to_hdl_file.read().unwrap();
|
||||||
|
if let Some(hdl_file) = path_to_hdl_file.get(&path_string) {
|
||||||
|
if let Some(AstLike::Svlog(syntax_tree)) = &hdl_file.ast_like {
|
||||||
let references = all_identifiers(&syntax_tree, &token);
|
let references = all_identifiers(&syntax_tree, &token);
|
||||||
Some(
|
let highlights = scope_tree.as_ref()?.document_highlights(&uri, &file.text, references, byte_idx);
|
||||||
scope_tree
|
Some(highlights)
|
||||||
.as_ref()?
|
} else {
|
||||||
.document_highlights(&uri, &file.text, references, byte_idx),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
info!("error happen in [sv_document_highlight]");
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use log::info;
|
|||||||
use sv_parser::{RefNode, SyntaxTree};
|
use sv_parser::{RefNode, SyntaxTree};
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
|
|
||||||
use crate::{server::LspServer, sources::{LSPSupport, ParseIR, Source}};
|
use crate::{server::LspServer, sources::{LSPSupport, Source}};
|
||||||
use crate::core::scope_tree::parse::get_ident;
|
use crate::core::scope_tree::parse::get_ident;
|
||||||
use crate::core::scope_tree::common::Scope;
|
use crate::core::scope_tree::common::Scope;
|
||||||
|
|
||||||
@ -16,30 +16,15 @@ pub fn document_highlight(
|
|||||||
let scope_tree = server.srcs.scope_tree.read().ok()?;
|
let scope_tree = server.srcs.scope_tree.read().ok()?;
|
||||||
|
|
||||||
// use the byte_idx of the definition if possible, otherwise use the cursor
|
// use the byte_idx of the definition if possible, otherwise use the cursor
|
||||||
let byte_idx =
|
let byte_idx = match scope_tree.as_ref()?.get_definition(token, file.text.pos_to_byte(&pos), uri) {
|
||||||
match scope_tree
|
|
||||||
.as_ref()?
|
|
||||||
.get_definition(token, file.text.pos_to_byte(&pos), uri)
|
|
||||||
{
|
|
||||||
Some(def) => def.byte_idx,
|
Some(def) => def.byte_idx,
|
||||||
None => file.text.pos_to_byte(&pos),
|
None => file.text.pos_to_byte(&pos),
|
||||||
};
|
};
|
||||||
let syntax_tree = file.parse_ir.as_ref()?;
|
|
||||||
match syntax_tree {
|
// TODO: 完成剩余部分
|
||||||
ParseIR::SyntaxTree(syntax_tree) => {
|
|
||||||
let references = all_identifiers(&syntax_tree, &token);
|
|
||||||
Some(
|
|
||||||
scope_tree
|
|
||||||
.as_ref()?
|
|
||||||
.document_highlights(&uri, &file.text, references, byte_idx),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
info!("error happen in [vhdl_document_highlight]");
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// return all identifiers in a syntax tree matching a given token
|
/// return all identifiers in a syntax tree matching a given token
|
||||||
fn all_identifiers(syntax_tree: &SyntaxTree, token: &str) -> Vec<(String, usize)> {
|
fn all_identifiers(syntax_tree: &SyntaxTree, token: &str) -> Vec<(String, usize)> {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{core::scope_tree::common::Scope, server::LspServer};
|
use crate::{core::scope_tree::common::Scope, server::LspServer, utils::from_uri_to_escape_path_string};
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
|
|
||||||
pub fn document_symbol(
|
pub fn document_symbol(
|
||||||
@ -6,13 +6,17 @@ pub fn document_symbol(
|
|||||||
params: &DocumentSymbolParams
|
params: &DocumentSymbolParams
|
||||||
) -> Option<DocumentSymbolResponse> {
|
) -> Option<DocumentSymbolResponse> {
|
||||||
let uri = ¶ms.text_document.uri;
|
let uri = ¶ms.text_document.uri;
|
||||||
let file_id = server.srcs.get_id(uri).to_owned();
|
|
||||||
server.srcs.wait_parse_ready(file_id, false);
|
let path_string = from_uri_to_escape_path_string(uri).unwrap();
|
||||||
let file = server.srcs.get_file(file_id)?;
|
|
||||||
let file = file.read().ok()?;
|
// 等待解析完成
|
||||||
|
server.srcs.wait_parse_ready(&path_string, false);
|
||||||
|
let source = server.srcs.get_source(&path_string)?;
|
||||||
|
let source = source.read().ok()?;
|
||||||
|
|
||||||
let scope_tree = server.srcs.scope_tree.read().ok()?;
|
let scope_tree = server.srcs.scope_tree.read().ok()?;
|
||||||
|
|
||||||
Some(DocumentSymbolResponse::Nested(
|
Some(DocumentSymbolResponse::Nested(
|
||||||
scope_tree.as_ref()?.document_symbols(uri, &file.text),
|
scope_tree.as_ref()?.document_symbols(uri, &source.text),
|
||||||
))
|
))
|
||||||
}
|
}
|
@ -4,16 +4,17 @@ use std::{path::PathBuf, str::FromStr};
|
|||||||
use log::info;
|
use log::info;
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
use vhdl_lang::{EntHierarchy, Token};
|
use vhdl_lang::{EntHierarchy, Token};
|
||||||
use crate::{server::LspServer, utils::{to_escape_path, to_lsp_range, to_symbol_kind}};
|
use crate::{server::LspServer, utils::{from_uri_to_escape_path_string, to_escape_path, to_lsp_range, to_symbol_kind}};
|
||||||
|
|
||||||
pub fn document_symbol(server: &LspServer, params: &DocumentSymbolParams) -> Option<DocumentSymbolResponse> {
|
pub fn document_symbol(server: &LspServer, params: &DocumentSymbolParams) -> Option<DocumentSymbolResponse> {
|
||||||
// info!("enter document symbol");
|
|
||||||
|
|
||||||
let uri = ¶ms.text_document.uri;
|
let uri = ¶ms.text_document.uri;
|
||||||
let file_id = server.srcs.get_id(&uri).to_owned();
|
let path_string = from_uri_to_escape_path_string(uri).unwrap();
|
||||||
server.srcs.wait_parse_ready(file_id, false);
|
|
||||||
let file = server.srcs.get_file(file_id)?;
|
// 等待解析完成
|
||||||
let file = file.read().ok()?;
|
server.srcs.wait_parse_ready(&path_string, false);
|
||||||
|
// let source_handle = server.srcs.get_source(&path_string)?;
|
||||||
|
// let source_handle = source_handle.read().ok()?;
|
||||||
|
|
||||||
let scope_tree = server.srcs.scope_tree.read().ok()?;
|
let scope_tree = server.srcs.scope_tree.read().ok()?;
|
||||||
|
|
||||||
let project = server.srcs.vhdl_project.read().ok()?;
|
let project = server.srcs.vhdl_project.read().ok()?;
|
||||||
|
@ -4,7 +4,7 @@ use regex::Regex;
|
|||||||
use ropey::Rope;
|
use ropey::Rope;
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
use crate::{core::{hdlparam::{Instance, Module}, scope_tree::common::Scope}, hover::{to_escape_path, BracketMatchResult, BracketMatcher}, server::LspServer, sources::LSPSupport};
|
use crate::{core::{hdlparam::{Instance, Module}, scope_tree::common::Scope}, hover::{to_escape_path, BracketMatchResult, BracketMatcher}, server::LspServer, sources::LSPSupport};
|
||||||
use super::feature::*;
|
use super::{feature::*, from_uri_to_escape_path_string};
|
||||||
use std::{path::PathBuf, str::FromStr, sync::RwLockReadGuard};
|
use std::{path::PathBuf, str::FromStr, sync::RwLockReadGuard};
|
||||||
|
|
||||||
use crate::core::scope_tree::common::*;
|
use crate::core::scope_tree::common::*;
|
||||||
@ -12,19 +12,22 @@ use crate::core::scope_tree::common::*;
|
|||||||
use super::{get_definition_token, get_language_id_by_uri};
|
use super::{get_definition_token, get_language_id_by_uri};
|
||||||
|
|
||||||
pub fn hover(server: &LspServer, params: &HoverParams) -> Option<Hover> {
|
pub fn hover(server: &LspServer, params: &HoverParams) -> Option<Hover> {
|
||||||
let doc = ¶ms.text_document_position_params.text_document.uri;
|
let uri = ¶ms.text_document_position_params.text_document.uri;
|
||||||
let pos: Position = params.text_document_position_params.position;
|
let pos: Position = params.text_document_position_params.position;
|
||||||
let file_id: usize = server.srcs.get_id(doc).to_owned();
|
|
||||||
server.srcs.wait_parse_ready(file_id, false);
|
|
||||||
let file: std::sync::Arc<std::sync::RwLock<crate::sources::Source>> = server.srcs.get_file(file_id)?;
|
|
||||||
let file: std::sync::RwLockReadGuard<'_, crate::sources::Source> = file.read().ok()?;
|
|
||||||
|
|
||||||
let line_text = file.text.line(pos.line as usize);
|
let path_string = from_uri_to_escape_path_string(uri).unwrap();
|
||||||
|
|
||||||
|
// 等待解析完成
|
||||||
|
server.srcs.wait_parse_ready(&path_string, false);
|
||||||
|
let source = server.srcs.get_source(&path_string)?;
|
||||||
|
let source = source.read().ok()?;
|
||||||
|
|
||||||
|
let line_text = source.text.line(pos.line as usize);
|
||||||
let token: String = get_definition_token(&line_text, pos);
|
let token: String = get_definition_token(&line_text, pos);
|
||||||
let language_id = get_language_id_by_uri(doc);
|
let language_id = get_language_id_by_uri(uri);
|
||||||
|
|
||||||
// match `include
|
// match `include
|
||||||
if let Some(hover) = hover_include(doc, &line_text, pos, &language_id) {
|
if let Some(hover) = hover_include(uri, &line_text, pos, &language_id) {
|
||||||
return Some(hover);
|
return Some(hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,13 +38,13 @@ pub fn hover(server: &LspServer, params: &HoverParams) -> Option<Hover> {
|
|||||||
|
|
||||||
// info!("enter hover_position_port_param");
|
// info!("enter hover_position_port_param");
|
||||||
// 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, uri, pos, &language_id) {
|
||||||
return Some(hover);
|
return Some(hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
// info!("enter hover_module_declaration");
|
// info!("enter hover_module_declaration");
|
||||||
// match module name
|
// match module name
|
||||||
if hover_for_module(server, pos, doc) {
|
if hover_for_module(server, pos, uri) {
|
||||||
if let Some(hover) = hover_module_declaration(server, &token, &language_id) {
|
if let Some(hover) = hover_module_declaration(server, &token, &language_id) {
|
||||||
return Some(hover);
|
return Some(hover);
|
||||||
}
|
}
|
||||||
@ -56,10 +59,10 @@ pub fn hover(server: &LspServer, params: &HoverParams) -> Option<Hover> {
|
|||||||
let global_scope = scope_tree.as_ref().unwrap();
|
let global_scope = scope_tree.as_ref().unwrap();
|
||||||
|
|
||||||
let symbol_definition: GenericDec = global_scope
|
let symbol_definition: GenericDec = global_scope
|
||||||
.get_definition(&token, file.text.pos_to_byte(&pos), doc)?;
|
.get_definition(&token, source.text.pos_to_byte(&pos), uri)?;
|
||||||
|
|
||||||
// match 正常 symbol
|
// match 正常 symbol
|
||||||
if let Some(hover) = hover_common_symbol(server, &token, &symbol_definition, &file, doc, pos, &language_id) {
|
if let Some(hover) = hover_common_symbol(server, &token, &symbol_definition, &source, uri, pos, &language_id) {
|
||||||
return Some(hover);
|
return Some(hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,24 +7,25 @@ use tower_lsp::lsp_types::*;
|
|||||||
use crate::{core::hdlparam::{Instance, Module}, hover::{BracketMatchResult, BracketMatcher}, server::LspServer};
|
use crate::{core::hdlparam::{Instance, Module}, hover::{BracketMatchResult, BracketMatcher}, server::LspServer};
|
||||||
use crate::core::scope_tree::common::*;
|
use crate::core::scope_tree::common::*;
|
||||||
|
|
||||||
use super::{from_lsp_pos, get_definition_token, get_language_id_by_uri, to_escape_path};
|
use super::{from_lsp_pos, from_uri_to_escape_path_string, get_definition_token, get_language_id_by_uri, to_escape_path};
|
||||||
|
|
||||||
pub fn hover(server: &LspServer, params: &HoverParams) -> Option<Hover> {
|
pub fn hover(server: &LspServer, params: &HoverParams) -> Option<Hover> {
|
||||||
let doc = ¶ms.text_document_position_params.text_document.uri;
|
let uri = ¶ms.text_document_position_params.text_document.uri;
|
||||||
let pos: Position = params.text_document_position_params.position;
|
let pos: Position = params.text_document_position_params.position;
|
||||||
let file_id: usize = server.srcs.get_id(doc).to_owned();
|
|
||||||
server.srcs.wait_parse_ready(file_id, false);
|
|
||||||
let file: std::sync::Arc<std::sync::RwLock<crate::sources::Source>> = server.srcs.get_file(file_id)?;
|
|
||||||
let file: std::sync::RwLockReadGuard<'_, crate::sources::Source> = file.read().ok()?;
|
|
||||||
|
|
||||||
let line_text = file.text.line(pos.line as usize);
|
let path_string = from_uri_to_escape_path_string(uri).unwrap();
|
||||||
let token: String = get_definition_token(&line_text, pos);
|
|
||||||
let language_id = get_language_id_by_uri(doc);
|
// 等待解析完成
|
||||||
|
server.srcs.wait_parse_ready(&path_string, false);
|
||||||
|
let source = server.srcs.get_source(&path_string)?;
|
||||||
|
let source = source.read().ok()?;
|
||||||
|
|
||||||
|
let line_text = source.text.line(pos.line as usize);
|
||||||
|
|
||||||
let project = server.srcs.vhdl_project.read().ok()?;
|
let project = server.srcs.vhdl_project.read().ok()?;
|
||||||
let global_project = project.as_ref().unwrap();
|
let global_project = project.as_ref().unwrap();
|
||||||
|
|
||||||
let path = match PathBuf::from_str(doc.path()) {
|
let path = match PathBuf::from_str(uri.path()) {
|
||||||
Ok(path) => path,
|
Ok(path) => path,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
info!("error happen in vhdl <hover>: {:?}", error);
|
info!("error happen in vhdl <hover>: {:?}", error);
|
||||||
|
@ -15,18 +15,15 @@ pub fn inlay_hint(server: &LspServer, params: &InlayHintParams) -> Option<Vec<In
|
|||||||
let path_string = path.to_str().unwrap();
|
let path_string = path.to_str().unwrap();
|
||||||
let visible_range = core::hdlparam::Range::from_lsp_range(¶ms.range);
|
let visible_range = core::hdlparam::Range::from_lsp_range(¶ms.range);
|
||||||
|
|
||||||
let fast_map = server.srcs.hdl_param.path_to_hdl_file.read().unwrap();
|
// 等待解析完成
|
||||||
let file_id = server.srcs.get_id(¶ms.text_document.uri);
|
server.srcs.wait_parse_ready(&path_string, false);
|
||||||
let file = server.srcs.get_file(file_id);
|
let source = server.srcs.get_source(&path_string)?;
|
||||||
if file.is_none() {
|
let source = source.read().ok()?;
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let file = file.unwrap();
|
let rope = &source.text;
|
||||||
let file = file.read().unwrap();
|
|
||||||
let rope = &file.text;
|
|
||||||
// 先找到 当前 所在的 hdlfile
|
// 先找到 当前 所在的 hdlfile
|
||||||
if let Some(hdl_file) = &fast_map.get(path_string) {
|
let path_to_hdl_file = server.srcs.hdl_param.path_to_hdl_file.read().unwrap();
|
||||||
|
if let Some(hdl_file) = &path_to_hdl_file.get(path_string) {
|
||||||
let fast = &hdl_file.fast;
|
let fast = &hdl_file.fast;
|
||||||
let mut hints = Vec::<InlayHint>::new();
|
let mut hints = Vec::<InlayHint>::new();
|
||||||
// 制作例化模块的 hint
|
// 制作例化模块的 hint
|
||||||
|
@ -200,7 +200,8 @@ fn do_sv_fast(
|
|||||||
hdl_param.update_hdl_file(
|
hdl_param.update_hdl_file(
|
||||||
path.to_string(),
|
path.to_string(),
|
||||||
fast.clone(),
|
fast.clone(),
|
||||||
parse_result
|
parse_result,
|
||||||
|
Some(crate::sources::AstLike::Svlog(syntax_tree))
|
||||||
);
|
);
|
||||||
return Ok(fast);
|
return Ok(fast);
|
||||||
}
|
}
|
||||||
@ -260,7 +261,8 @@ fn do_vhdl_fast(
|
|||||||
hdl_param.update_hdl_file(
|
hdl_param.update_hdl_file(
|
||||||
path.to_string(),
|
path.to_string(),
|
||||||
ip_fast.clone(),
|
ip_fast.clone(),
|
||||||
sv_parser::common::ParseResult::new()
|
sv_parser::common::ParseResult::new(),
|
||||||
|
None
|
||||||
);
|
);
|
||||||
return Ok(ip_fast);
|
return Ok(ip_fast);
|
||||||
} else if let Some(vhdl_project) = &mut *vhdl_project.write().unwrap() {
|
} else if let Some(vhdl_project) = &mut *vhdl_project.write().unwrap() {
|
||||||
@ -293,7 +295,8 @@ fn do_vhdl_fast(
|
|||||||
hdl_param.update_hdl_file(
|
hdl_param.update_hdl_file(
|
||||||
path.to_string(),
|
path.to_string(),
|
||||||
fast.clone(),
|
fast.clone(),
|
||||||
sv_parser::common::ParseResult::new()
|
sv_parser::common::ParseResult::new(),
|
||||||
|
None
|
||||||
);
|
);
|
||||||
return Ok(fast);
|
return Ok(fast);
|
||||||
}
|
}
|
||||||
@ -338,7 +341,8 @@ fn do_vhdl_fast(
|
|||||||
hdl_param.update_hdl_file(
|
hdl_param.update_hdl_file(
|
||||||
path.to_string(),
|
path.to_string(),
|
||||||
fast.clone(),
|
fast.clone(),
|
||||||
sv_parser::common::ParseResult::new()
|
sv_parser::common::ParseResult::new(),
|
||||||
|
None
|
||||||
);
|
);
|
||||||
return Ok(fast);
|
return Ok(fast);
|
||||||
}
|
}
|
||||||
@ -371,9 +375,10 @@ pub fn sync_fast(
|
|||||||
|
|
||||||
{
|
{
|
||||||
let uri = Url::from_file_path(path.to_string()).unwrap();
|
let uri = Url::from_file_path(path.to_string()).unwrap();
|
||||||
let file_id = backend.server.srcs.get_id(&uri);
|
let path_string = from_uri_to_escape_path_string(&uri).unwrap();
|
||||||
if let Some(file) = backend.server.srcs.get_file(file_id) {
|
|
||||||
let _unused = file.read().unwrap();
|
if let Some(source_handle) = backend.server.srcs.get_source(&path_string) {
|
||||||
|
let _unused = source_handle.read().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
263
src/sources.rs
263
src/sources.rs
@ -16,6 +16,7 @@ use log::{info, debug, error};
|
|||||||
use pathdiff::diff_paths;
|
use pathdiff::diff_paths;
|
||||||
use ropey::{Rope, RopeSlice};
|
use ropey::{Rope, RopeSlice};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
use vhdl_lang::ast::DesignFile;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env::current_dir;
|
use std::env::current_dir;
|
||||||
@ -25,7 +26,8 @@ use std::ops::Range as StdRange;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::{Arc, Condvar, Mutex, RwLock};
|
use std::sync::Arc;
|
||||||
|
use std::sync::{Condvar, Mutex, RwLock};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use sv_parser::*;
|
use sv_parser::*;
|
||||||
use vhdl_lang::Project;
|
use vhdl_lang::Project;
|
||||||
@ -36,10 +38,10 @@ impl LspServer {
|
|||||||
pub fn did_open(&self, params: DidOpenTextDocumentParams) -> PublishDiagnosticsParams {
|
pub fn did_open(&self, params: DidOpenTextDocumentParams) -> PublishDiagnosticsParams {
|
||||||
let document: TextDocumentItem = params.text_document;
|
let document: TextDocumentItem = params.text_document;
|
||||||
let uri = document.uri.clone();
|
let uri = document.uri.clone();
|
||||||
|
let path_string = from_uri_to_escape_path_string(&uri).unwrap();
|
||||||
|
|
||||||
// check if doc is already added
|
if self.srcs.contain_source(&path_string) {
|
||||||
if self.srcs.names.read().unwrap().contains_key(&document.uri) {
|
// 如果已经存在了,则进行增量更新
|
||||||
// convert to a did_change that replace the entire text
|
|
||||||
self.did_change(DidChangeTextDocumentParams {
|
self.did_change(DidChangeTextDocumentParams {
|
||||||
text_document: VersionedTextDocumentIdentifier::new(document.uri, document.version),
|
text_document: VersionedTextDocumentIdentifier::new(document.uri, document.version),
|
||||||
content_changes: vec![TextDocumentContentChangeEvent {
|
content_changes: vec![TextDocumentContentChangeEvent {
|
||||||
@ -49,18 +51,17 @@ impl LspServer {
|
|||||||
}],
|
}],
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
// 如果不存在,直接加入其中
|
||||||
self.srcs.add(self, document);
|
self.srcs.add(self, document);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 生成诊断信息
|
// 生成诊断信息
|
||||||
let urls = self.srcs.names.read().unwrap().keys().cloned().collect();
|
if let Some(source) = self.srcs.get_source(&path_string) {
|
||||||
let file_id = self.srcs.get_id(&uri);
|
let source = source.read().unwrap();
|
||||||
if let Some(file) = self.srcs.get_file(file_id) {
|
|
||||||
let file = file.read().unwrap();
|
|
||||||
let diagnostics = provide_diagnostics(
|
let diagnostics = provide_diagnostics(
|
||||||
uri,
|
uri,
|
||||||
&file.text,
|
&source.text,
|
||||||
urls,
|
|
||||||
&self.configuration.read().unwrap(),
|
&self.configuration.read().unwrap(),
|
||||||
&self
|
&self
|
||||||
);
|
);
|
||||||
@ -75,25 +76,26 @@ impl LspServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn did_change(&self, params: DidChangeTextDocumentParams) {
|
pub fn did_change(&self, params: DidChangeTextDocumentParams) {
|
||||||
let file_id = self.srcs.get_id(¶ms.text_document.uri);
|
let path_string = from_uri_to_escape_path_string(¶ms.text_document.uri).unwrap();
|
||||||
if let Some(file) = self.srcs.get_file(file_id) {
|
|
||||||
let mut file = file.write().unwrap();
|
if let Some(source) = self.srcs.get_source(&path_string) {
|
||||||
|
let mut source = source.write().unwrap();
|
||||||
|
|
||||||
// 根据输入的 change 动态更新对应的代码的文本片段
|
// 根据输入的 change 动态更新对应的代码的文本片段
|
||||||
for change in params.content_changes {
|
for change in params.content_changes {
|
||||||
if change.range.is_none() {
|
if change.range.is_none() {
|
||||||
file.text = Rope::from_str(&change.text);
|
source.text = Rope::from_str(&change.text);
|
||||||
} else {
|
} else {
|
||||||
file.text.apply_change(&change);
|
source.text.apply_change(&change);
|
||||||
}
|
}
|
||||||
file.last_change_range = change.range;
|
source.last_change_range = change.range;
|
||||||
}
|
}
|
||||||
file.version = params.text_document.version;
|
source.version = params.text_document.version;
|
||||||
drop(file);
|
drop(source);
|
||||||
|
|
||||||
// invalidate syntaxtree and wake parse thread
|
// 唤醒解析线程
|
||||||
let meta_data = self.srcs.get_meta_data(file_id).unwrap();
|
let source_status = self.srcs.get_source_status(&path_string).unwrap();
|
||||||
let (lock, cvar) = &*meta_data.read().unwrap().valid_parse;
|
let (lock, cvar) = &*source_status.read().unwrap().valid_parse;
|
||||||
let mut valid = lock.lock().unwrap();
|
let mut valid = lock.lock().unwrap();
|
||||||
*valid = false;
|
*valid = false;
|
||||||
cvar.notify_all();
|
cvar.notify_all();
|
||||||
@ -103,16 +105,14 @@ impl LspServer {
|
|||||||
/// 保存时触发的行为
|
/// 保存时触发的行为
|
||||||
/// - 提供诊断信息(主要是第三方诊断器,因为 save 后磁盘上的内容就和缓冲区中的一致了)
|
/// - 提供诊断信息(主要是第三方诊断器,因为 save 后磁盘上的内容就和缓冲区中的一致了)
|
||||||
pub fn did_save(&self, params: DidSaveTextDocumentParams) -> PublishDiagnosticsParams {
|
pub fn did_save(&self, params: DidSaveTextDocumentParams) -> PublishDiagnosticsParams {
|
||||||
let urls = self.srcs.names.read().unwrap().keys().cloned().collect();
|
let uri = params.text_document.uri;
|
||||||
let file_id = self.srcs.get_id(¶ms.text_document.uri);
|
let path_string = from_uri_to_escape_path_string(&uri).unwrap();
|
||||||
let uri = params.text_document.uri.clone();
|
|
||||||
|
|
||||||
if let Some(file) = self.srcs.get_file(file_id) {
|
if let Some(source) = self.srcs.get_source(&path_string) {
|
||||||
let file = file.read().unwrap();
|
let source = source.read().unwrap();
|
||||||
provide_diagnostics(
|
provide_diagnostics(
|
||||||
uri,
|
uri,
|
||||||
&file.text,
|
&source.text,
|
||||||
urls,
|
|
||||||
&self.configuration.read().unwrap(),
|
&self.configuration.read().unwrap(),
|
||||||
&self
|
&self
|
||||||
)
|
)
|
||||||
@ -128,41 +128,46 @@ impl LspServer {
|
|||||||
pub fn did_delete_files(&self, params: DeleteFilesParams) {
|
pub fn did_delete_files(&self, params: DeleteFilesParams) {
|
||||||
// 删除 sources 内对应的文件
|
// 删除 sources 内对应的文件
|
||||||
for file_delete in params.files {
|
for file_delete in params.files {
|
||||||
let url = Url::parse(&file_delete.uri).unwrap();
|
let uri = Url::parse(&file_delete.uri).unwrap();
|
||||||
let pathbuf = PathBuf::from_str(url.path()).unwrap();
|
let path_string = from_uri_to_escape_path_string(&uri).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();
|
let mut fast_sync_controller = self.srcs.fast_sync_controller.write().unwrap();
|
||||||
fast_sync_controller.remove(path_string);
|
fast_sync_controller.remove(&path_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.srcs.hdl_param.delete_file(path_string);
|
// hdlparam
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut names = self.srcs.names.write().unwrap();
|
self.srcs.hdl_param.delete_file(&path_string);
|
||||||
names.remove(&url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 文本缓冲器
|
||||||
|
{
|
||||||
|
let mut sources = self.srcs.sources.write().unwrap();
|
||||||
|
sources.remove(&path_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
// scope tree
|
||||||
{
|
{
|
||||||
let mut global_scope = self.srcs.scope_tree.write().unwrap();
|
let mut global_scope = self.srcs.scope_tree.write().unwrap();
|
||||||
match &mut *global_scope {
|
match &mut *global_scope {
|
||||||
Some(scope) => {
|
Some(scope) => {
|
||||||
scope.defs.retain(|x| x.url() != url);
|
scope.defs.retain(|x| x.url() != uri);
|
||||||
scope.scopes.retain(|x| x.url() != url);
|
scope.scopes.retain(|x| x.url() != uri);
|
||||||
},
|
},
|
||||||
None => {},
|
None => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// vhdl
|
||||||
{
|
{
|
||||||
let mut vhdl_project = self.srcs.vhdl_project.write().unwrap();
|
let mut vhdl_project = self.srcs.vhdl_project.write().unwrap();
|
||||||
match &mut *vhdl_project {
|
match &mut *vhdl_project {
|
||||||
Some(vhdl_project) => {
|
Some(vhdl_project) => {
|
||||||
let config_file_strs = vhdl_project.config_file_strs.clone()
|
let config_file_strs = vhdl_project.config_file_strs.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|x| x != path_string)
|
.filter(|x| x != &path_string)
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>();
|
||||||
let mut messages = Vec::new();
|
let mut messages = Vec::new();
|
||||||
let config_str = format!(
|
let config_str = format!(
|
||||||
@ -188,46 +193,40 @@ impl LspServer {
|
|||||||
|
|
||||||
/// The Source struct holds all file specific information
|
/// The Source struct holds all file specific information
|
||||||
pub struct Source {
|
pub struct Source {
|
||||||
/// id
|
/// 文件的 uri
|
||||||
pub id: usize,
|
|
||||||
/// uri
|
|
||||||
pub uri: Url,
|
pub uri: Url,
|
||||||
/// 代码文本信息
|
/// 代码文本信息
|
||||||
pub text: Rope,
|
pub text: Rope,
|
||||||
/// 版本号
|
/// 版本号
|
||||||
pub version: i32,
|
pub version: i32,
|
||||||
/// 解析的 IR,分为 DesignFile(VHDL)和 SyntaxTree(SV)两种
|
/// 是否已经完成至少一次解析,用于在初始化相关的函数中使用
|
||||||
pub parse_ir: Option<ParseIR>,
|
pub finish_at_least_once: bool,
|
||||||
/// 用于在解析失败时恢复解析的量
|
/// 用于在解析失败时恢复解析的量
|
||||||
pub last_change_range: Option<Range>,
|
pub last_change_range: Option<Range>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ParseIR {
|
|
||||||
/// 基于 vhdl-parser 的IR,存放 VHDL
|
|
||||||
#[allow(unused)]
|
|
||||||
DesignFile(vhdl_lang::ast::DesignFile),
|
|
||||||
/// 存放 sv 的 IR
|
|
||||||
SyntaxTree(sv_parser::SyntaxTree)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// file metadata, including whether or not the syntax tree is up to date
|
/// file metadata, including whether or not the syntax tree is up to date
|
||||||
pub struct SourceMeta {
|
pub struct SourceStatus {
|
||||||
pub id: usize,
|
/// 当前解析的文件的路径
|
||||||
|
pub path: String,
|
||||||
|
/// 用于进行控制的锁
|
||||||
pub valid_parse: Arc<(Mutex<bool>, Condvar)>,
|
pub valid_parse: Arc<(Mutex<bool>, Condvar)>,
|
||||||
|
/// 解析当前文件的线程句柄
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub parse_handle: JoinHandle<()>,
|
pub parse_handle: JoinHandle<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum AstLike {
|
||||||
|
Svlog(SyntaxTree),
|
||||||
|
Vhdl(DesignFile)
|
||||||
|
}
|
||||||
|
|
||||||
/// The Sources struct manages all source files
|
/// The Sources struct manages all source files
|
||||||
pub struct Sources {
|
pub struct Sources {
|
||||||
// all files
|
// 用于存储后端中的前端的文本缓冲区的备份
|
||||||
pub files: Arc<RwLock<Vec<Arc<RwLock<Source>>>>>,
|
pub sources: Arc<RwLock<HashMap<String, Arc<RwLock<Source>>>>>,
|
||||||
// map file urls to id
|
// 存储类似于线程句柄等数据的结构
|
||||||
pub names: Arc<RwLock<HashMap<Url, usize>>>,
|
pub sources_status: Arc<RwLock<HashMap<String, Arc<RwLock<SourceStatus>>>>>,
|
||||||
// file metadata
|
|
||||||
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 project, store vhdl design files, do lsp
|
// vhdl project, store vhdl design files, do lsp
|
||||||
@ -253,16 +252,15 @@ impl std::default::Default for Sources {
|
|||||||
impl Sources {
|
impl Sources {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
files: Arc::new(RwLock::new(Vec::new())),
|
sources: Arc::new(RwLock::new(HashMap::new())),
|
||||||
names: Arc::new(RwLock::new(HashMap::new())),
|
sources_status: Arc::new(RwLock::new(HashMap::new())),
|
||||||
meta: Arc::new(RwLock::new(Vec::new())),
|
|
||||||
scope_tree: Arc::new(RwLock::new(None)),
|
scope_tree: Arc::new(RwLock::new(None)),
|
||||||
vhdl_project: Arc::new(RwLock::new(None)),
|
vhdl_project: Arc::new(RwLock::new(None)),
|
||||||
include_dirs: Arc::new(RwLock::new(Vec::new())),
|
include_dirs: Arc::new(RwLock::new(Vec::new())),
|
||||||
primitive_text: Arc::new(PrimitiveText::new()),
|
primitive_text: Arc::new(PrimitiveText::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())),
|
fast_sync_controller: Arc::new(RwLock::new(HashMap::new())),
|
||||||
lsp_configuration: Arc::new(RwLock::new(HashMap::<String, Value>::new()))
|
lsp_configuration: Arc::new(RwLock::new(HashMap::new()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,13 +277,20 @@ impl Sources {
|
|||||||
hdl_param_handle.update_hdl_file(
|
hdl_param_handle.update_hdl_file(
|
||||||
fake_path,
|
fake_path,
|
||||||
template.fast,
|
template.fast,
|
||||||
sv_parser::common::ParseResult::new()
|
sv_parser::common::ParseResult::new(),
|
||||||
|
None
|
||||||
);
|
);
|
||||||
primitive_text_handle.update_text(&name, &template.text);
|
primitive_text_handle.update_text(&name, &template.text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 判断当前文本缓冲器中是否存在指定路径的文件的备份
|
||||||
|
pub fn contain_source(&self, path_string: &str) -> bool {
|
||||||
|
let sources = self.sources.read().unwrap();
|
||||||
|
sources.contains_key(path_string)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init_vhdl_project(&self, extension_path: &str) {
|
pub fn init_vhdl_project(&self, extension_path: &str) {
|
||||||
let project_handle = self.vhdl_project.clone();
|
let project_handle = self.vhdl_project.clone();
|
||||||
let mut global_project = project_handle.write().unwrap();
|
let mut global_project = project_handle.write().unwrap();
|
||||||
@ -319,25 +324,30 @@ impl Sources {
|
|||||||
#[allow(clippy::mutex_atomic)] // https://github.com/rust-lang/rust-clippy/issues/1516
|
#[allow(clippy::mutex_atomic)] // https://github.com/rust-lang/rust-clippy/issues/1516
|
||||||
let valid_parse = Arc::new((Mutex::new(false), Condvar::new()));
|
let valid_parse = Arc::new((Mutex::new(false), Condvar::new()));
|
||||||
let valid_parse2 = valid_parse.clone();
|
let valid_parse2 = valid_parse.clone();
|
||||||
let mut files = self.files.write().unwrap();
|
|
||||||
let source = Arc::new(RwLock::new(Source {
|
let mut sources = self.sources.write().unwrap();
|
||||||
id: files.len(),
|
|
||||||
|
// uri 转换为标准文件路径
|
||||||
|
let path_string = from_uri_to_escape_path_string(&doc.uri).unwrap();
|
||||||
|
|
||||||
|
// 为新加入的文件构建后端文本缓冲器副本
|
||||||
|
let source_handle = Arc::new(RwLock::new(Source {
|
||||||
uri: doc.uri.clone(),
|
uri: doc.uri.clone(),
|
||||||
text: Rope::from_str(&doc.text),
|
text: Rope::from_str(&doc.text),
|
||||||
version: doc.version,
|
version: doc.version,
|
||||||
parse_ir: None,
|
finish_at_least_once: false,
|
||||||
last_change_range: None,
|
last_change_range: None,
|
||||||
}));
|
}));
|
||||||
let source_handle = source.clone();
|
|
||||||
|
let parse_loop_used_source_handle = source_handle.clone();
|
||||||
let scope_handle = self.scope_tree.clone();
|
let scope_handle = self.scope_tree.clone();
|
||||||
let project_handle = self.vhdl_project.clone();
|
let project_handle = self.vhdl_project.clone();
|
||||||
let hdl_param_handle = self.hdl_param.clone();
|
let hdl_param_handle = self.hdl_param.clone();
|
||||||
let inc_dirs = self.include_dirs.clone();
|
let inc_dirs = self.include_dirs.clone();
|
||||||
|
|
||||||
|
let configuration = server.configuration.clone();
|
||||||
let uri = doc.uri.clone();
|
let uri = doc.uri.clone();
|
||||||
|
|
||||||
let conf = server.configuration.clone();
|
|
||||||
|
|
||||||
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();
|
||||||
|
|
||||||
@ -345,12 +355,14 @@ impl Sources {
|
|||||||
let pathbuf = PathBuf::from_str(&doc.uri.path()).unwrap();
|
let pathbuf = PathBuf::from_str(&doc.uri.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();
|
||||||
|
|
||||||
|
// 用于进行 fast 的同步(和 request 那边的同步)
|
||||||
let mut fast_controller = self.fast_sync_controller.write().unwrap();
|
let mut fast_controller = self.fast_sync_controller.write().unwrap();
|
||||||
let fast_lock = Arc::new(RwLock::new(true));
|
let fast_lock = Arc::new(RwLock::new(true));
|
||||||
fast_controller.insert(path_string.to_string(), fast_lock.clone());
|
fast_controller.insert(path_string.to_string(), fast_lock.clone());
|
||||||
drop(fast_controller);
|
drop(fast_controller);
|
||||||
|
|
||||||
// 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;
|
||||||
loop {
|
loop {
|
||||||
@ -360,7 +372,7 @@ impl Sources {
|
|||||||
{
|
{
|
||||||
let _unused = fast_lock.read().unwrap();
|
let _unused = fast_lock.read().unwrap();
|
||||||
// 从内存中直接获取增量更新系统维护的代码文本
|
// 从内存中直接获取增量更新系统维护的代码文本
|
||||||
let file = source_handle.read().unwrap();
|
let file = parse_loop_used_source_handle.read().unwrap();
|
||||||
let text = file.text.clone();
|
let text = file.text.clone();
|
||||||
let uri = &file.uri.clone();
|
let uri = &file.uri.clone();
|
||||||
|
|
||||||
@ -369,8 +381,8 @@ impl Sources {
|
|||||||
match language_id.as_str() {
|
match language_id.as_str() {
|
||||||
"vhdl" => {
|
"vhdl" => {
|
||||||
vhdl_parser_pipeline(
|
vhdl_parser_pipeline(
|
||||||
&conf,
|
&configuration,
|
||||||
&source_handle,
|
&parse_loop_used_source_handle,
|
||||||
&scope_handle,
|
&scope_handle,
|
||||||
&project_handle,
|
&project_handle,
|
||||||
&hdl_param_handle,
|
&hdl_param_handle,
|
||||||
@ -380,8 +392,8 @@ impl Sources {
|
|||||||
},
|
},
|
||||||
"verilog" | "systemverilog" => {
|
"verilog" | "systemverilog" => {
|
||||||
sv_parser_pipeline(
|
sv_parser_pipeline(
|
||||||
&conf,
|
&configuration,
|
||||||
&source_handle,
|
&parse_loop_used_source_handle,
|
||||||
&scope_handle,
|
&scope_handle,
|
||||||
&hdl_param_handle,
|
&hdl_param_handle,
|
||||||
&text,
|
&text,
|
||||||
@ -403,52 +415,47 @@ impl Sources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
files.push(source);
|
|
||||||
let fid = files.len() - 1;
|
// 将新的文件缓冲区数据结构加入 sources 和 status 中
|
||||||
self.meta
|
sources.insert(path_string.to_string(), source_handle);
|
||||||
.write()
|
|
||||||
.unwrap()
|
let mut source_status = self.sources_status.write().unwrap();
|
||||||
.push(Arc::new(RwLock::new(SourceMeta {
|
let status_handle = Arc::new(RwLock::new(SourceStatus {
|
||||||
id: fid,
|
path: path_string.to_string(),
|
||||||
valid_parse,
|
valid_parse,
|
||||||
parse_handle,
|
parse_handle,
|
||||||
})));
|
}));
|
||||||
|
source_status.insert(path_string.to_string(), status_handle);
|
||||||
self.names.write().unwrap().insert(doc.uri, fid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get file by id
|
/// 输入路径,获得路径对应的文件的文本缓冲器对象 source
|
||||||
pub fn get_file(&self, id: usize) -> Option<Arc<RwLock<Source>>> {
|
pub fn get_source(&self, path_string: &str) -> Option<Arc<RwLock<Source>>> {
|
||||||
let files = self.files.read().ok()?;
|
let sources = self.sources.read().unwrap();
|
||||||
for file in files.iter() {
|
if let Some(source_handle) = sources.get(path_string) {
|
||||||
let source = file.read().ok()?;
|
return Some(source_handle.clone());
|
||||||
if source.id == id {
|
|
||||||
return Some(file.clone());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get metadata by file id
|
/// 输入路径,获得路径对应的文件的文本缓冲器对象 source 的运行时状态
|
||||||
pub fn get_meta_data(&self, id: usize) -> Option<Arc<RwLock<SourceMeta>>> {
|
pub fn get_source_status(&self, path_string: &str) -> Option<Arc<RwLock<SourceStatus>>> {
|
||||||
let meta = self.meta.read().ok()?;
|
let source_status = self.sources_status.read().unwrap();
|
||||||
for data in meta.iter() {
|
if let Some(status_handle) = source_status.get(path_string) {
|
||||||
let i = data.read().ok()?;
|
return Some(status_handle.clone());
|
||||||
if i.id == id {
|
|
||||||
return Some(data.clone());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// wait for a valid parse
|
/// 等待解析线程创建完成 ?
|
||||||
pub fn wait_parse_ready(&self, id: usize, wait_valid: bool) {
|
pub fn wait_parse_ready(&self, path_string: &str, wait_valid: bool) {
|
||||||
if let Some(file) = self.get_file(id) {
|
if let Some(source_handle) = self.get_source(path_string) {
|
||||||
let file = file.read().unwrap();
|
let source = source_handle.read().unwrap();
|
||||||
if file.parse_ir.is_none() || wait_valid {
|
if !source.finish_at_least_once || wait_valid {
|
||||||
drop(file);
|
drop(source);
|
||||||
let meta_data = self.get_meta_data(id).unwrap();
|
let source_status_handle = self.get_source_status(path_string).unwrap(); // status 和 source 是同步创建的,要有一起有
|
||||||
let (lock, cvar) = &*meta_data.read().unwrap().valid_parse;
|
let (lock, cvar) = &*source_status_handle.read().unwrap().valid_parse;
|
||||||
let mut valid = lock.lock().unwrap();
|
let mut valid = lock.lock().unwrap();
|
||||||
while !*valid {
|
while !*valid {
|
||||||
valid = cvar.wait(valid).unwrap();
|
valid = cvar.wait(valid).unwrap();
|
||||||
@ -457,11 +464,6 @@ impl Sources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get file id from url
|
|
||||||
pub fn get_id(&self, uri: &Url) -> usize {
|
|
||||||
*self.names.read().unwrap().get(uri).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 根据输入 token,计算当前
|
/// 根据输入 token,计算当前
|
||||||
pub fn get_completions(
|
pub fn get_completions(
|
||||||
&self,
|
&self,
|
||||||
@ -721,13 +723,14 @@ pub fn sv_parser_pipeline(
|
|||||||
hdl_param_handle.update_hdl_file(
|
hdl_param_handle.update_hdl_file(
|
||||||
escape_path_string.to_string(),
|
escape_path_string.to_string(),
|
||||||
fast,
|
fast,
|
||||||
parse_result
|
parse_result,
|
||||||
|
Some(AstLike::Svlog(syntax_tree))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let parse_ir = ParseIR::SyntaxTree(syntax_tree);
|
|
||||||
file.parse_ir = Some(parse_ir);
|
file.finish_at_least_once = true;
|
||||||
} else {
|
} else {
|
||||||
file.parse_ir = None;
|
file.finish_at_least_once = false;
|
||||||
}
|
}
|
||||||
// file.syntax_tree = syntax_tree;
|
// file.syntax_tree = syntax_tree;
|
||||||
drop(file);
|
drop(file);
|
||||||
@ -849,14 +852,11 @@ pub fn vhdl_parser_pipeline(
|
|||||||
let mut global_project = project_handle.write().unwrap();
|
let mut global_project = project_handle.write().unwrap();
|
||||||
match &mut *global_project {
|
match &mut *global_project {
|
||||||
Some(vhdl_project) => {
|
Some(vhdl_project) => {
|
||||||
let mut file = source_handle.write().unwrap();
|
let mut source = source_handle.write().unwrap();
|
||||||
let text = doc.to_string();
|
let text = doc.to_string();
|
||||||
let mut scope_tree = if let Some(design_file) = vhdl_parse_str(&escape_path, &text) {
|
let mut scope_tree = if let Some(design_file) = vhdl_parse_str(&escape_path, &text) {
|
||||||
let arch_and_entity = vhdl_project.project.get_analyzed_units(&escape_path);
|
let arch_and_entity = vhdl_project.project.get_analyzed_units(&escape_path);
|
||||||
if let Some(mut fast) = make_fast_from_units(arch_and_entity) {
|
if let Some(mut fast) = make_fast_from_units(arch_and_entity) {
|
||||||
let parse_ir = ParseIR::DesignFile(design_file);
|
|
||||||
file.parse_ir = Some(parse_ir);
|
|
||||||
|
|
||||||
// for module in &fast.content {
|
// for module in &fast.content {
|
||||||
// info!("parse port number: {:?}", module.ports.len());
|
// info!("parse port number: {:?}", module.ports.len());
|
||||||
// }
|
// }
|
||||||
@ -882,7 +882,8 @@ pub fn vhdl_parser_pipeline(
|
|||||||
hdl_param_handle.update_hdl_file(
|
hdl_param_handle.update_hdl_file(
|
||||||
escape_path_string.to_string(),
|
escape_path_string.to_string(),
|
||||||
fast.clone(),
|
fast.clone(),
|
||||||
sv_parser::common::ParseResult::new()
|
sv_parser::common::ParseResult::new(),
|
||||||
|
Some(AstLike::Vhdl(design_file))
|
||||||
);
|
);
|
||||||
let scope_tree = get_scopes_from_vhdl_fast(&fast, doc, uri);
|
let scope_tree = get_scopes_from_vhdl_fast(&fast, doc, uri);
|
||||||
scope_tree
|
scope_tree
|
||||||
@ -890,10 +891,10 @@ pub fn vhdl_parser_pipeline(
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
file.parse_ir = None;
|
source.finish_at_least_once = false;
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
drop(file);
|
drop(source);
|
||||||
|
|
||||||
|
|
||||||
info!("finish parse {:?}", uri.to_string());
|
info!("finish parse {:?}", uri.to_string());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user