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)]"
],
"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 = to_escape_path(&path);
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) {
info!("find hdl_file, content: {:?}", hdl_file.fast.content);
// info!("find hdl_file, content: {:?}", hdl_file.fast.content);
// 在当前文件的 fast 中寻找
for module in &hdl_file.fast.content {
for instance in &module.instances {
if let Some(_) = &instance.instparams {
if instance.gen_dot_completion_param_range().contains(pos) {
// 补全当前 module 的所有 param
let inst_module = hdl_param.find_module_by_name(&instance.inst_type);
if inst_module.is_some() {
let inst_module = inst_module.unwrap();
if let Some((inst_module, file_type, _)) = hdl_param.find_module_context_by_name(&instance.inst_type) {
let mut completion_items = Vec::<CompletionItem>::new();
for param in inst_module.params {
let label_details = CompletionItemLabelDetails {
@ -175,7 +173,21 @@ fn get_position_port_param_completion(
..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 {
label: param.name,
detail: Some(param_desc),
@ -196,9 +208,7 @@ fn get_position_port_param_completion(
if instance.instports.is_some() {
let port_range = instance.gen_dot_completion_port_range();
if port_range.contains(pos) {
let inst_module = hdl_param.find_module_by_name(&instance.inst_type);
if inst_module.is_some() {
let inst_module = inst_module.unwrap();
if let Some((inst_module, file_type, _)) = hdl_param.find_module_context_by_name(&instance.inst_type) {
let mut completion_items = Vec::<CompletionItem>::new();
for port in inst_module.ports {
let label_details = CompletionItemLabelDetails {
@ -206,7 +216,21 @@ fn get_position_port_param_completion(
..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 {
label: port.name,
detail: Some(port_desc),
@ -228,36 +252,3 @@ fn get_position_port_param_completion(
}
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 {
pub fn to_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 {
pub fn to_vlog_description(&self) -> String {
let mut port_desc_array = Vec::<String>::new();
let dir_type = match self.dir_type.as_str() {
"in" => "input",
@ -215,7 +196,7 @@ impl Port {
}
impl Parameter {
pub fn to_description(&self) -> String {
pub fn to_vlog_description(&self) -> String {
let mut param_desc_array = Vec::<String>::new();
param_desc_array.push(format!("parameter {}", self.name));
@ -226,13 +207,12 @@ impl Parameter {
let param_desc = param_desc_array.join(" ");
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();
param_desc_array.push(format!("parameter {}", self.name));
param_desc_array.push(format!("{} : {}", self.name, self.net_type.to_lowercase()));
if self.init != "unknown" {
param_desc_array.push("=".to_string());
param_desc_array.push(self.init.to_string());
param_desc_array.push(format!(" := {}", self.init));
}
let param_desc = param_desc_array.join(" ");
param_desc

View File

@ -35,14 +35,21 @@ pub fn vhdl_parser(path: &str) -> FastHdlparam {
hdlparam
}
pub fn vhdl_parse(path: &PathBuf) -> Option<DesignFile> {
let mut diagnostics = Vec::new();
let parser = VHDLParser::new(VHDLStandard::VHDL2008);
if let Ok((_, design_file)) = parser.parse_design_file(path, &mut diagnostics) {
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
}

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 {
"common" => {
(language_id.to_string(), port.to_description())
(language_id.to_string(), port.to_vlog_description())
}
"ip" => {
("vhdl".to_string(), port.to_vhdl_description())
}
"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 {
let value = match file_type {
"common" => {
param.to_description()
param.to_vlog_description()
}
"ip" => {
param.vhdl_to_vlog_description()
param.to_vhdl_description()
}
"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() {
"common" => {
format!("```{}\n{}\n```", language_id, port_info.to_description())
format!("```{}\n{}\n```", language_id, port_info.to_vlog_description())
}
"ip" => {
// TODO: 支持更多的 IP
format!("```verilog\n{}\n```", port_info.vhdl_to_vlog_description())
format!("```verilog\n{}\n```", port_info.to_vhdl_description())
}
"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| {
match language_id {
"vhdl" => {
do_vhdl_fast(&path, &file_type, &tool_chain, backend)
do_vhdl_fast(
&path,
&file_type,
&tool_chain,
backend
)
}
"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 {

View File

@ -285,6 +285,10 @@ impl LanguageServer for Backend {
async fn did_change(&self, params: DidChangeTextDocumentParams) {
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) {
// // 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::sv_parser::make_fast_from_syntaxtree;
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::get_scopes_from_syntax_tree;
use crate::definition::get_scopes_from_vhdl_fast;
@ -18,7 +17,6 @@ use ropey::{Rope, RopeSlice};
use std::cmp::min;
use std::collections::HashMap;
use std::env::current_dir;
use std::fs;
#[allow(unused)]
use std::ops::Deref;
use std::ops::Range as StdRange;
@ -79,7 +77,7 @@ impl LSPServer {
if let Some(file) = self.srcs.get_file(file_id) {
let mut file = file.write().unwrap();
// loop through changes and apply
// 根据输入的 change 动态更新对应的代码的文本片段
for change in params.content_changes {
if change.range.is_none() {
file.text = Rope::from_str(&change.text);
@ -225,8 +223,6 @@ pub struct Sources {
pub scope_tree: Arc<RwLock<Option<GenericScope>>>,
// include directories, passed to parser to resolve `include
pub include_dirs: Arc<RwLock<Vec<PathBuf>>>,
// source directories
pub source_dirs: Arc<RwLock<Vec<PathBuf>>>,
/// hdlparam 后端实现
pub hdl_param: Arc<HdlParam>,
// 同步解析线程和发送 fast 请求的
@ -247,7 +243,6 @@ impl Sources {
meta: Arc::new(RwLock::new(Vec::new())),
scope_tree: Arc::new(RwLock::new(None)),
include_dirs: Arc::new(RwLock::new(Vec::new())),
source_dirs: Arc::new(RwLock::new(Vec::new())),
hdl_param: Arc::new(HdlParam::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 inc_dirs = self.include_dirs.clone();
let uri = doc.uri.clone();
let conf = server.conf.clone();
info!("launch worker to parse {:?}", doc.uri.to_string());
@ -291,17 +288,18 @@ impl Sources {
let parse_handle = thread::spawn(move || {
let (lock, cvar) = &*valid_parse2;
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);
// 此时 update fast 的地方为 write 会进行阻塞
{
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() {
"vhdl" => {
vhdl_parser_pipeline(
@ -692,11 +690,16 @@ pub fn vhdl_parser_pipeline(
};
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) {
let parse_ir = ParseIR::DesignFile(design_file);
file.parse_ir = Some(parse_ir);
for module in &fast.content {
info!("parse port number: {:?}", module.ports.len());
}
let file_type = {
let fast_map = hdl_param_handle.path_to_hdl_file.read().unwrap();
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 char_range_to_range(&self, range: StdRange<usize>) -> Range;
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
@ -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> {
@ -843,12 +842,4 @@ impl<'a> LSPSupport for RopeSlice<'a> {
fn apply_change(&mut self, _: &TextDocumentContentChangeEvent) {
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
}
}