#[allow(unused)] use log::info; use ropey::Rope; use tower_lsp::lsp_types::*; use vhdl_lang::Project; use crate::{sources::LSPSupport, utils::is_character_ordered_match}; /// cleanup the text of a definition so it can be included in completions pub fn clean_type_str(type_str: &str, ident: &str) -> String { let endings: &[_] = &[';', ',']; // remove anything after an equals sign let eq_offset = type_str.find('=').unwrap_or(type_str.len()); let mut result = type_str.to_string(); result.replace_range(eq_offset.., ""); result .trim_start() .trim_end() .trim_end_matches(endings) .trim_end_matches(ident) .split_whitespace() .collect::>() .join(" ") .replace("[ ", "[") .replace(" ]", "]") .replace(" : ", ":") } pub fn copy_defs(defs: &[Box]) -> Vec> { let mut decs: Vec> = Vec::new(); for def in defs { decs.push(Box::new(GenericDec { ident: def.ident(), byte_idx: def.byte_idx(), url: def.url(), type_str: def.type_str(), completion_kind: def.completion_kind(), symbol_kind: def.symbol_kind(), def_type: def.def_type(), })) } decs } pub fn copy_scopes(scopes: &[Box]) -> Vec> { let mut scope_decs: Vec> = Vec::new(); for scope in scopes { let mut scope_copy = GenericScope { ident: scope.ident(), byte_idx: scope.byte_idx(), start: scope.start(), end: scope.end(), url: scope.url(), type_str: scope.type_str(), completion_kind: scope.completion_kind(), symbol_kind: scope.symbol_kind(), def_type: scope.def_type(), defs: Vec::new(), scopes: Vec::new(), }; scope_copy.defs.extend(copy_defs(scope.defs())); scope_copy.scopes.extend(copy_scopes(scope.scopes())); scope_decs.push(Box::new(scope_copy)) } scope_decs } /// Definition 是所有非 scope 类型 symbol 的父类 pub trait Definition: std::fmt::Debug + Sync + Send { /// symbol 或者 scope 的名字,identity 的缩写 /// /// 对于 definition,而言 ident 就是它的字面量,比如 /// ```verilog /// parameter wire_size = 12; /// ``` /// 上面的 `wire_size` 这个 symbol 的 name 就是 `wire_size` /// /// 对于 scope 而言 /// ```verilog /// module beginner(); /// adwadwa /// endmodule /// 上面这个 module scope 的 ident 就是 `beginner` /// ``` fn ident(&self) -> String; /// 相对于文本的偏移量,可以利用 Rope 的 `byte_to_pos` 函数转换成 Position fn byte_idx(&self) -> usize; /// 当前 symbol 所在文件的 url fn url(&self) -> Url; /// 输出 Definition 的字符 fn type_str(&self) -> String; /// 类别,用于自动补全 fn completion_kind(&self) -> CompletionItemKind; /// 类别,用于文件大纲 fn symbol_kind(&self) -> SymbolKind; /// 类别,内部使用 fn def_type(&self) -> DefinitionType; /// 等价于 self.ident.starts_with fn starts_with(&self, token: &str) -> bool; /// 构造 completion 的 item fn completion(&self) -> CompletionItem; } /// Scope 是所有 scope 类型 symbol 的父类 pub trait Scope: std::fmt::Debug + Definition + Sync + Send { // the start byte of this scope fn start(&self) -> usize; // the end byte of this scope fn end(&self) -> usize; // all the within this scope fn defs(&self) -> &Vec>; // all the scopes within this scope, ex. task inside a module fn scopes(&self) -> &Vec>; // the definition of this scope fn definition(&self) -> GenericDec { GenericDec { ident: self.ident(), byte_idx: self.byte_idx(), url: self.url(), type_str: self.type_str(), completion_kind: self.completion_kind(), symbol_kind: self.symbol_kind(), def_type: DefinitionType::GenericScope, } } /// return a completion from the scope tree, this function should be called on the global scope fn get_completion(&self, token: &str, byte_idx: usize, url: &Url) -> Vec { let mut completions: Vec = Vec::new(); // first we need to go down the scope tree, to the scope the user is invoking a completion // in for scope in self.scopes() { // 如果当前的 token 在这个 scope 中,那么需要递归获取这个 scope 中的所有补全项目 if &scope.url() == url && scope.start() <= byte_idx && byte_idx <= scope.end() { completions = scope.get_completion(token, byte_idx, url); break; } } // let completion_idents: Vec = completions.iter().map(|x| x.label.clone()).collect(); // 寻找前缀相同的 symbol // 这里面并没有 macro for symbol in self.defs() { // 此处的去重会在外部完成 let symbol_name = symbol.ident(); // 此处仍然会给出 module 的补全,但是此处的只是名字的补全,而不是自动例化 match &symbol.def_type() { DefinitionType::Port => {}, DefinitionType::Net => {}, DefinitionType::Macro => { // 对于 TextMacro 类型的,因为是全局属性的,不进行补全 // 对于它的补全请参考 vlog_directives_completion & vlog_directives_completion_without_prefix continue; }, DefinitionType::Data => {}, DefinitionType::Modport => {}, DefinitionType::Subroutine => {}, DefinitionType::ModuleInstantiation => {}, DefinitionType::GenericScope => {}, DefinitionType::Class => {}, }; if is_character_ordered_match(token, &symbol_name) { completions.push(symbol.completion()); } } // 寻找前缀相同的 scope for scope in self.scopes() { if scope.starts_with(token) { completions.push(scope.completion()); } } completions } /// 根据输入的 token,计算出这个 token 在 scope 中的定义 /// 比如输入 clock,则返回 clock 这个变量在哪里被定义,没有则返回 None /// - `token`: 需要查找定义的完整的单词 /// - `byte_idx`: 当前光标所在文档的偏移量 /// - `url`: 当前文档的 url fn get_definition(&self, token: &str, byte_idx: usize, url: &Url) -> Option { let mut definition: Option = None; // 递归进入最浅层的 for scope in self.scopes() { if &scope.url() == url && scope.start() <= byte_idx && byte_idx <= scope.end() { definition = scope.get_definition(token, byte_idx, url); break; } } if definition.is_none() { // 优先找 定义,再找 scope for def in self.defs() { if def.ident() == token { return Some(GenericDec { ident: def.ident(), byte_idx: def.byte_idx(), url: def.url(), type_str: def.type_str(), completion_kind: def.completion_kind(), symbol_kind: def.symbol_kind(), def_type: def.def_type(), }); } } for scope in self.scopes() { if scope.ident() == token { return Some(scope.definition()); } } } definition } /// returns all symbols in a document fn document_symbols(&self, uri: &Url, doc: &Rope) -> Vec { let mut symbols: Vec = Vec::new(); for scope in self.scopes() { if &scope.url() == uri { #[allow(deprecated)] symbols.push(DocumentSymbol { name: scope.ident(), detail: Some(scope.type_str()), kind: scope.symbol_kind(), deprecated: None, range: Range::new(doc.byte_to_pos(scope.start()), doc.byte_to_pos(scope.end())), selection_range: Range::new( doc.byte_to_pos(scope.byte_idx()), doc.byte_to_pos(scope.byte_idx() + scope.ident().len()), ), children: Some(scope.document_symbols(uri, doc)), tags: None, }) } } for def in self.defs() { #[allow(deprecated)] symbols.push(DocumentSymbol { name: def.ident(), detail: Some(def.type_str()), kind: def.symbol_kind(), deprecated: None, range: Range::new( doc.byte_to_pos(def.byte_idx()), doc.byte_to_pos(def.byte_idx() + def.ident().len()), ), selection_range: Range::new( doc.byte_to_pos(def.byte_idx()), doc.byte_to_pos(def.byte_idx() + def.ident().len()), ), children: None, tags: None, }) } symbols } /// highlight all references of a symbol fn document_highlights( &self, uri: &Url, doc: &Rope, // all references in the doc's syntax tree references: Vec<(String, usize)>, // byte_idx of symbol definition byte_idx: usize, ) -> Vec { // to find references we need to grab references from locations downward from the // definition for scope in self.scopes() { if &scope.url() == uri && scope.start() <= byte_idx && byte_idx <= scope.end() { return scope.document_highlights(uri, doc, references, byte_idx); } } // we should now be in the scope of the definition, so we can grab all references // in this scope. This also grabs references below this scope. references .iter() .filter(|x| self.start() <= x.1 && x.1 <= self.end()) .map(|x| DocumentHighlight { range: Range::new(doc.byte_to_pos(x.1), doc.byte_to_pos(x.1 + x.0.len())), kind: None, }) .collect() } } #[derive(Debug, Clone, Copy)] pub enum DefinitionType { Port, Net, Macro, Data, Modport, Subroutine, ModuleInstantiation, GenericScope, Class, } #[derive(Debug)] pub struct PortDec { pub ident: String, pub byte_idx: usize, pub url: Url, pub type_str: String, pub completion_kind: CompletionItemKind, pub symbol_kind: SymbolKind, pub def_type: DefinitionType, pub interface: Option, pub modport: Option, } impl PortDec { pub fn new(url: &Url) -> Self { Self { ident: String::new(), byte_idx: 0, type_str: String::new(), completion_kind: CompletionItemKind::PROPERTY, symbol_kind: SymbolKind::PROPERTY, def_type: DefinitionType::Port, interface: None, modport: None, url: url.clone(), } } } impl Definition for PortDec { fn ident(&self) -> String { self.ident.clone() } fn byte_idx(&self) -> usize { self.byte_idx } fn url(&self) -> Url { self.url.clone() } fn type_str(&self) -> String { self.type_str.clone() } fn completion_kind(&self) -> CompletionItemKind { self.completion_kind } fn symbol_kind(&self) -> SymbolKind { self.symbol_kind } fn def_type(&self) -> DefinitionType { self.def_type } fn starts_with(&self, token: &str) -> bool { self.ident.starts_with(token) } fn completion(&self) -> CompletionItem { let label_details = CompletionItemLabelDetails { description: Some("module port".to_string()), ..Default::default() }; CompletionItem { label: self.ident.clone(), detail: Some(clean_type_str(&self.type_str, &self.ident)), label_details: Some(label_details), kind: Some(self.completion_kind), ..CompletionItem::default() } } } #[derive(Debug)] pub struct GenericDec { pub ident: String, pub byte_idx: usize, pub url: Url, pub type_str: String, pub completion_kind: CompletionItemKind, pub symbol_kind: SymbolKind, pub def_type: DefinitionType, } impl GenericDec { pub fn new(url: &Url) -> Self { Self { ident: String::new(), byte_idx: 0, url: url.clone(), type_str: String::new(), completion_kind: CompletionItemKind::VARIABLE, // FIXME: check if this replacement is correct symbol_kind: SymbolKind::NULL, def_type: DefinitionType::Net, } } } impl Definition for GenericDec { fn ident(&self) -> String { self.ident.clone() } fn byte_idx(&self) -> usize { self.byte_idx } fn url(&self) -> Url { self.url.clone() } fn type_str(&self) -> String { self.type_str.clone() } fn completion_kind(&self) -> CompletionItemKind { self.completion_kind } fn symbol_kind(&self) -> SymbolKind { self.symbol_kind } fn def_type(&self) -> DefinitionType { self.def_type } fn starts_with(&self, token: &str) -> bool { self.ident.starts_with(token) } fn completion(&self) -> CompletionItem { CompletionItem { label: self.ident.clone(), detail: Some(clean_type_str(&self.type_str, &self.ident)), kind: Some(self.completion_kind), ..CompletionItem::default() } } } #[derive(Debug)] pub struct PackageImport { pub ident: String, pub byte_idx: usize, pub url: Url, pub type_str: String, pub completion_kind: CompletionItemKind, pub symbol_kind: SymbolKind, pub def_type: DefinitionType, pub asterisk: bool, pub import_ident: Option, } impl PackageImport { pub fn new(url: &Url) -> Self { Self { ident: String::new(), byte_idx: 0, url: url.clone(), type_str: String::new(), completion_kind: CompletionItemKind::TEXT, symbol_kind: SymbolKind::NAMESPACE, def_type: DefinitionType::Data, asterisk: false, import_ident: None, } } } impl Definition for PackageImport { fn ident(&self) -> String { self.ident.clone() } fn byte_idx(&self) -> usize { self.byte_idx } fn url(&self) -> Url { self.url.clone() } fn type_str(&self) -> String { self.type_str.clone() } fn completion_kind(&self) -> CompletionItemKind { self.completion_kind } fn symbol_kind(&self) -> SymbolKind { self.symbol_kind } fn def_type(&self) -> DefinitionType { self.def_type } fn starts_with(&self, token: &str) -> bool { self.ident.starts_with(token) } fn completion(&self) -> CompletionItem { CompletionItem { label: self.ident.clone(), detail: Some(clean_type_str(&self.type_str, &self.ident.clone())), kind: Some(self.completion_kind), ..CompletionItem::default() } } } #[derive(Debug)] pub struct SubDec { pub ident: String, pub byte_idx: usize, pub url: Url, pub type_str: String, pub completion_kind: CompletionItemKind, pub symbol_kind: SymbolKind, pub def_type: DefinitionType, pub start: usize, pub end: usize, pub defs: Vec>, pub scopes: Vec>, } impl SubDec { pub fn new(url: &Url) -> Self { Self { ident: String::new(), byte_idx: 0, url: url.clone(), type_str: String::new(), completion_kind: CompletionItemKind::FUNCTION, symbol_kind: SymbolKind::FUNCTION, def_type: DefinitionType::Subroutine, start: 0, end: 0, defs: Vec::new(), scopes: Vec::new(), } } } impl Definition for SubDec { fn ident(&self) -> String { self.ident.clone() } fn byte_idx(&self) -> usize { self.byte_idx } fn url(&self) -> Url { self.url.clone() } fn type_str(&self) -> String { self.type_str.clone() } fn completion_kind(&self) -> CompletionItemKind { self.completion_kind } fn symbol_kind(&self) -> SymbolKind { self.symbol_kind } fn def_type(&self) -> DefinitionType { self.def_type } fn starts_with(&self, token: &str) -> bool { self.ident.starts_with(token) } fn completion(&self) -> CompletionItem { CompletionItem { label: self.ident.clone(), detail: Some(clean_type_str(&self.type_str, &self.ident)), kind: Some(self.completion_kind), ..CompletionItem::default() } } } impl Scope for SubDec { fn start(&self) -> usize { self.start } fn end(&self) -> usize { self.end } fn defs(&self) -> &Vec> { &self.defs } fn scopes(&self) -> &Vec> { &self.scopes } } #[derive(Debug)] pub struct ModportDec { pub ident: String, pub byte_idx: usize, pub url: Url, pub type_str: String, pub completion_kind: CompletionItemKind, pub symbol_kind: SymbolKind, pub def_type: DefinitionType, pub ports: Vec>, } impl ModportDec { pub fn new(url: &Url) -> Self { Self { ident: String::new(), byte_idx: 0, url: url.clone(), type_str: String::new(), completion_kind: CompletionItemKind::INTERFACE, symbol_kind: SymbolKind::INTERFACE, def_type: DefinitionType::Modport, ports: Vec::new(), } } } impl Definition for ModportDec { fn ident(&self) -> String { self.ident.clone() } fn byte_idx(&self) -> usize { self.byte_idx } fn url(&self) -> Url { self.url.clone() } fn type_str(&self) -> String { self.type_str.clone() } fn completion_kind(&self) -> CompletionItemKind { self.completion_kind } fn symbol_kind(&self) -> SymbolKind { self.symbol_kind } fn def_type(&self) -> DefinitionType { self.def_type } fn starts_with(&self, token: &str) -> bool { self.ident.starts_with(token) } fn completion(&self) -> CompletionItem { CompletionItem { label: self.ident.clone(), detail: Some(clean_type_str(&self.type_str, &self.ident)), kind: Some(self.completion_kind), ..CompletionItem::default() } } } #[derive(Debug)] pub struct ModInst { pub ident: String, pub byte_idx: usize, pub url: Url, pub type_str: String, pub completion_kind: CompletionItemKind, pub symbol_kind: SymbolKind, pub def_type: DefinitionType, pub mod_ident: String, } impl ModInst { pub fn new(url: &Url) -> Self { Self { ident: String::new(), byte_idx: 0, url: url.clone(), type_str: String::new(), completion_kind: CompletionItemKind::MODULE, symbol_kind: SymbolKind::MODULE, def_type: DefinitionType::ModuleInstantiation, mod_ident: String::new(), } } } impl Definition for ModInst { fn ident(&self) -> String { self.ident.clone() } fn byte_idx(&self) -> usize { self.byte_idx } fn url(&self) -> Url { self.url.clone() } fn type_str(&self) -> String { self.type_str.clone() } fn completion_kind(&self) -> CompletionItemKind { self.completion_kind } fn symbol_kind(&self) -> SymbolKind { self.symbol_kind } fn def_type(&self) -> DefinitionType { self.def_type } fn starts_with(&self, token: &str) -> bool { self.ident.starts_with(token) } fn completion(&self) -> CompletionItem { CompletionItem { label: self.ident.clone(), detail: Some(clean_type_str(&self.type_str, &self.ident)), kind: Some(self.completion_kind), ..CompletionItem::default() } } } pub struct VhdlProject { pub project: Project, pub std_config: vhdl_lang::Config, pub config_file_strs: Vec } #[derive(Debug)] pub struct GenericScope { pub ident: String, pub byte_idx: usize, pub start: usize, pub end: usize, pub url: Url, pub type_str: String, pub completion_kind: CompletionItemKind, pub symbol_kind: SymbolKind, pub def_type: DefinitionType, pub defs: Vec>, pub scopes: Vec>, } impl GenericScope { pub fn new(url: &Url) -> Self { Self { ident: String::new(), byte_idx: 0, start: 0, end: 0, url: url.clone(), type_str: String::new(), completion_kind: CompletionItemKind::MODULE, symbol_kind: SymbolKind::MODULE, def_type: DefinitionType::GenericScope, defs: Vec::new(), scopes: Vec::new(), } } } impl Definition for GenericScope { fn ident(&self) -> String { self.ident.clone() } fn byte_idx(&self) -> usize { self.byte_idx } fn url(&self) -> Url { self.url.clone() } fn type_str(&self) -> String { self.type_str.clone() } fn completion_kind(&self) -> CompletionItemKind { self.completion_kind } fn symbol_kind(&self) -> SymbolKind { self.symbol_kind } fn def_type(&self) -> DefinitionType { self.def_type } fn starts_with(&self, token: &str) -> bool { self.ident.starts_with(token) } fn completion(&self) -> CompletionItem { CompletionItem { label: self.ident.clone(), detail: Some(clean_type_str(&self.type_str, &self.ident)), kind: Some(self.completion_kind), ..CompletionItem::default() } } } impl Scope for GenericScope { fn start(&self) -> usize { self.start } fn end(&self) -> usize { self.end } fn defs(&self) -> &Vec> { &self.defs } fn scopes(&self) -> &Vec> { &self.scopes } } #[derive(Debug)] pub struct ClassDec { pub ident: String, pub byte_idx: usize, pub start: usize, pub end: usize, pub url: Url, pub type_str: String, pub completion_kind: CompletionItemKind, pub symbol_kind: SymbolKind, pub def_type: DefinitionType, pub defs: Vec>, pub scopes: Vec>, // class, package pub extends: (Vec, Option), // class, package pub implements: Vec<(String, Option)>, } impl ClassDec { pub fn new(url: &Url) -> Self { Self { ident: String::new(), byte_idx: 0, start: 0, end: 0, url: url.clone(), type_str: String::new(), completion_kind: CompletionItemKind::CLASS, symbol_kind: SymbolKind::CLASS, def_type: DefinitionType::Class, defs: Vec::new(), scopes: Vec::new(), extends: (Vec::new(), None), implements: Vec::new(), } } } impl Definition for ClassDec { fn ident(&self) -> String { self.ident.clone() } fn byte_idx(&self) -> usize { self.byte_idx } fn url(&self) -> Url { self.url.clone() } fn type_str(&self) -> String { self.type_str.clone() } fn completion_kind(&self) -> CompletionItemKind { self.completion_kind } fn symbol_kind(&self) -> SymbolKind { self.symbol_kind } fn def_type(&self) -> DefinitionType { self.def_type } fn starts_with(&self, token: &str) -> bool { self.ident.starts_with(token) } fn completion(&self) -> CompletionItem { CompletionItem { label: self.ident.clone(), detail: Some(clean_type_str(&self.type_str, &self.ident)), kind: Some(self.completion_kind), ..CompletionItem::default() } } } impl Scope for ClassDec { fn start(&self) -> usize { self.start } fn end(&self) -> usize { self.end } fn defs(&self) -> &Vec> { &self.defs } fn scopes(&self) -> &Vec> { &self.scopes } }