This commit is contained in:
锦恢 2024-11-12 15:56:29 +08:00
parent c8aa5e2dcc
commit 15cfaccec1
9 changed files with 111 additions and 108 deletions

View File

@ -15,5 +15,25 @@
"#[allow(unused)]" "#[allow(unused)]"
], ],
"description": "#[allow(unused)]" "description": "#[allow(unused)]"
},
"match file_type": {
"scope": "rust",
"prefix": "matchfiletype",
"body": [
"match file_type.as_str() {",
"\t\"common\" => {",
"\t\t",
"\t}",
"\t\"ip\" => {",
"\t\t",
"\t}",
"\t\"primitives\" => {",
"\t\t",
"\t}",
"\t_ => {",
"\t\t",
"\t}",
"}",
]
} }
} }

View File

@ -156,18 +156,16 @@ fn get_position_port_param_completion(
let path = PathBuf::from_str(url.path()).unwrap(); let path = PathBuf::from_str(url.path()).unwrap();
let path = to_escape_path(&path); let path = to_escape_path(&path);
let path_string = path.to_str().unwrap(); let path_string = path.to_str().unwrap();
info!("enter get_position_port_param_completion, pos: {pos:?}"); // info!("enter get_position_port_param_completion, pos: {pos:?}");
if let Some(hdl_file) = fast_map.get(path_string) { if let Some(hdl_file) = fast_map.get(path_string) {
info!("find hdl_file, content: {:?}", hdl_file.fast.content); // info!("find hdl_file, content: {:?}", hdl_file.fast.content);
// 在当前文件的 fast 中寻找 // 在当前文件的 fast 中寻找
for module in &hdl_file.fast.content { for module in &hdl_file.fast.content {
for instance in &module.instances { for instance in &module.instances {
if let Some(_) = &instance.instparams { if let Some(_) = &instance.instparams {
if instance.gen_dot_completion_param_range().contains(pos) { if instance.gen_dot_completion_param_range().contains(pos) {
// 补全当前 module 的所有 param // 补全当前 module 的所有 param
let inst_module = hdl_param.find_module_by_name(&instance.inst_type); if let Some((inst_module, file_type, _)) = hdl_param.find_module_context_by_name(&instance.inst_type) {
if inst_module.is_some() {
let inst_module = inst_module.unwrap();
let mut completion_items = Vec::<CompletionItem>::new(); let mut completion_items = Vec::<CompletionItem>::new();
for param in inst_module.params { for param in inst_module.params {
let label_details = CompletionItemLabelDetails { let label_details = CompletionItemLabelDetails {
@ -175,7 +173,21 @@ fn get_position_port_param_completion(
..CompletionItemLabelDetails::default() ..CompletionItemLabelDetails::default()
}; };
let param_desc = make_param_desc(&param); let param_desc = match file_type.as_str() {
"common" => {
param.to_vlog_description()
}
"ip" => {
param.to_vhdl_description()
}
"primitives" => {
param.to_vlog_description()
}
_ => {
param.to_vlog_description()
}
};
let c_item = CompletionItem { let c_item = CompletionItem {
label: param.name, label: param.name,
detail: Some(param_desc), detail: Some(param_desc),
@ -196,9 +208,7 @@ fn get_position_port_param_completion(
if instance.instports.is_some() { if instance.instports.is_some() {
let port_range = instance.gen_dot_completion_port_range(); let port_range = instance.gen_dot_completion_port_range();
if port_range.contains(pos) { if port_range.contains(pos) {
let inst_module = hdl_param.find_module_by_name(&instance.inst_type); if let Some((inst_module, file_type, _)) = hdl_param.find_module_context_by_name(&instance.inst_type) {
if inst_module.is_some() {
let inst_module = inst_module.unwrap();
let mut completion_items = Vec::<CompletionItem>::new(); let mut completion_items = Vec::<CompletionItem>::new();
for port in inst_module.ports { for port in inst_module.ports {
let label_details = CompletionItemLabelDetails { let label_details = CompletionItemLabelDetails {
@ -206,7 +216,21 @@ fn get_position_port_param_completion(
..CompletionItemLabelDetails::default() ..CompletionItemLabelDetails::default()
}; };
let port_desc = make_port_desc(&port); let port_desc = match file_type.as_str() {
"common" => {
port.to_vlog_description()
}
"ip" => {
port.to_vhdl_description()
}
"primitives" => {
port.to_vlog_description()
}
_ => {
port.to_vlog_description()
}
};
let c_item = CompletionItem { let c_item = CompletionItem {
label: port.name, label: port.name,
detail: Some(port_desc), detail: Some(port_desc),
@ -228,36 +252,3 @@ fn get_position_port_param_completion(
} }
None None
} }
fn make_port_desc(port: &crate::core::hdlparam::Port) -> String {
let mut port_desc_array = Vec::<String>::new();
port_desc_array.push(port.dir_type.to_string());
if port.net_type != "unknown" {
port_desc_array.push(port.net_type.to_string());
}
if port.signed != "unsigned" {
port_desc_array.push("signed".to_string());
}
if port.width != "1" {
port_desc_array.push(port.width.to_string());
}
port_desc_array.push(port.name.to_string());
let port_desc = port_desc_array.join(" ");
port_desc
}
fn make_param_desc(param: &crate::core::hdlparam::Parameter) -> String {
let mut param_desc_array = Vec::<String>::new();
param_desc_array.push(format!("parameter {}", param.name));
if param.init != "unknown" {
param_desc_array.push("=".to_string());
param_desc_array.push(param.init.to_string());
}
let param_desc = param_desc_array.join(" ");
param_desc
}

View File

@ -156,26 +156,7 @@ pub struct Parameter {
} }
impl Port { impl Port {
pub fn to_description(&self) -> String { pub fn to_vlog_description(&self) -> String {
let mut port_desc_array = Vec::<String>::new();
port_desc_array.push(self.dir_type.to_string());
if self.net_type != "unknown" {
port_desc_array.push(self.net_type.to_string());
}
if self.signed != "unsigned" {
port_desc_array.push("signed".to_string());
}
if self.width != "1" {
port_desc_array.push(self.width.to_string());
}
port_desc_array.push(self.name.to_string());
let port_desc = port_desc_array.join(" ");
port_desc
}
pub fn vhdl_to_vlog_description(&self) -> String {
let mut port_desc_array = Vec::<String>::new(); let mut port_desc_array = Vec::<String>::new();
let dir_type = match self.dir_type.as_str() { let dir_type = match self.dir_type.as_str() {
"in" => "input", "in" => "input",
@ -215,7 +196,7 @@ impl Port {
} }
impl Parameter { impl Parameter {
pub fn to_description(&self) -> String { pub fn to_vlog_description(&self) -> String {
let mut param_desc_array = Vec::<String>::new(); let mut param_desc_array = Vec::<String>::new();
param_desc_array.push(format!("parameter {}", self.name)); param_desc_array.push(format!("parameter {}", self.name));
@ -226,13 +207,12 @@ impl Parameter {
let param_desc = param_desc_array.join(" "); let param_desc = param_desc_array.join(" ");
param_desc param_desc
} }
pub fn vhdl_to_vlog_description(&self) -> String { pub fn to_vhdl_description(&self) -> String {
let mut param_desc_array = Vec::<String>::new(); let mut param_desc_array = Vec::<String>::new();
param_desc_array.push(format!("parameter {}", self.name)); param_desc_array.push(format!("{} : {}", self.name, self.net_type.to_lowercase()));
if self.init != "unknown" { if self.init != "unknown" {
param_desc_array.push("=".to_string()); param_desc_array.push(format!(" := {}", self.init));
param_desc_array.push(self.init.to_string());
} }
let param_desc = param_desc_array.join(" "); let param_desc = param_desc_array.join(" ");
param_desc param_desc

View File

@ -35,14 +35,21 @@ pub fn vhdl_parser(path: &str) -> FastHdlparam {
hdlparam hdlparam
} }
pub fn vhdl_parse(path: &PathBuf) -> Option<DesignFile> { pub fn vhdl_parse(path: &PathBuf) -> Option<DesignFile> {
let mut diagnostics = Vec::new(); let mut diagnostics = Vec::new();
let parser = VHDLParser::new(VHDLStandard::VHDL2008); let parser = VHDLParser::new(VHDLStandard::VHDL2008);
if let Ok((_, design_file)) = parser.parse_design_file(path, &mut diagnostics) { if let Ok((_, design_file)) = parser.parse_design_file(path, &mut diagnostics) {
return Some(design_file); return Some(design_file);
} }
None
}
pub fn vhdl_parse_str(path: &PathBuf, code: &str) -> Option<DesignFile> {
let mut diagnostics = Vec::new();
let parser = VHDLParser::new(VHDLStandard::VHDL2008);
if let Ok((_, design_file)) = parser.parse_vhdl_str(code, path, &mut diagnostics) {
return Some(design_file);
}
None None
} }

View File

@ -301,16 +301,16 @@ fn make_port_desc_hover(file_type: &str, port: &crate::core::hdlparam::Port, ran
let (language, value) = match file_type { let (language, value) = match file_type {
"common" => { "common" => {
(language_id.to_string(), port.to_description()) (language_id.to_string(), port.to_vlog_description())
} }
"ip" => { "ip" => {
("vhdl".to_string(), port.to_vhdl_description()) ("vhdl".to_string(), port.to_vhdl_description())
} }
"primitives" => { "primitives" => {
(language_id.to_string(), port.to_description()) (language_id.to_string(), port.to_vlog_description())
} }
_ => { _ => {
(language_id.to_string(), port.to_description()) (language_id.to_string(), port.to_vlog_description())
} }
}; };
@ -324,16 +324,16 @@ fn make_port_desc_hover(file_type: &str, port: &crate::core::hdlparam::Port, ran
fn make_param_desc_hover(file_type: &str, param: &crate::core::hdlparam::Parameter, range: &Range, language_id: &str) -> Hover { fn make_param_desc_hover(file_type: &str, param: &crate::core::hdlparam::Parameter, range: &Range, language_id: &str) -> Hover {
let value = match file_type { let value = match file_type {
"common" => { "common" => {
param.to_description() param.to_vlog_description()
} }
"ip" => { "ip" => {
param.vhdl_to_vlog_description() param.to_vhdl_description()
} }
"primitives" => { "primitives" => {
param.to_description() param.to_vlog_description()
} }
_ => { _ => {
param.to_description() param.to_vlog_description()
} }
}; };

View File

@ -155,17 +155,17 @@ fn make_instport_hints(
let port_desc_value = match file_type.as_str() { let port_desc_value = match file_type.as_str() {
"common" => { "common" => {
format!("```{}\n{}\n```", language_id, port_info.to_description()) format!("```{}\n{}\n```", language_id, port_info.to_vlog_description())
} }
"ip" => { "ip" => {
// TODO: 支持更多的 IP // TODO: 支持更多的 IP
format!("```verilog\n{}\n```", port_info.vhdl_to_vlog_description()) format!("```verilog\n{}\n```", port_info.to_vhdl_description())
} }
"primitives" => { "primitives" => {
format!("```{}\n{}\n```", language_id, port_info.to_description()) format!("```{}\n{}\n```", language_id, port_info.to_vlog_description())
} }
_ => { _ => {
format!("```{}\n{}\n```", language_id, port_info.to_description()) format!("```{}\n{}\n```", language_id, port_info.to_vlog_description())
} }
}; };

View File

@ -118,11 +118,21 @@ pub fn do_fast(
let parse_fast_by_language_id = |language_id: &str| { let parse_fast_by_language_id = |language_id: &str| {
match language_id { match language_id {
"vhdl" => { "vhdl" => {
do_vhdl_fast(&path, &file_type, &tool_chain, backend) do_vhdl_fast(
&path,
&file_type,
&tool_chain,
backend
)
} }
"verilog" | "systemverilog" => { "verilog" | "systemverilog" => {
do_sv_fast(&path, &file_type, &tool_chain, backend) do_sv_fast(
&path,
&file_type,
&tool_chain,
backend
)
} }
_ => Err(tower_lsp::jsonrpc::Error { _ => Err(tower_lsp::jsonrpc::Error {

View File

@ -285,6 +285,10 @@ impl LanguageServer for Backend {
async fn did_change(&self, params: DidChangeTextDocumentParams) { async fn did_change(&self, params: DidChangeTextDocumentParams) {
info!("file did change: {:?}", params.text_document.uri); info!("file did change: {:?}", params.text_document.uri);
for change in &params.content_changes {
info!("change: {:?}", change);
}
// // 如果文件太大则显示错误 // // 如果文件太大则显示错误
// if CacheManager::uri_is_big_file(&params.text_document.uri) { // if CacheManager::uri_is_big_file(&params.text_document.uri) {
// // self.client.show_message(MessageType::WARNING, "考虑到性能问题,对于大于 1MB 的文件不会主动提供语言服务") // // self.client.show_message(MessageType::WARNING, "考虑到性能问题,对于大于 1MB 的文件不会主动提供语言服务")

View File

@ -1,8 +1,7 @@
use crate::core::cache_storage::CacheManager;
use crate::core::hdlparam::HdlParam; use crate::core::hdlparam::HdlParam;
use crate::core::sv_parser::make_fast_from_syntaxtree; use crate::core::sv_parser::make_fast_from_syntaxtree;
use crate::core::vhdl_parser::make_fast_from_design_file; use crate::core::vhdl_parser::make_fast_from_design_file;
use crate::core::vhdl_parser::vhdl_parse; use crate::core::vhdl_parser::vhdl_parse_str;
use crate::definition::def_types::*; use crate::definition::def_types::*;
use crate::definition::get_scopes_from_syntax_tree; use crate::definition::get_scopes_from_syntax_tree;
use crate::definition::get_scopes_from_vhdl_fast; use crate::definition::get_scopes_from_vhdl_fast;
@ -18,7 +17,6 @@ use ropey::{Rope, RopeSlice};
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;
use std::fs;
#[allow(unused)] #[allow(unused)]
use std::ops::Deref; use std::ops::Deref;
use std::ops::Range as StdRange; use std::ops::Range as StdRange;
@ -79,7 +77,7 @@ impl LSPServer {
if let Some(file) = self.srcs.get_file(file_id) { if let Some(file) = self.srcs.get_file(file_id) {
let mut file = file.write().unwrap(); let mut file = file.write().unwrap();
// loop through changes and apply // 根据输入的 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); file.text = Rope::from_str(&change.text);
@ -225,8 +223,6 @@ pub struct Sources {
pub scope_tree: Arc<RwLock<Option<GenericScope>>>, pub scope_tree: Arc<RwLock<Option<GenericScope>>>,
// include directories, passed to parser to resolve `include // include directories, passed to parser to resolve `include
pub include_dirs: Arc<RwLock<Vec<PathBuf>>>, pub include_dirs: Arc<RwLock<Vec<PathBuf>>>,
// source directories
pub source_dirs: Arc<RwLock<Vec<PathBuf>>>,
/// hdlparam 后端实现 /// hdlparam 后端实现
pub hdl_param: Arc<HdlParam>, pub hdl_param: Arc<HdlParam>,
// 同步解析线程和发送 fast 请求的 // 同步解析线程和发送 fast 请求的
@ -247,7 +243,6 @@ impl Sources {
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)),
include_dirs: Arc::new(RwLock::new(Vec::new())), include_dirs: Arc::new(RwLock::new(Vec::new())),
source_dirs: Arc::new(RwLock::new(Vec::new())),
hdl_param: Arc::new(HdlParam::new()), hdl_param: Arc::new(HdlParam::new()),
fast_sync_controller: Arc::new(RwLock::new(HashMap::<String, Arc<RwLock<bool>>>::new())) fast_sync_controller: Arc::new(RwLock::new(HashMap::<String, Arc<RwLock<bool>>>::new()))
} }
@ -273,6 +268,8 @@ impl Sources {
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 uri = doc.uri.clone();
let conf = server.conf.clone(); let conf = server.conf.clone();
info!("launch worker to parse {:?}", doc.uri.to_string()); info!("launch worker to parse {:?}", doc.uri.to_string());
@ -291,17 +288,18 @@ impl Sources {
let parse_handle = thread::spawn(move || { let parse_handle = thread::spawn(move || {
let (lock, cvar) = &*valid_parse2; let (lock, cvar) = &*valid_parse2;
loop { loop {
let file = source_handle.read().unwrap();
let text = file.text.clone();
let uri = &file.uri.clone();
let range = &file.last_change_range.clone();
drop(file);
info!("do parse in {:?}, language_id: {:?}", uri.to_string(), language_id); info!("do parse in {:?}, language_id: {:?}", uri.to_string(), language_id);
// 此时 update fast 的地方为 write 会进行阻塞 // 此时 update fast 的地方为 write 会进行阻塞
{ {
let _unused = fast_lock.read().unwrap(); let _unused = fast_lock.read().unwrap();
// 从内存中直接获取增量更新系统维护的代码文本
let file = source_handle.read().unwrap();
let text = file.text.clone();
let uri = &file.uri.clone();
let range = &file.last_change_range.clone();
drop(file);
match language_id.as_str() { match language_id.as_str() {
"vhdl" => { "vhdl" => {
vhdl_parser_pipeline( vhdl_parser_pipeline(
@ -692,11 +690,16 @@ pub fn vhdl_parser_pipeline(
}; };
let mut file = source_handle.write().unwrap(); let mut file = source_handle.write().unwrap();
let mut scope_tree = if let Some(design_file) = vhdl_parse(&escape_path) { let text = doc.to_string();
let mut scope_tree = if let Some(design_file) = vhdl_parse_str(&escape_path, &text) {
if let Some(mut fast) = make_fast_from_design_file(&design_file) { if let Some(mut fast) = make_fast_from_design_file(&design_file) {
let parse_ir = ParseIR::DesignFile(design_file); let parse_ir = ParseIR::DesignFile(design_file);
file.parse_ir = Some(parse_ir); file.parse_ir = Some(parse_ir);
for module in &fast.content {
info!("parse port number: {:?}", module.ports.len());
}
let file_type = { let file_type = {
let fast_map = hdl_param_handle.path_to_hdl_file.read().unwrap(); let fast_map = hdl_param_handle.path_to_hdl_file.read().unwrap();
if let Some(hdl_file) = fast_map.get(escape_path_string) { if let Some(hdl_file) = fast_map.get(escape_path_string) {
@ -763,7 +766,6 @@ pub trait LSPSupport {
fn range_to_char_range(&self, range: &Range) -> StdRange<usize>; fn range_to_char_range(&self, range: &Range) -> StdRange<usize>;
fn char_range_to_range(&self, range: StdRange<usize>) -> Range; fn char_range_to_range(&self, range: StdRange<usize>) -> Range;
fn apply_change(&mut self, change: &TextDocumentContentChangeEvent); fn apply_change(&mut self, change: &TextDocumentContentChangeEvent);
fn find_first_str(&self, target: &str) -> Option<usize>;
} }
/// Extend ropey's Rope type with lsp convenience functions /// Extend ropey's Rope type with lsp convenience functions
@ -806,9 +808,6 @@ impl LSPSupport for Rope {
} }
} }
} }
fn find_first_str(&self, _: &str) -> Option<usize> {
panic!("haven't impl this method");
}
} }
impl<'a> LSPSupport for RopeSlice<'a> { impl<'a> LSPSupport for RopeSlice<'a> {
@ -843,12 +842,4 @@ impl<'a> LSPSupport for RopeSlice<'a> {
fn apply_change(&mut self, _: &TextDocumentContentChangeEvent) { fn apply_change(&mut self, _: &TextDocumentContentChangeEvent) {
panic!("can't edit a rope slice"); panic!("can't edit a rope slice");
} }
fn find_first_str(&self, target: &str) -> Option<usize> {
for (i, c) in self.chars().enumerate() {
if c.to_string() == target {
return Some(i)
}
}
None
}
} }