完成 module 端口赋值的 inlay hints
This commit is contained in:
parent
2dd7f98d5f
commit
cdcea82947
1
.vscode/settings.json
vendored
Normal file
1
.vscode/settings.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
@ -142,6 +142,42 @@ pub struct Parameter {
|
|||||||
pub range: Range
|
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)]
|
#[derive(Debug, Serialize, PartialEq, PartialOrd, Eq, Ord, Deserialize, Clone)]
|
||||||
pub enum AssignType {
|
pub enum AssignType {
|
||||||
Named,
|
Named,
|
||||||
|
@ -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 {
|
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 {
|
let language_string = LanguageString {
|
||||||
language: language_id.to_string(),
|
language: language_id.to_string(),
|
||||||
value: port_desc
|
value: port.to_description()
|
||||||
};
|
};
|
||||||
Hover {
|
Hover {
|
||||||
contents: HoverContents::Scalar(MarkedString::LanguageString(language_string)),
|
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 {
|
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 {
|
let language_string = LanguageString {
|
||||||
language: language_id.to_string(),
|
language: language_id.to_string(),
|
||||||
value: param_desc
|
value: param.to_description()
|
||||||
};
|
};
|
||||||
Hover {
|
Hover {
|
||||||
contents: HoverContents::Scalar(MarkedString::LanguageString(language_string)),
|
contents: HoverContents::Scalar(MarkedString::LanguageString(language_string)),
|
||||||
@ -358,6 +333,11 @@ pub fn hover_module_declaration(
|
|||||||
search_result()
|
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 {
|
if let Some((module, path_string)) = module_info {
|
||||||
let path_uri = Url::from_file_path(path_string.to_string()).unwrap().to_string();
|
let path_uri = Url::from_file_path(path_string.to_string()).unwrap().to_string();
|
||||||
let def_row = module.range.start.line;
|
let def_row = module.range.start.line;
|
||||||
|
@ -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)]
|
#[allow(unused)]
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use ropey::Rope;
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
|
|
||||||
use super::to_escape_path;
|
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 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);
|
||||||
|
|
||||||
info!("enter hints");
|
|
||||||
|
|
||||||
let fast_map = server.srcs.hdl_param.path_to_hdl_file.read().unwrap();
|
let fast_map = server.srcs.hdl_param.path_to_hdl_file.read().unwrap();
|
||||||
|
let file_id = server.srcs.get_id(¶ms.text_document.uri);
|
||||||
|
let file = server.srcs.get_file(file_id).unwrap();
|
||||||
|
let file = file.read().unwrap();
|
||||||
|
let rope = &file.text;
|
||||||
// 先找到 当前 所在的 hdlfile
|
// 先找到 当前 所在的 hdlfile
|
||||||
if let Some(hdl_file) = &fast_map.get(path_string) {
|
if let Some(hdl_file) = &fast_map.get(path_string) {
|
||||||
info!("enter some");
|
|
||||||
|
|
||||||
let fast = &hdl_file.fast;
|
let fast = &hdl_file.fast;
|
||||||
let mut hints = Vec::<InlayHint>::new();
|
let mut hints = Vec::<InlayHint>::new();
|
||||||
// 制作例化模块的 hint
|
// 制作例化模块的 hint
|
||||||
@ -28,11 +29,11 @@ pub fn inlay_hint(server: &LSPServer, params: &InlayHintParams) -> Option<Vec<In
|
|||||||
for instance in &module.instances {
|
for instance in &module.instances {
|
||||||
// 根据在可见视图外面的 range 就不管了
|
// 根据在可见视图外面的 range 就不管了
|
||||||
if is_visible_range(&instance.instparams, &visible_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) {
|
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(
|
fn make_instparam_hints(
|
||||||
|
server: &LSPServer,
|
||||||
params: &InlayHintParams,
|
params: &InlayHintParams,
|
||||||
instance: &core::hdlparam::Instance
|
instance: &core::hdlparam::Instance,
|
||||||
|
rope: &Rope
|
||||||
) -> Vec<InlayHint> {
|
) -> Vec<InlayHint> {
|
||||||
let mut hints = Vec::<InlayHint>::new();
|
let mut hints = Vec::<InlayHint>::new();
|
||||||
|
|
||||||
@ -66,36 +69,89 @@ fn make_instparam_hints(
|
|||||||
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(
|
fn make_instport_hints(
|
||||||
|
server: &LSPServer,
|
||||||
params: &InlayHintParams,
|
params: &InlayHintParams,
|
||||||
instance: &core::hdlparam::Instance
|
instance: &core::hdlparam::Instance,
|
||||||
|
rope: &Rope
|
||||||
) -> Vec<InlayHint> {
|
) -> Vec<InlayHint> {
|
||||||
let mut hints = Vec::<InlayHint>::new();
|
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 {
|
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 {
|
let port_desc = MarkupContent {
|
||||||
kind: MarkupKind::Markdown,
|
kind: MarkupKind::Markdown,
|
||||||
value: format!("```verilog\n{:?}\n```", port_assigment.port)
|
value: format!("```verilog\n{}\n```", port_info.to_description())
|
||||||
};
|
};
|
||||||
|
|
||||||
let hint = InlayHint {
|
let label = {
|
||||||
position: port_assigment.range.to_lsp_range().start,
|
let dir_type = port_info.dir_type.to_string();
|
||||||
label: InlayHintLabel::String("start".to_string()),
|
if dir_type == "output" {
|
||||||
padding_left: Some(true),
|
format!("{}", dir_type)
|
||||||
padding_right: Some(true),
|
} else {
|
||||||
kind: Some(InlayHintKind::PARAMETER),
|
format!("{}{}", dir_type, " ".repeat(1))
|
||||||
text_edits: None,
|
}
|
||||||
tooltip: Some(InlayHintTooltip::MarkupContent(port_desc)),
|
|
||||||
data: None
|
|
||||||
};
|
};
|
||||||
hints.push(hint);
|
|
||||||
|
|
||||||
let port_desc = MarkupContent {
|
|
||||||
kind: MarkupKind::Markdown,
|
|
||||||
value: format!("```verilog\n{:?}\n```", port_assigment.port)
|
|
||||||
};
|
|
||||||
let hint = InlayHint {
|
let hint = InlayHint {
|
||||||
position: port_assigment.range.to_lsp_range().end,
|
position: hint_position,
|
||||||
label: InlayHintLabel::String("end".to_string()),
|
label: InlayHintLabel::String(label),
|
||||||
padding_left: Some(true),
|
padding_left: Some(true),
|
||||||
padding_right: Some(true),
|
padding_right: Some(true),
|
||||||
kind: Some(InlayHintKind::PARAMETER),
|
kind: Some(InlayHintKind::PARAMETER),
|
||||||
@ -105,6 +161,7 @@ fn make_instport_hints(
|
|||||||
};
|
};
|
||||||
hints.push(hint);
|
hints.push(hint);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hints
|
hints
|
||||||
}
|
}
|
@ -213,18 +213,22 @@ impl LanguageServer for Backend {
|
|||||||
completion_provider: Some(completion_provider),
|
completion_provider: Some(completion_provider),
|
||||||
definition_provider: Some(OneOf::Left(true)),
|
definition_provider: Some(OneOf::Left(true)),
|
||||||
hover_provider: Some(HoverProviderCapability::Simple(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_symbol_provider: Some(OneOf::Left(true)),
|
||||||
document_highlight_provider: Some(OneOf::Left(true)),
|
document_highlight_provider: Some(OneOf::Left(true)),
|
||||||
..ServerCapabilities::default()
|
..ServerCapabilities::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(InitializeResult::default())
|
Ok(InitializeResult {
|
||||||
|
server_info,
|
||||||
|
capabilities,
|
||||||
|
offset_encoding: None
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn initialized(&self, _: InitializedParams) {
|
async fn initialized(&self, _: InitializedParams) {
|
||||||
self.client
|
self.client
|
||||||
.log_message(MessageType::INFO, "digital lsp initialized!")
|
.log_message(MessageType::INFO, "Digital LSP initialized!")
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// self.client.send_notification::<StringNotification>(StringNotification { content: "hello from lsp server".to_string() }).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>> {
|
async fn hover(&self, params: HoverParams) -> Result<Option<Hover>> {
|
||||||
|
|
||||||
Ok(self.server.hover(params))
|
Ok(self.server.hover(params))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,7 +298,6 @@ impl LanguageServer for Backend {
|
|||||||
&self,
|
&self,
|
||||||
params: DocumentSymbolParams,
|
params: DocumentSymbolParams,
|
||||||
) -> Result<Option<DocumentSymbolResponse>> {
|
) -> Result<Option<DocumentSymbolResponse>> {
|
||||||
info!("enter document");
|
|
||||||
Ok(self.server.document_symbol(params))
|
Ok(self.server.document_symbol(params))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +305,6 @@ impl LanguageServer for Backend {
|
|||||||
&self,
|
&self,
|
||||||
params: DocumentHighlightParams,
|
params: DocumentHighlightParams,
|
||||||
) -> Result<Option<Vec<DocumentHighlight>>> {
|
) -> Result<Option<Vec<DocumentHighlight>>> {
|
||||||
info!("enter highlight");
|
|
||||||
Ok(self.server.document_highlight(params))
|
Ok(self.server.document_highlight(params))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,7 +312,6 @@ impl LanguageServer for Backend {
|
|||||||
&self,
|
&self,
|
||||||
params: InlayHintParams
|
params: InlayHintParams
|
||||||
) -> Result<Option<Vec<InlayHint>>> {
|
) -> Result<Option<Vec<InlayHint>>> {
|
||||||
info!("enter inlay_hint");
|
|
||||||
Ok(self.server.inlay_hint(params))
|
Ok(self.server.inlay_hint(params))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,8 +68,6 @@ impl LSPServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn did_change(&self, params: DidChangeTextDocumentParams) {
|
pub fn did_change(&self, params: DidChangeTextDocumentParams) {
|
||||||
info!("[LSPServer] did change");
|
|
||||||
|
|
||||||
let file_id = self.srcs.get_id(¶ms.text_document.uri);
|
let file_id = self.srcs.get_id(¶ms.text_document.uri);
|
||||||
let file = self.srcs.get_file(file_id).unwrap();
|
let file = self.srcs.get_file(file_id).unwrap();
|
||||||
let mut file = file.write().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 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
|
||||||
@ -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> {
|
impl<'a> LSPSupport for RopeSlice<'a> {
|
||||||
@ -831,4 +833,12 @@ 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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user