-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathauto_complete_provider.rs
129 lines (114 loc) · 4.19 KB
/
auto_complete_provider.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use osmium_libs_solidity_ast_extractor::types::SolidityAstFile;
use solc_ast_rs_types::types::{ContractDefinition, ImportDirective};
use crate::{
completions::{
position_scope_visitor::PositionScopeVisitor,
spi_completion_provider::SPICompletionProvider,
},
types::{self, CompletionItem},
Position,
};
use super::{
imports_completion_visitor::ImportCompletionVisitor,
inheritence_completion_visitor::InheritenceCompletionVisitor,
};
pub struct AutoCompleteProvider {}
impl AutoCompleteProvider {
pub fn new() -> Self {
Self {}
}
fn while_inherits(
&self,
contract: &ContractDefinition,
root_file: &SolidityAstFile,
files: &Vec<SolidityAstFile>,
) -> Vec<CompletionItem> {
let mut complete_finder = InheritenceCompletionVisitor::new(contract.clone());
let mut completes: Vec<CompletionItem> = vec![];
let mut inheritences = vec![contract.clone()];
while let Some(current) = inheritences.pop() {
// info!("Current contract to search for inheritence: {:?}", current.name);
for file in files {
let (items, inheritences_res) = complete_finder.find(
&file.ast,
root_file.file.path == file.file.path,
current.clone(),
);
completes.append(&mut items.clone());
inheritences.append(&mut inheritences_res.clone());
}
}
completes
}
fn get_import_completes(
&self,
imports: Vec<ImportDirective>,
files: &Vec<SolidityAstFile>,
) -> Vec<CompletionItem> {
let mut completes: Vec<CompletionItem> = vec![];
let mut imports_to_check: Vec<ImportDirective> = vec![];
for import in imports {
if import.unit_alias.is_empty() && import.symbol_aliases.is_empty() {
imports_to_check.push(import);
} else if import.unit_alias.is_empty() {
for symbol in import.symbol_aliases {
completes.push(CompletionItem {
label: symbol.foreign.name.clone(),
kind: types::CompletionItemKind::MODULE,
});
}
} else {
completes.push(CompletionItem {
label: import.unit_alias.clone(),
kind: types::CompletionItemKind::MODULE,
});
}
}
let mut import_finder = ImportCompletionVisitor::new(imports_to_check.clone());
let files = import_finder.get_files_from_imports(files);
for file in files {
completes.append(&mut import_finder.find(&file.ast));
}
completes
}
pub fn get_suggestions(
&self,
uri: &str,
position: Position,
files: &Vec<SolidityAstFile>,
) -> Vec<CompletionItem> {
if let Some(file) = files.iter().find(|file| file.file.path == uri) {
let mut scope_finder = PositionScopeVisitor::new(file.file.content.clone(), position);
let (contract, spi, imports) = scope_finder.find(&file.ast);
let mut completes: Vec<CompletionItem> = vec![];
if let Some(contract) = contract {
completes.append(&mut self.while_inherits(&contract, file, files));
}
let spi_finder = SPICompletionProvider::new(spi);
completes.append(&mut spi_finder.inspect());
completes.append(&mut self.get_import_completes(imports, files));
return completes;
}
vec![]
}
}
#[cfg(test)]
mod test {
use crate::test_utils::{create_test_ast_file, create_test_ast_file_struct_definition};
use super::*;
#[test]
fn test_get_suggestions() {
let provider = AutoCompleteProvider::new();
let uri = "test.sol";
let position = Position {
line: 10,
column: 15,
};
let files = vec![
create_test_ast_file(),
create_test_ast_file_struct_definition(),
];
let completes = provider.get_suggestions(uri, position, &files);
assert_eq!(completes.len(), 4);
}
}