完成 module 端口赋值的 inlay hints

This commit is contained in:
锦恢 2024-11-01 20:39:29 +08:00
parent 2dd7f98d5f
commit cdcea82947
6 changed files with 161 additions and 77 deletions

1
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1 @@
{}

View File

@ -142,6 +142,42 @@ pub struct Parameter {
pub range: Range
}
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
}
}
impl Parameter {
pub fn to_description(&self) -> String {
let mut param_desc_array = Vec::<String>::new();
param_desc_array.push(format!("parameter {}", self.name));
if self.init != "unknown" {
param_desc_array.push("=".to_string());
param_desc_array.push(self.init.to_string());
}
let param_desc = param_desc_array.join(" ");
param_desc
}
}
#[derive(Debug, Serialize, PartialEq, PartialOrd, Eq, Ord, Deserialize, Clone)]
pub enum AssignType {
Named,

View File

@ -295,25 +295,9 @@ pub fn hover_position_port_param(
}
fn make_port_desc_hover(port: &crate::core::hdlparam::Port, range: &Range, language_id: &str) -> Hover {
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(" ");
let language_string = LanguageString {
language: language_id.to_string(),
value: port_desc
value: port.to_description()
};
Hover {
contents: HoverContents::Scalar(MarkedString::LanguageString(language_string)),
@ -322,18 +306,9 @@ fn make_port_desc_hover(port: &crate::core::hdlparam::Port, range: &Range, langu
}
fn make_param_desc_hover(param: &crate::core::hdlparam::Parameter, range: &Range, language_id: &str) -> Hover {
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(" ");
let language_string = LanguageString {
language: language_id.to_string(),
value: param_desc
value: param.to_description()
};
Hover {
contents: HoverContents::Scalar(MarkedString::LanguageString(language_string)),
@ -358,6 +333,11 @@ pub fn hover_module_declaration(
search_result()
};
// info!("token: {:?}, module info: {:?}", token_name, module_info);
// let test = server.srcs.hdl_param.module_name_to_path.read().unwrap();
// info!("module name to path: {:#?}", test);
if let Some((module, path_string)) = module_info {
let path_uri = Url::from_file_path(path_string.to_string()).unwrap().to_string();
let def_row = module.range.start.line;

View File

@ -1,8 +1,9 @@
use std::{path::PathBuf, str::FromStr};
use std::{collections::HashMap, path::PathBuf, str::FromStr};
use crate::{core, server::LSPServer};
use crate::{core, server::LSPServer, sources::LSPSupport};
#[allow(unused)]
use log::info;
use ropey::Rope;
use tower_lsp::lsp_types::*;
use super::to_escape_path;
@ -14,13 +15,13 @@ pub fn inlay_hint(server: &LSPServer, params: &InlayHintParams) -> Option<Vec<In
let path_string = path.to_str().unwrap();
let visible_range = core::hdlparam::Range::from_lsp_range(&params.range);
info!("enter hints");
let fast_map = server.srcs.hdl_param.path_to_hdl_file.read().unwrap();
let file_id = server.srcs.get_id(&params.text_document.uri);
let file = server.srcs.get_file(file_id).unwrap();
let file = file.read().unwrap();
let rope = &file.text;
// 先找到 当前 所在的 hdlfile
if let Some(hdl_file) = &fast_map.get(path_string) {
info!("enter some");
let fast = &hdl_file.fast;
let mut hints = Vec::<InlayHint>::new();
// 制作例化模块的 hint
@ -28,11 +29,11 @@ pub fn inlay_hint(server: &LSPServer, params: &InlayHintParams) -> Option<Vec<In
for instance in &module.instances {
// 根据在可见视图外面的 range 就不管了
if is_visible_range(&instance.instparams, &visible_range) {
hints.extend(make_instparam_hints(params, instance));
hints.extend(make_instparam_hints(server, params, instance, rope));
}
if is_visible_range(&instance.instports, &visible_range) {
hints.extend(make_instport_hints(params, instance));
hints.extend(make_instport_hints(server, params, instance, rope));
}
}
}
@ -57,8 +58,10 @@ fn is_visible_range(
}
fn make_instparam_hints(
server: &LSPServer,
params: &InlayHintParams,
instance: &core::hdlparam::Instance
instance: &core::hdlparam::Instance,
rope: &Rope
) -> Vec<InlayHint> {
let mut hints = Vec::<InlayHint>::new();
@ -66,36 +69,89 @@ fn make_instparam_hints(
hints
}
pub fn position_to_index(rope: &Rope, position: Position) -> usize {
let line_start = rope.line_to_char(position.line as usize);
let char_index = line_start + position.character as usize;
char_index
}
pub fn index_to_position(slice: &Rope, char_index: usize) -> Position {
let line = slice.char_to_line(char_index);
let line_start = slice.line_to_char(line);
let character = char_index - line_start;
Position {
line: line as u32,
character: character as u32,
}
}
fn find_instport_inlay_hints_position(
rope: &Rope,
range: &Range
) -> Option<Position> {
// let start = rope.pos_to_byte(&range.start);
// let end = rope.pos_to_byte(&range.end);
let start_offset = position_to_index(rope, range.start);
let end_offset = position_to_index(rope, range.end);
let instport_text = rope.slice(start_offset .. end_offset);
let instport_text = instport_text.to_string();
info!("{:?}", instport_text);
if let Some(offset) = instport_text.find("(") {
let target_offset = start_offset + offset + 1;
let target_position = index_to_position(rope, target_offset);
return Some(target_position);
}
None
}
fn make_instport_hints(
server: &LSPServer,
params: &InlayHintParams,
instance: &core::hdlparam::Instance
instance: &core::hdlparam::Instance,
rope: &Rope
) -> Vec<InlayHint> {
let mut hints = Vec::<InlayHint>::new();
let define_module = server.srcs.hdl_param.find_module_by_name(&instance.inst_type);
if define_module.is_none() {
return hints;
}
let define_module = define_module.unwrap();
// 制作 port name 到 port 的映射
let mut port_map = HashMap::<String, &core::hdlparam::Port>::new();
for port in &define_module.ports {
port_map.insert(port.name.to_string(), port);
}
for port_assigment in &instance.intstport_assignments {
let port_name = port_assigment.port.clone().unwrap_or("".to_string());
let port = port_map.get(&port_name);
if port.is_none() {
continue;
}
let port_info = port.unwrap();
let instport_range = port_assigment.range.to_lsp_range();
info!("inst name: {:?}, range: {:?}", instance.name, instport_range);
if let Some(hint_position) = find_instport_inlay_hints_position(rope, &instport_range) {
let port_desc = MarkupContent {
kind: MarkupKind::Markdown,
value: format!("```verilog\n{:?}\n```", port_assigment.port)
value: format!("```verilog\n{}\n```", port_info.to_description())
};
let hint = InlayHint {
position: port_assigment.range.to_lsp_range().start,
label: InlayHintLabel::String("start".to_string()),
padding_left: Some(true),
padding_right: Some(true),
kind: Some(InlayHintKind::PARAMETER),
text_edits: None,
tooltip: Some(InlayHintTooltip::MarkupContent(port_desc)),
data: None
let label = {
let dir_type = port_info.dir_type.to_string();
if dir_type == "output" {
format!("{}", dir_type)
} else {
format!("{}{}", dir_type, " ".repeat(1))
}
};
hints.push(hint);
let port_desc = MarkupContent {
kind: MarkupKind::Markdown,
value: format!("```verilog\n{:?}\n```", port_assigment.port)
};
let hint = InlayHint {
position: port_assigment.range.to_lsp_range().end,
label: InlayHintLabel::String("end".to_string()),
position: hint_position,
label: InlayHintLabel::String(label),
padding_left: Some(true),
padding_right: Some(true),
kind: Some(InlayHintKind::PARAMETER),
@ -105,6 +161,7 @@ fn make_instport_hints(
};
hints.push(hint);
}
}
hints
}

View File

@ -213,18 +213,22 @@ impl LanguageServer for Backend {
completion_provider: Some(completion_provider),
definition_provider: Some(OneOf::Left(true)),
hover_provider: Some(HoverProviderCapability::Simple(true)),
// inlay_hint_provider: Some(OneOf::Left(true)),
inlay_hint_provider: Some(OneOf::Left(true)),
document_symbol_provider: Some(OneOf::Left(true)),
document_highlight_provider: Some(OneOf::Left(true)),
..ServerCapabilities::default()
};
Ok(InitializeResult::default())
Ok(InitializeResult {
server_info,
capabilities,
offset_encoding: None
})
}
async fn initialized(&self, _: InitializedParams) {
self.client
.log_message(MessageType::INFO, "digital lsp initialized!")
.log_message(MessageType::INFO, "Digital LSP initialized!")
.await;
// self.client.send_notification::<StringNotification>(StringNotification { content: "hello from lsp server".to_string() }).await;
@ -276,7 +280,6 @@ impl LanguageServer for Backend {
}
async fn hover(&self, params: HoverParams) -> Result<Option<Hover>> {
Ok(self.server.hover(params))
}
@ -295,7 +298,6 @@ impl LanguageServer for Backend {
&self,
params: DocumentSymbolParams,
) -> Result<Option<DocumentSymbolResponse>> {
info!("enter document");
Ok(self.server.document_symbol(params))
}
@ -303,7 +305,6 @@ impl LanguageServer for Backend {
&self,
params: DocumentHighlightParams,
) -> Result<Option<Vec<DocumentHighlight>>> {
info!("enter highlight");
Ok(self.server.document_highlight(params))
}
@ -311,7 +312,6 @@ impl LanguageServer for Backend {
&self,
params: InlayHintParams
) -> Result<Option<Vec<InlayHint>>> {
info!("enter inlay_hint");
Ok(self.server.inlay_hint(params))
}
}

View File

@ -68,8 +68,6 @@ impl LSPServer {
}
pub fn did_change(&self, params: DidChangeTextDocumentParams) {
info!("[LSPServer] did change");
let file_id = self.srcs.get_id(&params.text_document.uri);
let file = self.srcs.get_file(file_id).unwrap();
let mut file = file.write().unwrap();
@ -755,6 +753,7 @@ 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
@ -797,6 +796,9 @@ impl LSPSupport for Rope {
}
}
}
fn find_first_str(&self, _: &str) -> Option<usize> {
panic!("haven't impl this method");
}
}
impl<'a> LSPSupport for RopeSlice<'a> {
@ -831,4 +833,12 @@ 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
}
}