实现模块跨文件的定义跳转
This commit is contained in:
parent
79f505177d
commit
ceb827b850
@ -1,5 +1,4 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::f64::consts::E;
|
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -25,10 +24,6 @@ pub struct Range {
|
|||||||
pub end: Position
|
pub end: Position
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait LikePosition {
|
|
||||||
fn line(&self) -> u32;
|
|
||||||
fn character(&self) -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Range {
|
impl Range {
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
@ -42,6 +37,27 @@ impl Range {
|
|||||||
pub fn contains(&self, postion: &LspPosition) -> bool {
|
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
|
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 {
|
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)
|
Ok(hdlparam)
|
||||||
}
|
}
|
||||||
@ -576,6 +576,7 @@ fn get_includes(path: &PathBuf) -> Vec<crate::core::fast_hdlparam::Include> {
|
|||||||
includes
|
includes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
fn update_module_range(path: &PathBuf, hdlparam: &mut FastHdlparam) {
|
fn update_module_range(path: &PathBuf, hdlparam: &mut FastHdlparam) {
|
||||||
let file = File::open(path).unwrap();
|
let file = File::open(path).unwrap();
|
||||||
let reader = BufReader::new(file);
|
let reader = BufReader::new(file);
|
||||||
|
@ -159,11 +159,8 @@ fn goto_instantiation<'a>(
|
|||||||
if token_name == port.name {
|
if token_name == port.name {
|
||||||
let def_path = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap();
|
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 target_uri = Url::from_file_path(def_path).unwrap();
|
||||||
let mut target_range = port.range.to_lsp_range();
|
let mut target_range = port.range.clone();
|
||||||
target_range.start.line -= 1;
|
let target_range = target_range.affine(-1, -1).to_lsp_range();
|
||||||
target_range.start.character -= 1;
|
|
||||||
target_range.end.line -= 1;
|
|
||||||
target_range.end.character -= 1;
|
|
||||||
|
|
||||||
let link = vec![LocationLink {
|
let link = vec![LocationLink {
|
||||||
target_uri,
|
target_uri,
|
||||||
@ -212,10 +209,26 @@ pub fn goto_position_port_param_definition(
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn goto_instance_definition() {
|
pub fn goto_module_declaration_definition(
|
||||||
|
server: &LSPServer,
|
||||||
}
|
token_name: &str
|
||||||
|
) -> Option<GotoDefinitionResponse> {
|
||||||
pub fn goto_module_definition() {
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
}
|
}
|
@ -49,6 +49,11 @@ impl LSPServer {
|
|||||||
return Some(definition);
|
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 byte_idx = file.text.pos_to_byte(&pos);
|
||||||
let global_scope = scope_tree.as_ref()?;
|
let global_scope = scope_tree.as_ref()?;
|
||||||
let def = global_scope.get_definition(&token, byte_idx, &doc)?;
|
let def = global_scope.get_definition(&token, byte_idx, &doc)?;
|
||||||
|
@ -3,7 +3,7 @@ use std::{path::PathBuf, str::FromStr};
|
|||||||
use log::info;
|
use log::info;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use ropey::RopeSlice;
|
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};
|
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 port_num = module.ports.len();
|
||||||
let param_num = module.params.len();
|
let param_num = module.params.len();
|
||||||
let instance_num = module.instances.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
|
// 统计 dir
|
||||||
let mut input_count = 0 as u32;
|
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 io_desc = format!("`input` {input_count}, `output` {output_count}, `inout` {inout_count}");
|
||||||
let desc_string = format!("{} | {}", port_desc, io_desc);
|
|
||||||
|
|
||||||
let module_path = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap();
|
let path_string = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap_or("unknown".to_string());
|
||||||
let module_pathbuf = PathBuf::from_str(module_path.as_str()).unwrap();
|
let define_info = format!("define in {path_string}");
|
||||||
|
|
||||||
let mut markdowns = Vec::<MarkedString>::new();
|
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("".to_string()));
|
||||||
|
markdowns.push(MarkedString::String(define_info));
|
||||||
markdowns.push(MarkedString::String("---".to_string()));
|
markdowns.push(MarkedString::String("---".to_string()));
|
||||||
|
|
||||||
info!("module range: {:?}", module.range);
|
info!("module range: {:?}", module.range);
|
||||||
|
let module_profile = make_module_profile_code(&module);
|
||||||
if let Some(code) = get_range_text(&module_pathbuf, &module.range.to_lsp_range()) {
|
let profile_markdown = LanguageString {
|
||||||
let code = LanguageString {
|
|
||||||
language: language_id.to_string(),
|
language: language_id.to_string(),
|
||||||
value: code
|
value: module_profile
|
||||||
};
|
};
|
||||||
markdowns.push(MarkedString::LanguageString(code));
|
markdowns.push(MarkedString::LanguageString(profile_markdown));
|
||||||
}
|
|
||||||
|
|
||||||
let hover = Hover {
|
let hover = Hover {
|
||||||
contents: HoverContents::Array(markdowns),
|
contents: HoverContents::Array(markdowns),
|
||||||
@ -386,3 +385,64 @@ pub fn hover_module_declaration(
|
|||||||
|
|
||||||
None
|
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::server::LSPServer;
|
||||||
use crate::sources::LSPSupport;
|
use crate::sources::LSPSupport;
|
||||||
use crate::utils::*;
|
use crate::utils::*;
|
||||||
|
#[allow(unused)]
|
||||||
use log::info;
|
use log::info;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use ropey::Rope;
|
use ropey::Rope;
|
||||||
@ -40,7 +41,6 @@ impl LSPServer {
|
|||||||
let scope_tree: RwLockReadGuard<'_, Option<GenericScope>> = self.srcs.scope_tree.read().ok()?;
|
let scope_tree: RwLockReadGuard<'_, Option<GenericScope>> = self.srcs.scope_tree.read().ok()?;
|
||||||
let global_scope = scope_tree.as_ref();
|
let global_scope = scope_tree.as_ref();
|
||||||
|
|
||||||
// info!("get scope tree: {:?}", scope_tree);
|
|
||||||
|
|
||||||
// match positional port param
|
// match positional port param
|
||||||
if let Some(hover) = hover_position_port_param(self, &line_text, &doc, pos, &language_id) {
|
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;
|
use super::to_escape_path;
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn get_range_text(path: &PathBuf, range: &Range) -> Option<String> {
|
pub fn get_range_text(path: &PathBuf, range: &Range) -> Option<String> {
|
||||||
let path = to_escape_path(path);
|
let path = to_escape_path(path);
|
||||||
if let Some(rope) = open_doc_as_rope(&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
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn open_doc_as_rope(path: &PathBuf) -> Option<Rope> {
|
pub fn open_doc_as_rope(path: &PathBuf) -> Option<Rope> {
|
||||||
if let std::result::Result::Ok(text) = fs::read_to_string(path) {
|
if let std::result::Result::Ok(text) = fs::read_to_string(path) {
|
||||||
let rope = Rope::from_str(text.as_str());
|
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