实现 macro 跳转
This commit is contained in:
parent
0040a4eb28
commit
b3d7a9faa1
@ -12,7 +12,7 @@ pub struct Range {
|
|||||||
pub end: Position
|
pub end: Position
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, PartialEq, Deserialize)]
|
#[derive(Debug, Serialize, PartialEq, Deserialize, Clone)]
|
||||||
pub struct Port {
|
pub struct Port {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
@ -23,7 +23,7 @@ pub struct Port {
|
|||||||
pub range: Range
|
pub range: Range
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, PartialEq, Deserialize)]
|
#[derive(Debug, Serialize, PartialEq, Deserialize, Clone)]
|
||||||
pub struct Parameter {
|
pub struct Parameter {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub net_type: String,
|
pub net_type: String,
|
||||||
@ -44,7 +44,7 @@ pub struct Parameter {
|
|||||||
// pub range: Range
|
// pub range: Range
|
||||||
// }
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Instance {
|
pub struct Instance {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
@ -54,7 +54,7 @@ pub struct Instance {
|
|||||||
pub range: Range
|
pub range: Range
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Module {
|
pub struct Module {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub params: Vec<Parameter>,
|
pub params: Vec<Parameter>,
|
||||||
@ -63,27 +63,27 @@ pub struct Module {
|
|||||||
pub range: Range
|
pub range: Range
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct DefineParam {
|
pub struct DefineParam {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub value: String
|
pub value: String
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Define {
|
pub struct Define {
|
||||||
name: String,
|
pub name: String,
|
||||||
replacement: String,
|
pub replacement: String,
|
||||||
range: Range,
|
pub range: Range,
|
||||||
params: Vec<DefineParam>
|
pub params: Vec<DefineParam>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Include {
|
pub struct Include {
|
||||||
pub path: String,
|
pub path: String,
|
||||||
pub range: Range
|
pub range: Range
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Error {
|
pub struct Error {
|
||||||
severity: String,
|
severity: String,
|
||||||
message: String,
|
message: String,
|
||||||
@ -93,7 +93,7 @@ pub struct Error {
|
|||||||
running_phase: Option<String>,
|
running_phase: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Macro {
|
pub struct Macro {
|
||||||
pub defines: Vec<Define>,
|
pub defines: Vec<Define>,
|
||||||
pub includes: Vec<Include>,
|
pub includes: Vec<Include>,
|
||||||
@ -101,7 +101,7 @@ pub struct Macro {
|
|||||||
pub invalid: Vec<Range>
|
pub invalid: Vec<Range>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct FastHdlparam {
|
pub struct FastHdlparam {
|
||||||
#[serde(rename = "macro")]
|
#[serde(rename = "macro")]
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
use std::{path::PathBuf, str::FromStr};
|
use std::{path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use regex::Regex;
|
||||||
use ropey::RopeSlice;
|
use ropey::RopeSlice;
|
||||||
use tower_lsp::lsp_types::{GotoDefinitionResponse, LocationLink, Position, Range, Url};
|
use tower_lsp::lsp_types::{GotoDefinitionResponse, LocationLink, Position, Range, Url};
|
||||||
|
|
||||||
use crate::utils::{resolve_path, to_escape_path};
|
use crate::{server::LSPServer, utils::{get_word_range_at_position, resolve_path, to_escape_path}};
|
||||||
|
|
||||||
/// 跳转到定义
|
/// 跳转到 include 的文件
|
||||||
pub fn goto_include_definition(uri: &Url, line: &RopeSlice, pos: Position) -> Option<GotoDefinitionResponse> {
|
pub fn goto_include_definition(uri: &Url, line: &RopeSlice, pos: Position) -> Option<GotoDefinitionResponse> {
|
||||||
let line_text = line.as_str().unwrap_or("");
|
let line_text = line.as_str().unwrap_or("");
|
||||||
if line_text.trim().starts_with("`include") {
|
if line_text.trim().starts_with("`include") {
|
||||||
@ -48,7 +49,7 @@ pub fn goto_include_definition(uri: &Url, line: &RopeSlice, pos: Position) -> Op
|
|||||||
|
|
||||||
let origin_selection_range = Range::new(
|
let origin_selection_range = Range::new(
|
||||||
Position { line: pos.line, character: first_quote_idx as u32 },
|
Position { line: pos.line, character: first_quote_idx as u32 },
|
||||||
Position { line: pos.line, character: last_quote_idx as u32 }
|
Position { line: pos.line, character: (last_quote_idx + 1) as u32 }
|
||||||
);
|
);
|
||||||
|
|
||||||
let target_position = Position { line: 0, character: 0 };
|
let target_position = Position { line: 0, character: 0 };
|
||||||
@ -68,4 +69,43 @@ pub fn goto_include_definition(uri: &Url, line: &RopeSlice, pos: Position) -> Op
|
|||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// 跳转到宏定义
|
||||||
|
pub fn goto_macro_definition(server: &LSPServer, line: &RopeSlice, pos: Position) -> Option<GotoDefinitionResponse> {
|
||||||
|
let macro_text_regex = Regex::new(r"[`0-9a-zA-Z]").unwrap();
|
||||||
|
if let Some((macro_text, range)) = get_word_range_at_position(line, pos, macro_text_regex) {
|
||||||
|
if macro_text.starts_with("`") {
|
||||||
|
if let Some((macro_define, define_path)) = server.find_macros(¯o_text) {
|
||||||
|
let define_path = PathBuf::from_str(&define_path).unwrap();
|
||||||
|
let target_uri = match Url::from_file_path(define_path) {
|
||||||
|
Ok(uri) => uri,
|
||||||
|
Err(_) => return None
|
||||||
|
};
|
||||||
|
|
||||||
|
let start = macro_define.range.start;
|
||||||
|
let end = macro_define.range.end;
|
||||||
|
let target_range = Range::new(
|
||||||
|
Position { line: start.line, character: start.character },
|
||||||
|
Position { line: end.line, character: end.character }
|
||||||
|
);
|
||||||
|
let link = vec![LocationLink {
|
||||||
|
target_uri,
|
||||||
|
origin_selection_range: Some(range),
|
||||||
|
target_range: target_range,
|
||||||
|
target_selection_range: target_range
|
||||||
|
}];
|
||||||
|
let links = GotoDefinitionResponse::Link(link);
|
||||||
|
return Some(links);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn goto_instance_definition() {
|
||||||
|
|
||||||
}
|
}
|
@ -29,11 +29,18 @@ impl LSPServer {
|
|||||||
let line_text = file.text.line(pos.line as usize);
|
let line_text = file.text.line(pos.line as usize);
|
||||||
let token: String = get_definition_token(&line_text, pos);
|
let token: String = get_definition_token(&line_text, pos);
|
||||||
|
|
||||||
let include_definition = goto_include_definition(&doc, &line_text, pos);
|
// match include
|
||||||
if include_definition.is_some() {
|
if let Some(definition) = goto_include_definition(&doc, &line_text, pos) {
|
||||||
return include_definition;
|
return Some(definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// match macro
|
||||||
|
if let Some(definition) = goto_macro_definition(self, &line_text, pos) {
|
||||||
|
return Some(definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
// match instance
|
||||||
|
|
||||||
let scope_tree = self.srcs.scope_tree.read().ok()?;
|
let scope_tree = self.srcs.scope_tree.read().ok()?;
|
||||||
|
|
||||||
let def = scope_tree
|
let def = scope_tree
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
|
use std::{path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
|
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};
|
use tower_lsp::lsp_types::{Hover, HoverContents, LanguageString, MarkedString, Position, Range, Url};
|
||||||
|
|
||||||
use super::get_word_range_at_position;
|
use crate::{core::fast_hdlparam::Define, server::LSPServer};
|
||||||
|
|
||||||
|
use super::{get_word_range_at_position, resolve_path, to_escape_path};
|
||||||
|
|
||||||
/// 将 4'b0011 分解为 ("b", "0011")
|
/// 将 4'b0011 分解为 ("b", "0011")
|
||||||
fn parse_digit_string(digit_string: &str) -> Option<(&str, &str)> {
|
fn parse_digit_string(digit_string: &str) -> Option<(&str, &str)> {
|
||||||
@ -98,4 +103,102 @@ pub fn match_format_digit(line: &RopeSlice, pos: Position, language_id: &str) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hover_include(uri: &Url, line: &RopeSlice, pos: Position, language_id: &String) -> Option<Hover> {
|
||||||
|
let line_text = line.as_str().unwrap_or("");
|
||||||
|
if line_text.trim().starts_with("`include") {
|
||||||
|
let character = pos.character as usize;
|
||||||
|
let first_quote_idx = line_text.find("\"");
|
||||||
|
let last_quote_idx = line_text.rfind("\"");
|
||||||
|
|
||||||
|
if first_quote_idx.is_none() || last_quote_idx.is_none() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let first_quote_idx = first_quote_idx.unwrap();
|
||||||
|
let last_quote_idx = last_quote_idx.unwrap();
|
||||||
|
if character >= first_quote_idx && character <= last_quote_idx {
|
||||||
|
let mut path_string = &line_text[(first_quote_idx + 1) .. last_quote_idx];
|
||||||
|
if path_string.starts_with("./") || path_string.starts_with(".\\") {
|
||||||
|
path_string = &path_string[2 ..];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 路径转换
|
||||||
|
let path = match PathBuf::from_str(uri.path()) {
|
||||||
|
Ok(path) => path,
|
||||||
|
Err(error) => {
|
||||||
|
info!("error happen in <goto_include_definition>: {:?}", error);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let escape_path = to_escape_path(&path);
|
||||||
|
let escape_path = escape_path.to_str().unwrap_or("");
|
||||||
|
if escape_path.len() == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(abs_path) = resolve_path(escape_path, path_string) {
|
||||||
|
let content = format!("{:?}", abs_path).replace("\\", "/");
|
||||||
|
let language_string = LanguageString {
|
||||||
|
language: language_id.to_string(),
|
||||||
|
value: content
|
||||||
|
};
|
||||||
|
let markdown = MarkedString::LanguageString(language_string);
|
||||||
|
let range = Range::new(
|
||||||
|
Position { line: pos.line, character: first_quote_idx as u32 },
|
||||||
|
Position { line: pos.line, character: (last_quote_idx + 1) as u32 }
|
||||||
|
);
|
||||||
|
let hover = Hover {
|
||||||
|
contents: HoverContents::Scalar(markdown),
|
||||||
|
range: Some(range)
|
||||||
|
};
|
||||||
|
return Some(hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_macro_define_content(macro_define: &Define) -> String {
|
||||||
|
let macro_name = macro_define.name.trim();
|
||||||
|
let macro_value = macro_define.replacement.trim();
|
||||||
|
if macro_define.params.len() == 0 {
|
||||||
|
format!("`define {} {}", macro_name, macro_value)
|
||||||
|
} else {
|
||||||
|
let mut macro_sig_vec: Vec<String> = Vec::new();
|
||||||
|
for macro_param in ¯o_define.params {
|
||||||
|
if macro_param.value == "Unknown" {
|
||||||
|
macro_sig_vec.push(macro_param.name.to_string());
|
||||||
|
} else {
|
||||||
|
macro_sig_vec.push(format!("{}={}", macro_param.name, macro_param.value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let macro_sig = macro_sig_vec.join(", ");
|
||||||
|
format!("`define {}({}) {}", macro_name, macro_sig, macro_value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hover_macro(server: &LSPServer, line: &RopeSlice, pos: Position, language_id: &str) -> Option<Hover> {
|
||||||
|
let macro_text_regex = Regex::new(r"[`0-9a-zA-Z]").unwrap();
|
||||||
|
if let Some((macro_text, range)) = get_word_range_at_position(line, pos, macro_text_regex) {
|
||||||
|
if macro_text.starts_with("`") {
|
||||||
|
if let Some((macro_define, _)) = server.find_macros(¯o_text) {
|
||||||
|
let content = make_macro_define_content(¯o_define);
|
||||||
|
let language_string = LanguageString {
|
||||||
|
language: language_id.to_string(),
|
||||||
|
value: content
|
||||||
|
};
|
||||||
|
let markdown = MarkedString::LanguageString(language_string);
|
||||||
|
let hover = Hover {
|
||||||
|
contents: HoverContents::Scalar(markdown),
|
||||||
|
range: Some(range)
|
||||||
|
};
|
||||||
|
return Some(hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
use std::{path::PathBuf, str::FromStr, sync::RwLockReadGuard};
|
use std::sync::RwLockReadGuard;
|
||||||
|
|
||||||
use crate::definition::*;
|
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::*;
|
||||||
use log::info;
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use ropey::{Rope, RopeSlice};
|
use ropey::Rope;
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
|
|
||||||
pub mod feature;
|
pub mod feature;
|
||||||
@ -26,10 +25,15 @@ impl LSPServer {
|
|||||||
let language_id = get_language_id_by_uri(&doc);
|
let language_id = get_language_id_by_uri(&doc);
|
||||||
|
|
||||||
// match `include
|
// match `include
|
||||||
if let Some(hover) = match_include(&doc, &line_text, pos, &language_id) {
|
if let Some(hover) = hover_include(&doc, &line_text, pos, &language_id) {
|
||||||
return Some(hover);
|
return Some(hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// match macro
|
||||||
|
if let Some(hover) = hover_macro(self, &line_text, pos, &language_id) {
|
||||||
|
return Some(hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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();
|
||||||
@ -89,12 +93,10 @@ fn get_hover(doc: &Rope, line: usize) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
hover.reverse();
|
hover.reverse();
|
||||||
info!("hover array: {:?}", hover);
|
|
||||||
|
|
||||||
let multi_space_regex = Regex::new(r"\s+").unwrap();
|
let multi_space_regex = Regex::new(r"\s+").unwrap();
|
||||||
|
|
||||||
let line_handler = |line: &str| -> String {
|
let line_handler = |line: &str| -> String {
|
||||||
let line = multi_space_regex.replace_all(line.trim(), " ");
|
let line = multi_space_regex.replace_all(line.trim(), " ");
|
||||||
let line = line.into_owned();
|
let line = line.into_owned();
|
||||||
return format!("{}\n", line);
|
return format!("{}\n", line);
|
||||||
};
|
};
|
||||||
@ -112,60 +114,6 @@ fn get_hover(doc: &Rope, line: usize) -> String {
|
|||||||
result.join("").trim_end().to_owned()
|
result.join("").trim_end().to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn match_include(uri: &Url, line: &RopeSlice, pos: Position, language_id: &String) -> Option<Hover> {
|
|
||||||
let line_text = line.as_str().unwrap_or("");
|
|
||||||
if line_text.trim().starts_with("`include") {
|
|
||||||
let character = pos.character as usize;
|
|
||||||
let first_quote_idx = line_text.find("\"");
|
|
||||||
let last_quote_idx = line_text.rfind("\"");
|
|
||||||
|
|
||||||
if first_quote_idx.is_none() || last_quote_idx.is_none() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let first_quote_idx = first_quote_idx.unwrap();
|
|
||||||
let last_quote_idx = last_quote_idx.unwrap();
|
|
||||||
if character >= first_quote_idx && character <= last_quote_idx {
|
|
||||||
let mut path_string = &line_text[(first_quote_idx + 1) .. last_quote_idx];
|
|
||||||
if path_string.starts_with("./") || path_string.starts_with(".\\") {
|
|
||||||
path_string = &path_string[2 ..];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 路径转换
|
|
||||||
let path = match PathBuf::from_str(uri.path()) {
|
|
||||||
Ok(path) => path,
|
|
||||||
Err(error) => {
|
|
||||||
info!("error happen in <goto_include_definition>: {:?}", error);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let escape_path = to_escape_path(&path);
|
|
||||||
let escape_path = escape_path.to_str().unwrap_or("");
|
|
||||||
if escape_path.len() == 0 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(abs_path) = resolve_path(escape_path, path_string) {
|
|
||||||
let content = format!("{:?}", abs_path);
|
|
||||||
let language_string = LanguageString {
|
|
||||||
language: language_id.to_string(),
|
|
||||||
value: content
|
|
||||||
};
|
|
||||||
let markdown = MarkedString::LanguageString(language_string);
|
|
||||||
let hover = Hover {
|
|
||||||
contents: HoverContents::Scalar(markdown),
|
|
||||||
range: None
|
|
||||||
};
|
|
||||||
return Some(hover);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn match_common_symbol(
|
fn match_common_symbol(
|
||||||
scope_tree: &GenericScope,
|
scope_tree: &GenericScope,
|
||||||
token: &String,
|
token: &String,
|
||||||
|
@ -2,9 +2,8 @@
|
|||||||
|
|
||||||
use request::{ CustomParamRequest, CustomRequest, DoFastApi };
|
use request::{ CustomParamRequest, CustomRequest, DoFastApi };
|
||||||
|
|
||||||
use digital_lsp::server::GLOBAL_FAST_MAP;
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use std::{collections::HashMap, sync::{Arc, RwLock}};
|
use std::sync::Arc;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use tower_lsp::{LspService, Server};
|
use tower_lsp::{LspService, Server};
|
||||||
|
|
||||||
@ -40,10 +39,7 @@ async fn main() {
|
|||||||
let (service, socket) = LspService::build(|client| {
|
let (service, socket) = LspService::build(|client| {
|
||||||
let backend = Arc::new(Backend::new(client, log_handle));
|
let backend = Arc::new(Backend::new(client, log_handle));
|
||||||
|
|
||||||
// 初始化全局变量
|
|
||||||
let _ = GLOBAL_BACKEND.set(backend.clone());
|
let _ = GLOBAL_BACKEND.set(backend.clone());
|
||||||
let _ = GLOBAL_FAST_MAP.set(RwLock::new(HashMap::new()));
|
|
||||||
|
|
||||||
backend
|
backend
|
||||||
})
|
})
|
||||||
.custom_method("custom/request", CustomRequest)
|
.custom_method("custom/request", CustomRequest)
|
||||||
|
@ -13,7 +13,7 @@ use crate::core::fast_hdlparam::FastHdlparam;
|
|||||||
use crate::core::sv_parser::make_fast_from_syntaxtree;
|
use crate::core::sv_parser::make_fast_from_syntaxtree;
|
||||||
|
|
||||||
use crate::utils::*;
|
use crate::utils::*;
|
||||||
use crate::server::{update_global_fast, Backend, GLOBAL_BACKEND, GLOBAL_FAST_MAP};
|
use crate::server::{Backend, GLOBAL_BACKEND};
|
||||||
use crate::sources::recovery_sv_parse;
|
use crate::sources::recovery_sv_parse;
|
||||||
|
|
||||||
|
|
||||||
@ -69,8 +69,8 @@ impl <'a>tower_lsp::jsonrpc::Method<&'a Arc<Backend>, (DoFastApiRequestParams, )
|
|||||||
fn invoke(&self, _server: &'a Arc<Backend>, _params: (DoFastApiRequestParams, )) -> Self::Future {
|
fn invoke(&self, _server: &'a Arc<Backend>, _params: (DoFastApiRequestParams, )) -> Self::Future {
|
||||||
let request_param = _params.0;
|
let request_param = _params.0;
|
||||||
let path = request_param.path;
|
let path = request_param.path;
|
||||||
let fut = future::ready(do_fast(path));
|
let hdlparam = do_fast(path, _server);
|
||||||
fut
|
future::ready(hdlparam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ fn make_textdocumenitem_from_path(path_buf: &PathBuf) -> Option<TextDocumentItem
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 前端交互接口: do_fast,输入文件路径,计算出对应的 fast 结构
|
/// 前端交互接口: do_fast,输入文件路径,计算出对应的 fast 结构
|
||||||
pub fn do_fast(path: String) -> Result<FastHdlparam> {
|
pub fn do_fast<'a>(path: String, _server: &Arc<Backend>) -> Result<FastHdlparam> {
|
||||||
info!("parse fast {}", path);
|
info!("parse fast {}", path);
|
||||||
|
|
||||||
let path_buf = PathBuf::from(&path);
|
let path_buf = PathBuf::from(&path);
|
||||||
@ -115,12 +115,13 @@ pub fn do_fast(path: String) -> Result<FastHdlparam> {
|
|||||||
&includes
|
&includes
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if let Some(syntax_tree) = parse_result {
|
if let Some(syntax_tree) = parse_result {
|
||||||
if let Ok(hdlparam) = make_fast_from_syntaxtree(&syntax_tree, &path_buf) {
|
if let Ok(hdlparam) = make_fast_from_syntaxtree(&syntax_tree, &path_buf) {
|
||||||
update_global_fast(&hdlparam);
|
let mut fast_map = _server.server.srcs.fast_map.write().unwrap();
|
||||||
return Ok(hdlparam);
|
fast_map.insert(path.to_string(), hdlparam);
|
||||||
|
if let Some(hdlparam) = fast_map.get(&path) {
|
||||||
|
return Ok(hdlparam.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use crate::core::fast_hdlparam::FastHdlparam;
|
|
||||||
use crate::sources::*;
|
use crate::sources::*;
|
||||||
use crate::completion::keyword::*;
|
use crate::completion::keyword::*;
|
||||||
use flexi_logger::LoggerHandle;
|
use flexi_logger::LoggerHandle;
|
||||||
@ -6,7 +5,6 @@ use flexi_logger::LoggerHandle;
|
|||||||
use log::{debug, info, warn};
|
use log::{debug, info, warn};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
use std::sync::{Arc, Mutex, RwLock};
|
use std::sync::{Arc, Mutex, RwLock};
|
||||||
use tower_lsp::jsonrpc::Result;
|
use tower_lsp::jsonrpc::Result;
|
||||||
@ -14,7 +12,6 @@ use tower_lsp::lsp_types::*;
|
|||||||
use tower_lsp::{Client, LanguageServer};
|
use tower_lsp::{Client, LanguageServer};
|
||||||
|
|
||||||
pub static GLOBAL_BACKEND: OnceCell<Arc<Backend>> = OnceCell::new();
|
pub static GLOBAL_BACKEND: OnceCell<Arc<Backend>> = OnceCell::new();
|
||||||
pub static GLOBAL_FAST_MAP: OnceCell<RwLock<HashMap<String, FastHdlparam>>> = OnceCell::new();
|
|
||||||
|
|
||||||
pub struct LSPServer {
|
pub struct LSPServer {
|
||||||
pub srcs: Sources,
|
pub srcs: Sources,
|
||||||
@ -301,6 +298,3 @@ impl LanguageServer for Backend {
|
|||||||
Ok(self.server.document_highlight(params))
|
Ok(self.server.document_highlight(params))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_global_fast(fast: &FastHdlparam) {
|
|
||||||
}
|
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::core::fast_hdlparam::FastHdlparam;
|
||||||
use crate::definition::def_types::*;
|
use crate::definition::def_types::*;
|
||||||
use crate::definition::get_scopes;
|
use crate::definition::get_scopes;
|
||||||
use crate::diagnostics::{get_diagnostics, is_hidden};
|
use crate::diagnostics::{get_diagnostics, is_hidden};
|
||||||
@ -162,6 +163,8 @@ pub struct Sources {
|
|||||||
pub include_dirs: Arc<RwLock<Vec<PathBuf>>>,
|
pub include_dirs: Arc<RwLock<Vec<PathBuf>>>,
|
||||||
// source directories
|
// source directories
|
||||||
pub source_dirs: Arc<RwLock<Vec<PathBuf>>>,
|
pub source_dirs: Arc<RwLock<Vec<PathBuf>>>,
|
||||||
|
// fast result
|
||||||
|
pub fast_map: Arc<RwLock<HashMap<String, FastHdlparam>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::default::Default for Sources {
|
impl std::default::Default for Sources {
|
||||||
@ -179,6 +182,7 @@ impl Sources {
|
|||||||
scope_tree: Arc::new(RwLock::new(None)),
|
scope_tree: Arc::new(RwLock::new(None)),
|
||||||
include_dirs: Arc::new(RwLock::new(Vec::new())),
|
include_dirs: Arc::new(RwLock::new(Vec::new())),
|
||||||
source_dirs: Arc::new(RwLock::new(Vec::new())),
|
source_dirs: Arc::new(RwLock::new(Vec::new())),
|
||||||
|
fast_map: Arc::new(RwLock::new(HashMap::new()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn init(&self) {
|
pub fn init(&self) {
|
||||||
|
21
src/utils/fast.rs
Normal file
21
src/utils/fast.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
use crate::{core::fast_hdlparam::Define, server::LSPServer};
|
||||||
|
|
||||||
|
impl LSPServer {
|
||||||
|
/// 根据输入的 macro 名字,寻找 fast 中存在的第一个 macro
|
||||||
|
/// macro 可以以 ` 开头
|
||||||
|
pub fn find_macros(&self, macro_name: &str) -> Option<(Define, String)> {
|
||||||
|
let macro_name = macro_name.replace("`", "");
|
||||||
|
let fast_map = self.srcs.fast_map.read().unwrap();
|
||||||
|
for path in fast_map.keys() {
|
||||||
|
if let Some(hdlparam) = fast_map.get(path) {
|
||||||
|
for define in &hdlparam.fast_macro.defines {
|
||||||
|
if define.name == macro_name {
|
||||||
|
return Some((define.clone(), path.to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,8 @@ use regex::Regex;
|
|||||||
use ropey::RopeSlice;
|
use ropey::RopeSlice;
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
|
|
||||||
|
pub mod fast;
|
||||||
|
|
||||||
/// 根据 pos 获取到当前光标所在的字符串,相当于 getWordRangeAtPosition
|
/// 根据 pos 获取到当前光标所在的字符串,相当于 getWordRangeAtPosition
|
||||||
pub fn get_definition_token(line: &RopeSlice, pos: Position) -> String {
|
pub fn get_definition_token(line: &RopeSlice, pos: Position) -> String {
|
||||||
let mut token = String::new();
|
let mut token = String::new();
|
||||||
@ -137,5 +139,4 @@ pub fn to_escape_path(path: &PathBuf) -> PathBuf {
|
|||||||
PathBuf::from(decoded_path_str)
|
PathBuf::from(decoded_path_str)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user