实现模块跨文件的定义跳转
This commit is contained in:
parent
79f505177d
commit
ceb827b850
@ -1,5 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
use std::f64::consts::E;
|
||||
use std::sync::RwLock;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -25,10 +24,6 @@ pub struct Range {
|
||||
pub end: Position
|
||||
}
|
||||
|
||||
pub trait LikePosition {
|
||||
fn line(&self) -> u32;
|
||||
fn character(&self) -> u32;
|
||||
}
|
||||
|
||||
impl Range {
|
||||
#[allow(unused)]
|
||||
@ -42,6 +37,27 @@ impl Range {
|
||||
pub fn contains(&self, postion: &LspPosition) -> bool {
|
||||
compare_pos(&self.start.to_lsp_position(), postion) != 1 && compare_pos(postion, &self.end.to_lsp_position()) != 1
|
||||
}
|
||||
|
||||
/// 对所有的 line 或者 所有的 character 进行偏移操作
|
||||
pub fn affine(&mut self, line_offset: i32, character_offset: i32) -> &Range {
|
||||
if line_offset > 0 {
|
||||
self.start.line += line_offset as u32;
|
||||
self.end.line += line_offset as u32;
|
||||
} else {
|
||||
self.start.line -= (- line_offset) as u32;
|
||||
self.end.line -= (- line_offset) as u32;
|
||||
}
|
||||
|
||||
if character_offset > 0 {
|
||||
self.start.character += character_offset as u32;
|
||||
self.end.character += character_offset as u32;
|
||||
} else {
|
||||
self.start.character -= (- character_offset) as u32;
|
||||
self.end.character -= (- character_offset) as u32;
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn compare_pos(pos1: &LspPosition, pos2: &LspPosition) -> i32 {
|
||||
|
@ -313,7 +313,7 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re
|
||||
}
|
||||
}
|
||||
|
||||
update_module_range(&path, &mut hdlparam);
|
||||
// update_module_range(&path, &mut hdlparam);
|
||||
|
||||
Ok(hdlparam)
|
||||
}
|
||||
@ -576,6 +576,7 @@ fn get_includes(path: &PathBuf) -> Vec<crate::core::fast_hdlparam::Include> {
|
||||
includes
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn update_module_range(path: &PathBuf, hdlparam: &mut FastHdlparam) {
|
||||
let file = File::open(path).unwrap();
|
||||
let reader = BufReader::new(file);
|
||||
|
@ -159,12 +159,9 @@ fn goto_instantiation<'a>(
|
||||
if token_name == port.name {
|
||||
let def_path = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap();
|
||||
let target_uri = Url::from_file_path(def_path).unwrap();
|
||||
let mut target_range = port.range.to_lsp_range();
|
||||
target_range.start.line -= 1;
|
||||
target_range.start.character -= 1;
|
||||
target_range.end.line -= 1;
|
||||
target_range.end.character -= 1;
|
||||
|
||||
let mut target_range = port.range.clone();
|
||||
let target_range = target_range.affine(-1, -1).to_lsp_range();
|
||||
|
||||
let link = vec![LocationLink {
|
||||
target_uri,
|
||||
origin_selection_range: Some(range.clone()),
|
||||
@ -212,10 +209,26 @@ pub fn goto_position_port_param_definition(
|
||||
None
|
||||
}
|
||||
|
||||
pub fn goto_instance_definition() {
|
||||
pub fn goto_module_declaration_definition(
|
||||
server: &LSPServer,
|
||||
token_name: &str
|
||||
) -> Option<GotoDefinitionResponse> {
|
||||
if let Some(module) = server.srcs.hdl_param.find_module_by_name(token_name) {
|
||||
let def_path = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap();
|
||||
let target_uri = Url::from_file_path(PathBuf::from_str(&def_path).unwrap()).unwrap();
|
||||
|
||||
let mut target_range = module.range.clone();
|
||||
let target_range = target_range.affine(-1, -1).to_lsp_range();
|
||||
|
||||
let link = vec![LocationLink {
|
||||
target_uri,
|
||||
origin_selection_range: None,
|
||||
target_range: target_range,
|
||||
target_selection_range: target_range
|
||||
}];
|
||||
let links = GotoDefinitionResponse::Link(link);
|
||||
return Some(links);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn goto_module_definition() {
|
||||
|
||||
None
|
||||
}
|
@ -49,6 +49,11 @@ impl LSPServer {
|
||||
return Some(definition);
|
||||
}
|
||||
|
||||
// match module name
|
||||
if let Some(definition) = goto_module_declaration_definition(self, &token) {
|
||||
return Some(definition);
|
||||
}
|
||||
|
||||
let byte_idx = file.text.pos_to_byte(&pos);
|
||||
let global_scope = scope_tree.as_ref()?;
|
||||
let def = global_scope.get_definition(&token, byte_idx, &doc)?;
|
||||
|
@ -3,7 +3,7 @@ use std::{path::PathBuf, str::FromStr};
|
||||
use log::info;
|
||||
use regex::Regex;
|
||||
use ropey::RopeSlice;
|
||||
use tower_lsp::lsp_types::{Hover, HoverContents, LanguageString, MarkedString, Position, Range, Url};
|
||||
use tower_lsp::lsp_types::{Hover, HoverContents, LanguageString, MarkedString, MarkupContent, MarkupKind, Position, Range, Url};
|
||||
|
||||
use crate::{core::fast_hdlparam::{Define, FastHdlparam}, server::LSPServer};
|
||||
|
||||
@ -339,7 +339,7 @@ pub fn hover_module_declaration(
|
||||
let port_num = module.ports.len();
|
||||
let param_num = module.params.len();
|
||||
let instance_num = module.instances.len();
|
||||
let port_desc = format!(" port {port_num} param {param_num} instantiation {instance_num}");
|
||||
let port_desc = format!("`port` {port_num}, `param` {param_num}, `instantiation` {instance_num}");
|
||||
|
||||
// 统计 dir
|
||||
let mut input_count = 0 as u32;
|
||||
@ -355,26 +355,25 @@ pub fn hover_module_declaration(
|
||||
}
|
||||
}
|
||||
|
||||
let io_desc = format!(" input {input_count} output {output_count} inout {inout_count}");
|
||||
let desc_string = format!("{} | {}", port_desc, io_desc);
|
||||
let io_desc = format!("`input` {input_count}, `output` {output_count}, `inout` {inout_count}");
|
||||
|
||||
let module_path = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap();
|
||||
let module_pathbuf = PathBuf::from_str(module_path.as_str()).unwrap();
|
||||
let path_string = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap_or("unknown".to_string());
|
||||
let define_info = format!("define in {path_string}");
|
||||
|
||||
let mut markdowns = Vec::<MarkedString>::new();
|
||||
markdowns.push(MarkedString::String(desc_string));
|
||||
markdowns.push(MarkedString::String(port_desc));
|
||||
markdowns.push(MarkedString::String(io_desc));
|
||||
markdowns.push(MarkedString::String("".to_string()));
|
||||
markdowns.push(MarkedString::String(define_info));
|
||||
markdowns.push(MarkedString::String("---".to_string()));
|
||||
|
||||
info!("module range: {:?}", module.range);
|
||||
|
||||
if let Some(code) = get_range_text(&module_pathbuf, &module.range.to_lsp_range()) {
|
||||
let code = LanguageString {
|
||||
language: language_id.to_string(),
|
||||
value: code
|
||||
};
|
||||
markdowns.push(MarkedString::LanguageString(code));
|
||||
}
|
||||
let module_profile = make_module_profile_code(&module);
|
||||
let profile_markdown = LanguageString {
|
||||
language: language_id.to_string(),
|
||||
value: module_profile
|
||||
};
|
||||
markdowns.push(MarkedString::LanguageString(profile_markdown));
|
||||
|
||||
let hover = Hover {
|
||||
contents: HoverContents::Array(markdowns),
|
||||
@ -385,4 +384,65 @@ pub fn hover_module_declaration(
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
|
||||
/// 根据 module 获取 module 的简单描述代码
|
||||
fn make_module_profile_code(module: &crate::core::fast_hdlparam::Module) -> String {
|
||||
let mut codes = Vec::<String>::new();
|
||||
let param_num = module.params.len();
|
||||
let port_num = module.ports.len();
|
||||
|
||||
if module.params.len() > 0 {
|
||||
codes.push(format!("module {} #(", module.name));
|
||||
for (i, param) in module.params.iter().enumerate() {
|
||||
let mut param_desc_array = Vec::<String>::new();
|
||||
param_desc_array.push(format!("parameter {}", param.name));
|
||||
if param.init != "unknown" {
|
||||
param_desc_array.push(param.init.to_string());
|
||||
}
|
||||
|
||||
let param_desc = param_desc_array.join(" ");
|
||||
if i == param_num - 1 {
|
||||
codes.push(format!("\t{param_desc}"));
|
||||
} else {
|
||||
codes.push(format!("\t{param_desc},"));
|
||||
}
|
||||
}
|
||||
codes.push(")(".to_string());
|
||||
} else {
|
||||
codes.push(format!("module {} (", module.name));
|
||||
}
|
||||
|
||||
if module.ports.len() > 0 {
|
||||
for (i, port) in module.ports.iter().enumerate() {
|
||||
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(" ");
|
||||
if i == port_num - 1 {
|
||||
codes.push(format!("\t{port_desc}"));
|
||||
} else {
|
||||
codes.push(format!("\t{port_desc},"));
|
||||
}
|
||||
}
|
||||
codes.push(format!(")"));
|
||||
} else {
|
||||
codes.push(format!(")"));
|
||||
}
|
||||
|
||||
let profile_string = codes.join("\n");
|
||||
profile_string
|
||||
}
|
@ -4,6 +4,7 @@ use crate::definition::*;
|
||||
use crate::server::LSPServer;
|
||||
use crate::sources::LSPSupport;
|
||||
use crate::utils::*;
|
||||
#[allow(unused)]
|
||||
use log::info;
|
||||
use regex::Regex;
|
||||
use ropey::Rope;
|
||||
@ -40,7 +41,6 @@ impl LSPServer {
|
||||
let scope_tree: RwLockReadGuard<'_, Option<GenericScope>> = self.srcs.scope_tree.read().ok()?;
|
||||
let global_scope = scope_tree.as_ref();
|
||||
|
||||
// info!("get scope tree: {:?}", scope_tree);
|
||||
|
||||
// match positional port param
|
||||
if let Some(hover) = hover_position_port_param(self, &line_text, &doc, pos, &language_id) {
|
||||
|
@ -8,6 +8,7 @@ use crate::sources::LSPSupport;
|
||||
|
||||
use super::to_escape_path;
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn get_range_text(path: &PathBuf, range: &Range) -> Option<String> {
|
||||
let path = to_escape_path(path);
|
||||
if let Some(rope) = open_doc_as_rope(&path) {
|
||||
@ -19,6 +20,7 @@ pub fn get_range_text(path: &PathBuf, range: &Range) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn open_doc_as_rope(path: &PathBuf) -> Option<Rope> {
|
||||
if let std::result::Result::Ok(text) = fs::read_to_string(path) {
|
||||
let rope = Rope::from_str(text.as_str());
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 90e9d4cb3ba4e3a55a9b3fcd0fb83389a376ec35
|
||||
Subproject commit 3002b3970b64903ec98a3274d7254fefa82f0435
|
Loading…
x
Reference in New Issue
Block a user