refactor vhdl lsp service
This commit is contained in:
parent
c40e66f3df
commit
2fcfed4674
102
Cargo.lock
generated
102
Cargo.lock
generated
@ -286,6 +286,15 @@ version = "0.8.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-deque"
|
name = "crossbeam-deque"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
@ -348,6 +357,7 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
"tower-lsp",
|
"tower-lsp",
|
||||||
"vhdl_lang",
|
"vhdl_lang",
|
||||||
|
"vhdl_ls",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"xml",
|
"xml",
|
||||||
]
|
]
|
||||||
@ -426,6 +436,29 @@ dependencies = [
|
|||||||
"syn 2.0.79",
|
"syn 2.0.79",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_filter"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.11.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"env_filter",
|
||||||
|
"humantime",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@ -544,6 +577,15 @@ dependencies = [
|
|||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuzzy-matcher"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94"
|
||||||
|
dependencies = [
|
||||||
|
"thread_local",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
@ -609,6 +651,12 @@ version = "1.9.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
|
checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humantime"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iana-time-zone"
|
name = "iana-time-zone"
|
||||||
version = "0.1.61"
|
version = "0.1.61"
|
||||||
@ -720,6 +768,18 @@ version = "0.4.22"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lsp-server"
|
||||||
|
version = "0.7.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "550446e84739dcaf6d48a4a093973850669e13e8a34d8f8d64851041be267cd9"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
|
"log",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lsp-types"
|
name = "lsp-types"
|
||||||
version = "0.94.1"
|
version = "0.94.1"
|
||||||
@ -733,6 +793,19 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lsp-types"
|
||||||
|
version = "0.95.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e34d33a8e9b006cd3fc4fe69a921affa097bae4bb65f76271f4644f9a334365"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serde_repr",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.4"
|
version = "2.7.4"
|
||||||
@ -1462,6 +1535,16 @@ dependencies = [
|
|||||||
"syn 2.0.79",
|
"syn 2.0.79",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread_local"
|
||||||
|
version = "1.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyvec"
|
name = "tinyvec"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
@ -1578,7 +1661,7 @@ dependencies = [
|
|||||||
"dashmap",
|
"dashmap",
|
||||||
"futures",
|
"futures",
|
||||||
"httparse",
|
"httparse",
|
||||||
"lsp-types",
|
"lsp-types 0.94.1",
|
||||||
"memchr",
|
"memchr",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -1736,6 +1819,23 @@ dependencies = [
|
|||||||
"syn 2.0.79",
|
"syn 2.0.79",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vhdl_ls"
|
||||||
|
version = "0.83.0"
|
||||||
|
dependencies = [
|
||||||
|
"clap 4.5.19",
|
||||||
|
"env_logger",
|
||||||
|
"fnv",
|
||||||
|
"fuzzy-matcher",
|
||||||
|
"log",
|
||||||
|
"lsp-server",
|
||||||
|
"lsp-types 0.95.1",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"tower-lsp",
|
||||||
|
"vhdl_lang",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
|
@ -6,6 +6,7 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sv-parser = { version = "0.13.3", path = "sv-parser/sv-parser"}
|
sv-parser = { version = "0.13.3", path = "sv-parser/sv-parser"}
|
||||||
|
vhdl_ls = { version = "^0.83.0", path = "vhdl-parser/vhdl_ls" }
|
||||||
vhdl_lang = { version = "^0.83.0", path = "vhdl-parser/vhdl_lang" }
|
vhdl_lang = { version = "^0.83.0", path = "vhdl-parser/vhdl_lang" }
|
||||||
dirs-next = "2.0"
|
dirs-next = "2.0"
|
||||||
bincode = "1.3"
|
bincode = "1.3"
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
use std::{path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
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;
|
use crate::{hover::feature::make_vhdl_module_profile_code, utils::{from_lsp_pos, 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};
|
||||||
|
|
||||||
@ -26,6 +28,27 @@ pub fn completion(server: &LSPServer, params: &CompletionParams) -> Option<Compl
|
|||||||
doc.position,
|
doc.position,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let project = server.srcs.vhdl_project.read().ok()?;
|
||||||
|
let global_project = project.as_ref().unwrap();
|
||||||
|
let path = match PathBuf::from_str(uri.path()) {
|
||||||
|
Ok(path) => path,
|
||||||
|
Err(error) => {
|
||||||
|
info!("error happen in vhdl <hover>: {:?}", error);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let escape_path = to_escape_path(&path);
|
||||||
|
let project_file = escape_path.as_path();
|
||||||
|
let Some(source) = global_project.project.get_source(project_file) else {
|
||||||
|
return None
|
||||||
|
};
|
||||||
|
let cursor = from_lsp_pos(params.text_document_position.position);
|
||||||
|
|
||||||
|
let vhdl_project_completion_items = global_project.project
|
||||||
|
.list_completion_options(&source, cursor)
|
||||||
|
.into_iter()
|
||||||
|
.map(|item| vhdl_ls::VHDLServer::completion_item_to_tower_lsp_item(item))
|
||||||
|
.collect::<Vec<CompletionItem>>();
|
||||||
|
|
||||||
let response = match ¶ms.context {
|
let response = match ¶ms.context {
|
||||||
Some(context) => match context.trigger_kind {
|
Some(context) => match context.trigger_kind {
|
||||||
@ -65,6 +88,8 @@ pub fn completion(server: &LSPServer, params: &CompletionParams) -> Option<Compl
|
|||||||
make_module_completions(server, &token, &language_id)
|
make_module_completions(server, &token, &language_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
completion_items.items.extend(vhdl_project_completion_items);
|
||||||
|
|
||||||
// 去重
|
// 去重
|
||||||
completion_items.items.dedup_by_key(|i| i.label.to_string());
|
completion_items.items.dedup_by_key(|i| i.label.to_string());
|
||||||
Some(completion_items)
|
Some(completion_items)
|
||||||
@ -100,6 +125,9 @@ pub fn completion(server: &LSPServer, params: &CompletionParams) -> Option<Compl
|
|||||||
.cloned()
|
.cloned()
|
||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
comps.items.extend(vhdl_project_completion_items);
|
||||||
|
|
||||||
comps.items.dedup_by_key(|i| i.label.clone());
|
comps.items.dedup_by_key(|i| i.label.clone());
|
||||||
Some(comps)
|
Some(comps)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
use crate::sources::LSPSupport;
|
use std::ffi::OsStr;
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
use log::info;
|
use log::info;
|
||||||
use ropey::Rope;
|
use ropey::Rope;
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
|
use vhdl_lang::Project;
|
||||||
|
|
||||||
|
use crate::sources::LSPSupport;
|
||||||
|
|
||||||
/// cleanup the text of a definition so it can be included in completions
|
/// cleanup the text of a definition so it can be included in completions
|
||||||
pub fn clean_type_str(type_str: &str, ident: &str) -> String {
|
pub fn clean_type_str(type_str: &str, ident: &str) -> String {
|
||||||
@ -749,6 +753,12 @@ impl Definition for ModInst {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct VhdlProject {
|
||||||
|
pub project: Project,
|
||||||
|
pub std_config: vhdl_lang::Config,
|
||||||
|
pub config_file_strs: Vec<String>
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct GenericScope {
|
pub struct GenericScope {
|
||||||
pub ident: String,
|
pub ident: String,
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
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, sources::LSPSupport, utils::get_definition_token};
|
use crate::{server::LSPServer, utils::{from_lsp_pos, get_definition_token, srcpos_to_location, to_escape_path}};
|
||||||
|
|
||||||
use super::{Definition, Scope};
|
use super::{Definition, Scope};
|
||||||
|
|
||||||
@ -16,6 +18,29 @@ pub fn goto_vhdl_definition(server: &LSPServer, params: &GotoDefinitionParams) -
|
|||||||
let line_text = file.text.line(pos.line as usize);
|
let line_text = file.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 project = server.srcs.vhdl_project.read().ok()?;
|
||||||
|
let global_project = project.as_ref().unwrap();
|
||||||
|
let path = match PathBuf::from_str(doc.path()) {
|
||||||
|
Ok(path) => path,
|
||||||
|
Err(error) => {
|
||||||
|
info!("error happen in vhdl <hover>: {:?}", error);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let escape_path = to_escape_path(&path);
|
||||||
|
let project_file = escape_path.as_path();
|
||||||
|
let Some(source) = global_project.project.get_source(project_file) else {
|
||||||
|
return None
|
||||||
|
};
|
||||||
|
|
||||||
|
let ents = global_project.project.find_implementation(&source, from_lsp_pos(pos));
|
||||||
|
|
||||||
|
Some(GotoDefinitionResponse::Array(
|
||||||
|
ents.into_iter()
|
||||||
|
.filter_map(|ent| ent.decl_pos().map(srcpos_to_location))
|
||||||
|
.collect(),
|
||||||
|
))
|
||||||
|
|
||||||
// // match include
|
// // match include
|
||||||
// if let Some(definition) = goto_include_definition(doc, &line_text, pos) {
|
// if let Some(definition) = goto_include_definition(doc, &line_text, pos) {
|
||||||
// return Some(definition);
|
// return Some(definition);
|
||||||
@ -28,7 +53,7 @@ pub fn goto_vhdl_definition(server: &LSPServer, params: &GotoDefinitionParams) -
|
|||||||
|
|
||||||
// match instance
|
// match instance
|
||||||
|
|
||||||
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, doc, pos) {
|
||||||
@ -40,13 +65,13 @@ pub fn goto_vhdl_definition(server: &LSPServer, params: &GotoDefinitionParams) -
|
|||||||
// return Some(definition);
|
// return Some(definition);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
let byte_idx = file.text.pos_to_byte(&pos);
|
// let byte_idx = file.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, doc)?;
|
||||||
|
|
||||||
let def_pos = file.text.byte_to_pos(def.byte_idx());
|
// let def_pos = file.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),
|
||||||
)))
|
// )))
|
||||||
}
|
}
|
@ -1,7 +1,10 @@
|
|||||||
|
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::{definition::Scope, server::LSPServer};
|
use vhdl_lang::{EntHierarchy, Token};
|
||||||
|
use crate::{definition::Scope, server::LSPServer, utils::{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");
|
// info!("enter document symbol");
|
||||||
@ -13,7 +16,66 @@ pub fn document_symbol(server: &LSPServer, params: &DocumentSymbolParams) -> Opt
|
|||||||
let file = file.read().ok()?;
|
let file = file.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 global_project = project.as_ref().unwrap();
|
||||||
|
let path = match PathBuf::from_str(uri.path()) {
|
||||||
|
Ok(path) => path,
|
||||||
|
Err(error) => {
|
||||||
|
info!("error happen in vhdl <hover>: {:?}", error);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let escape_path = to_escape_path(&path);
|
||||||
|
let project_file = escape_path.as_path();
|
||||||
|
let Some(source) = global_project.project.get_source(project_file) else {
|
||||||
|
return None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Some files are mapped to multiple libraries, only use the first library for document symbols
|
||||||
|
let library_name = global_project.project
|
||||||
|
.library_mapping_of(&source)
|
||||||
|
.into_iter()
|
||||||
|
.next()?;
|
||||||
|
|
||||||
|
fn to_document_symbol(
|
||||||
|
EntHierarchy { ent, children }: EntHierarchy,
|
||||||
|
ctx: &Vec<Token>,
|
||||||
|
) -> DocumentSymbol {
|
||||||
|
// Use the declaration position, if it exists,
|
||||||
|
// else the position of the first source range token.
|
||||||
|
// The latter is applicable for unnamed elements, e.g., processes or loops.
|
||||||
|
let selection_pos = ent.decl_pos().unwrap_or(ent.src_span.start_token.pos(ctx));
|
||||||
|
let src_range = ent.src_span.pos(ctx).range();
|
||||||
|
#[allow(deprecated)]
|
||||||
|
DocumentSymbol {
|
||||||
|
name: ent.describe(),
|
||||||
|
kind: to_symbol_kind(ent.kind()),
|
||||||
|
tags: None,
|
||||||
|
detail: None,
|
||||||
|
selection_range: to_lsp_range(selection_pos.range),
|
||||||
|
range: to_lsp_range(src_range),
|
||||||
|
children: if !children.is_empty() {
|
||||||
|
Some(
|
||||||
|
children
|
||||||
|
.into_iter()
|
||||||
|
.map(|hierarchy| to_document_symbol(hierarchy, ctx))
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
deprecated: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Some(DocumentSymbolResponse::Nested(
|
Some(DocumentSymbolResponse::Nested(
|
||||||
scope_tree.as_ref()?.document_symbols(uri, &file.text),
|
global_project.project
|
||||||
|
.document_symbols(&library_name, &source)
|
||||||
|
.into_iter()
|
||||||
|
.map(|(hierarchy, tokens)| to_document_symbol(hierarchy, tokens))
|
||||||
|
.collect(),
|
||||||
))
|
))
|
||||||
|
// Some(DocumentSymbolResponse::Nested(
|
||||||
|
// scope_tree.as_ref()?.document_symbols(uri, &file.text),
|
||||||
|
// ))
|
||||||
}
|
}
|
@ -6,7 +6,7 @@ use ropey::Rope;
|
|||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
use crate::{core::hdlparam::{Instance, Module}, definition::{Definition, DefinitionType, GenericDec, Scope}, hover::{BracketMatchResult, BracketMatcher}, server::LSPServer, sources::LSPSupport};
|
use crate::{core::hdlparam::{Instance, Module}, definition::{Definition, DefinitionType, GenericDec, Scope}, hover::{BracketMatchResult, BracketMatcher}, server::LSPServer, sources::LSPSupport};
|
||||||
|
|
||||||
use super::{feature::hover_format_digit, get_definition_token, get_language_id_by_uri, to_escape_path};
|
use super::{from_lsp_pos, 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 doc = ¶ms.text_document_position_params.text_document.uri;
|
||||||
@ -20,6 +20,30 @@ pub fn hover(server: &LSPServer, params: &HoverParams) -> Option<Hover> {
|
|||||||
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(doc);
|
||||||
|
|
||||||
|
let project = server.srcs.vhdl_project.read().ok()?;
|
||||||
|
let global_project = project.as_ref().unwrap();
|
||||||
|
|
||||||
|
let path = match PathBuf::from_str(doc.path()) {
|
||||||
|
Ok(path) => path,
|
||||||
|
Err(error) => {
|
||||||
|
info!("error happen in vhdl <hover>: {:?}", error);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let escape_path = to_escape_path(&path);
|
||||||
|
let source = global_project.project.get_source(&escape_path)?;
|
||||||
|
|
||||||
|
let ent = global_project.project.find_declaration(&source, from_lsp_pos(pos))?;
|
||||||
|
let value = global_project.project.format_declaration(ent)?;
|
||||||
|
|
||||||
|
Some(Hover {
|
||||||
|
contents: HoverContents::Markup(MarkupContent {
|
||||||
|
kind: MarkupKind::Markdown,
|
||||||
|
value: format!("```vhdl\n{value}\n```"),
|
||||||
|
}),
|
||||||
|
range: None,
|
||||||
|
})
|
||||||
|
|
||||||
// // match `include
|
// // match `include
|
||||||
// if let Some(hover) = hover_include(doc, &line_text, pos, &language_id) {
|
// if let Some(hover) = hover_include(doc, &line_text, pos, &language_id) {
|
||||||
// return Some(hover);
|
// return Some(hover);
|
||||||
@ -30,11 +54,11 @@ 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 scope_tree = server.srcs.scope_tree.read().ok()?;
|
||||||
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, 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) {
|
||||||
@ -47,16 +71,16 @@ pub fn hover(server: &LSPServer, params: &HoverParams) -> Option<Hover> {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// 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, &file, doc, pos, &language_id) {
|
||||||
return Some(hover);
|
// return Some(hover);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// match digit 5'b00110
|
// // match digit 5'b00110
|
||||||
if let Some(hover) = hover_format_digit(&line_text, pos, &language_id) {
|
// if let Some(hover) = hover_format_digit(&line_text, pos, &language_id) {
|
||||||
return Some(hover);
|
// return Some(hover);
|
||||||
}
|
// }
|
||||||
|
|
||||||
None
|
// None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_hover_with_comment(doc: &Rope, line: usize, language_id: &str, exclude_code: bool) -> Option<Hover> {
|
fn make_hover_with_comment(doc: &Rope, line: usize, language_id: &str, exclude_code: bool) -> Option<Hover> {
|
||||||
|
@ -22,11 +22,13 @@ use std::env::current_dir;
|
|||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::ops::Range as StdRange;
|
use std::ops::Range as StdRange;
|
||||||
|
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, Condvar, Mutex, RwLock};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use sv_parser::*;
|
use sv_parser::*;
|
||||||
|
use vhdl_lang::Project;
|
||||||
use thread::JoinHandle;
|
use thread::JoinHandle;
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
@ -144,6 +146,32 @@ impl LSPServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut vhdl_project = self.srcs.vhdl_project.write().unwrap();
|
||||||
|
match &mut *vhdl_project {
|
||||||
|
Some(vhdl_project) => {
|
||||||
|
let config_file_strs = vhdl_project.config_file_strs.clone()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|x| x != path_string)
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
let mut messages = Vec::new();
|
||||||
|
let config_str = format!(
|
||||||
|
r#"
|
||||||
|
[libraries]
|
||||||
|
digital_lsp.files = [{}]
|
||||||
|
"#, config_file_strs.join(",")
|
||||||
|
);
|
||||||
|
let config = vhdl_lang::Config::from_str(&config_str, Path::new(""));
|
||||||
|
if let Ok(mut config) = config {
|
||||||
|
config.append(&vhdl_project.std_config, &mut messages);
|
||||||
|
let mut project = Project::from_config(config, &mut messages);
|
||||||
|
project.analyse();
|
||||||
|
*vhdl_project = VhdlProject { project, std_config: vhdl_project.std_config.clone(), config_file_strs };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,6 +242,8 @@ 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 project, store vhdl design files, do lsp
|
||||||
|
pub vhdl_project: Arc<RwLock<Option<VhdlProject>>>,
|
||||||
// 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>>>,
|
||||||
// primitive instance text
|
// primitive instance text
|
||||||
@ -239,6 +269,7 @@ 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)),
|
||||||
|
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()),
|
||||||
@ -280,6 +311,7 @@ impl Sources {
|
|||||||
}));
|
}));
|
||||||
let source_handle = source.clone();
|
let source_handle = source.clone();
|
||||||
let scope_handle = self.scope_tree.clone();
|
let scope_handle = self.scope_tree.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();
|
||||||
|
|
||||||
@ -321,6 +353,7 @@ impl Sources {
|
|||||||
&conf,
|
&conf,
|
||||||
&source_handle,
|
&source_handle,
|
||||||
&scope_handle,
|
&scope_handle,
|
||||||
|
&project_handle,
|
||||||
&hdl_param_handle,
|
&hdl_param_handle,
|
||||||
&text,
|
&text,
|
||||||
uri,
|
uri,
|
||||||
@ -707,6 +740,7 @@ pub fn vhdl_parser_pipeline(
|
|||||||
conf: &Arc<RwLock<ProjectConfig>>,
|
conf: &Arc<RwLock<ProjectConfig>>,
|
||||||
source_handle: &Arc<RwLock<Source>>,
|
source_handle: &Arc<RwLock<Source>>,
|
||||||
scope_handle: &Arc<RwLock<Option<GenericScope>>>,
|
scope_handle: &Arc<RwLock<Option<GenericScope>>>,
|
||||||
|
project_handle: &Arc<RwLock<Option<VhdlProject>>>,
|
||||||
hdl_param_handle: &Arc<HdlParam>,
|
hdl_param_handle: &Arc<HdlParam>,
|
||||||
doc: &Rope,
|
doc: &Rope,
|
||||||
uri: &Url
|
uri: &Url
|
||||||
@ -797,6 +831,65 @@ pub fn vhdl_parser_pipeline(
|
|||||||
None => *global_scope = scope_tree,
|
None => *global_scope = scope_tree,
|
||||||
}
|
}
|
||||||
// eprintln!("{:#?}", *global_scope);
|
// eprintln!("{:#?}", *global_scope);
|
||||||
|
|
||||||
|
let mut global_project = project_handle.write().unwrap();
|
||||||
|
match &mut *global_project {
|
||||||
|
Some(vhdl_project) => {
|
||||||
|
if let Some(source) = vhdl_project.project.get_source(&escape_path) {
|
||||||
|
source.change(None, &doc.to_string());
|
||||||
|
vhdl_project.project.update_source(&source);
|
||||||
|
vhdl_project.project.analyse();
|
||||||
|
} else {
|
||||||
|
vhdl_project.config_file_strs.push(format!("{:?}", escape_path));
|
||||||
|
let mut messages = Vec::new();
|
||||||
|
let config_str = format!(
|
||||||
|
r#"
|
||||||
|
[libraries]
|
||||||
|
digital_lsp.files = [{}]
|
||||||
|
"#, vhdl_project.config_file_strs.join(",")
|
||||||
|
);
|
||||||
|
let config = vhdl_lang::Config::from_str(&config_str, Path::new(""));
|
||||||
|
if let Ok(mut config) = config {
|
||||||
|
config.append(&vhdl_project.std_config, &mut messages);
|
||||||
|
let mut project = Project::from_config(config, &mut messages);
|
||||||
|
project.analyse();
|
||||||
|
*vhdl_project = VhdlProject { project, std_config: vhdl_project.std_config.clone(), config_file_strs: vhdl_project.config_file_strs.clone() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let std_cfg_path = match PathBuf::from_str(&(extension_path + "/resources/dide-lsp/static/vhdl_libraries/vhdl_ls.toml")) {
|
||||||
|
Ok(path) => path,
|
||||||
|
Err(e) => {
|
||||||
|
info!("error happen in <vhdl_parse_pipeline>: {:?}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match vhdl_lang::Config::read_file_path(&std_cfg_path) {
|
||||||
|
Ok(std_config) => {
|
||||||
|
let config_str = format!(
|
||||||
|
r#"
|
||||||
|
[libraries]
|
||||||
|
digital_lsp.files = [{:?}]
|
||||||
|
"#, escape_path
|
||||||
|
);
|
||||||
|
let mut config_file_strs = Vec::new();
|
||||||
|
config_file_strs.push(format!("{:?}", escape_path));
|
||||||
|
let config = vhdl_lang::Config::from_str(&config_str, Path::new(""));
|
||||||
|
if let Ok(mut config) = config {
|
||||||
|
let mut messages = Vec::new();
|
||||||
|
config.append(&std_config, &mut messages);
|
||||||
|
let mut project = Project::from_config(config, &mut messages);
|
||||||
|
project.analyse();
|
||||||
|
*global_project = Some(VhdlProject { project, std_config, config_file_strs });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => info!("error happen in <vhdl_parse_pipeline>: Can't load standard vhdl lib from {std_cfg_path:#?} because {e:#?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drop(global_project);
|
||||||
|
|
||||||
drop(global_scope);
|
drop(global_scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit eb7ea05f13a133a175352da8ba537ac1717a35cf
|
Subproject commit 2446bd0a812d1667ad7033f10cd27a03967fa15e
|
Loading…
x
Reference in New Issue
Block a user