889 lines
25 KiB
Rust
889 lines
25 KiB
Rust
#[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::<Vec<&str>>()
|
||
.join(" ")
|
||
.replace("[ ", "[")
|
||
.replace(" ]", "]")
|
||
.replace(" : ", ":")
|
||
}
|
||
|
||
pub fn copy_defs(defs: &[Box<dyn Definition>]) -> Vec<Box<dyn Definition>> {
|
||
let mut decs: Vec<Box<dyn Definition>> = 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<dyn Scope>]) -> Vec<Box<dyn Scope>> {
|
||
let mut scope_decs: Vec<Box<dyn Scope>> = 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<Box<dyn Definition>>;
|
||
// all the scopes within this scope, ex. task inside a module
|
||
fn scopes(&self) -> &Vec<Box<dyn Scope>>;
|
||
// 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<CompletionItem> {
|
||
let mut completions: Vec<CompletionItem> = 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<String> = 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<GenericDec> {
|
||
let mut definition: Option<GenericDec> = 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<DocumentSymbol> {
|
||
let mut symbols: Vec<DocumentSymbol> = 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<DocumentHighlight> {
|
||
// 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<String>,
|
||
pub modport: Option<String>,
|
||
}
|
||
|
||
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<String>,
|
||
}
|
||
|
||
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<Box<dyn Definition>>,
|
||
pub scopes: Vec<Box<dyn Scope>>,
|
||
}
|
||
|
||
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<Box<dyn Definition>> {
|
||
&self.defs
|
||
}
|
||
|
||
fn scopes(&self) -> &Vec<Box<dyn Scope>> {
|
||
&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<Box<dyn Definition>>,
|
||
}
|
||
|
||
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<String>
|
||
}
|
||
|
||
#[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<Box<dyn Definition>>,
|
||
pub scopes: Vec<Box<dyn Scope>>,
|
||
}
|
||
|
||
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<Box<dyn Definition>> {
|
||
&self.defs
|
||
}
|
||
|
||
fn scopes(&self) -> &Vec<Box<dyn Scope>> {
|
||
&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<Box<dyn Definition>>,
|
||
pub scopes: Vec<Box<dyn Scope>>,
|
||
// class, package
|
||
pub extends: (Vec<String>, Option<String>),
|
||
// class, package
|
||
pub implements: Vec<(String, Option<String>)>,
|
||
}
|
||
|
||
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<Box<dyn Definition>> {
|
||
&self.defs
|
||
}
|
||
|
||
fn scopes(&self) -> &Vec<Box<dyn Scope>> {
|
||
&self.scopes
|
||
}
|
||
}
|