Skip to content

Commit 67061ac

Browse files
authored
merge: #10 from astrodevs-labs/feat/9-autocomplete-staging
9 - Autocomplete
2 parents c329404 + 2543611 commit 67061ac

39 files changed

+1489
-587
lines changed

.vscode/settings.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,8 @@
1010
},
1111
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
1212
"typescript.tsc.autoDetect": "off",
13-
"npm.packageManager": "bun"
14-
}
13+
"npm.packageManager": "pnpm",
14+
"rust-analyzer.linkedProjects": [
15+
".\\libs\\code-actions\\Cargo.toml"
16+
]
17+
}

Cargo.lock

Lines changed: 23 additions & 23 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/ast-extractor/src/extract.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,15 @@ fn get_ast_from_foundry_output(
3434
if file.file.contains("safeconsole.sol") {
3535
continue;
3636
}
37-
let ast: SourceUnit = serde_json::from_value(file.clone().json).map_err(|e| {
37+
let ast: Result<SourceUnit, serde_json::Error> = serde_json::from_value(file.clone().json);
38+
if let Err(e) = &ast {
3839
error!(
3940
"Error while parsing json ast in file '{}': {:?}",
4041
file.file, e
4142
);
42-
e
43-
})?;
43+
continue;
44+
}
45+
let ast = ast.unwrap();
4446
let out_path = &file.file;
4547
ast_files.push(SolidityAstFile {
4648
file: SolidityFile {
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"rust-analyzer.linkedProjects": [
3+
".\\Cargo.toml",
4+
".\\Cargo.toml"
5+
]
6+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "osmium-libs-solidity-references"
2+
name = "osmium-libs-solidity-code-actions"
33
version = "0.1.0"
44
edition = "2021"
55

Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
{
2-
"name": "osmium-libs-solidity-references",
3-
"license": "GNU-GPL-3.0",
4-
"scripts": {
5-
"build": "cargo build --release --target-dir ./target",
6-
"format": "cargo fmt --all",
7-
"format:check": "cargo fmt --check --all",
8-
"test": "cargo test",
9-
"lint": "cargo clippy --allow-dirty --allow-staged --all-targets --all-features --fix -- -D warnings",
10-
"lint:check": "cargo clippy --all-targets --all-features -- -D warnings"
11-
}
12-
}
1+
{
2+
"name": "osmium-libs-solidity-code-actions",
3+
"license": "GNU-GPL-3.0",
4+
"scripts": {
5+
"build": "cargo build --release --target-dir ./target",
6+
"format": "cargo fmt --all",
7+
"format:check": "cargo fmt --check --all",
8+
"test": "cargo test",
9+
"lint": "cargo clippy --allow-dirty --allow-staged --all-targets --all-features --fix -- -D warnings",
10+
"lint:check": "cargo clippy --all-targets --all-features -- -D warnings"
11+
}
12+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use crate::completions::auto_complete_provider::AutoCompleteProvider;
2+
use crate::error::CodeActionError;
3+
use crate::references::reference_provider::ReferenceProvider;
4+
use crate::types::{CompletionItem, Location, Position};
5+
use osmium_libs_solidity_ast_extractor::extract::extract_ast_from_foundry;
6+
use osmium_libs_solidity_ast_extractor::types::SolidityAstFile;
7+
use std::sync::RwLock;
8+
use std::sync::{Arc, Mutex};
9+
10+
#[derive(Debug)]
11+
pub struct CodeActionsProvider {
12+
pub files: Arc<Mutex<Vec<SolidityAstFile>>>,
13+
pub base_path: RwLock<String>,
14+
}
15+
16+
impl Default for CodeActionsProvider {
17+
fn default() -> Self {
18+
Self::new()
19+
}
20+
}
21+
22+
impl CodeActionsProvider {
23+
pub fn new() -> Self {
24+
Self {
25+
files: Arc::new(Mutex::new(vec![])),
26+
base_path: RwLock::new(String::new()),
27+
}
28+
}
29+
30+
pub fn set_base_path(&self, base_path: String) {
31+
let mut r = self.base_path.write().unwrap();
32+
*r = base_path;
33+
}
34+
35+
pub fn update_file_content(&self) -> Result<(), CodeActionError> {
36+
let new_files = extract_ast_from_foundry(&self.base_path.read().unwrap())?; // will always find the root foundry project
37+
let mut files = self.files.lock().unwrap();
38+
*files = new_files;
39+
Ok(())
40+
}
41+
42+
pub fn get_references(&self, uri: &str, position: Position) -> Vec<Location> {
43+
let files = self.files.lock().unwrap();
44+
let provider = ReferenceProvider::new();
45+
provider.get_references(uri, position, &files)
46+
}
47+
48+
pub fn get_definition(&self, uri: &str, position: Position) -> Option<Location> {
49+
let files = self.files.lock().unwrap();
50+
let provider = ReferenceProvider::new();
51+
provider.get_definition(
52+
uri,
53+
position,
54+
&files,
55+
self.base_path.read().unwrap().as_str(),
56+
)
57+
}
58+
59+
pub fn get_completions(&self, uri: &str, position: Position) -> Vec<CompletionItem> {
60+
let files = self.files.lock().unwrap();
61+
let provider = AutoCompleteProvider::new();
62+
provider.get_suggestions(uri, position, &files)
63+
}
64+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pub mod auto_complete_provider;
2+
mod imports_completion_visitor;
3+
mod inheritence_completion_visitor;
4+
mod position_scope_visitor;
5+
mod spi_completion_provider;
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
use osmium_libs_solidity_ast_extractor::types::SolidityAstFile;
2+
use solc_ast_rs_types::types::{ContractDefinition, ImportDirective};
3+
4+
use crate::{
5+
completions::{
6+
position_scope_visitor::PositionScopeVisitor,
7+
spi_completion_provider::SPICompletionProvider,
8+
},
9+
types::{self, CompletionItem},
10+
Position,
11+
};
12+
13+
use super::{
14+
imports_completion_visitor::ImportCompletionVisitor,
15+
inheritence_completion_visitor::InheritenceCompletionVisitor,
16+
};
17+
18+
pub struct AutoCompleteProvider {}
19+
20+
impl AutoCompleteProvider {
21+
pub fn new() -> Self {
22+
Self {}
23+
}
24+
25+
fn while_inherits(
26+
&self,
27+
contract: &ContractDefinition,
28+
root_file: &SolidityAstFile,
29+
files: &Vec<SolidityAstFile>,
30+
) -> Vec<CompletionItem> {
31+
let mut complete_finder = InheritenceCompletionVisitor::new(contract.clone());
32+
let mut completes: Vec<CompletionItem> = vec![];
33+
let mut inheritences = vec![contract.clone()];
34+
35+
while let Some(current) = inheritences.pop() {
36+
// info!("Current contract to search for inheritence: {:?}", current.name);
37+
for file in files {
38+
let (items, inheritences_res) = complete_finder.find(
39+
&file.ast,
40+
root_file.file.path == file.file.path,
41+
current.clone(),
42+
);
43+
completes.append(&mut items.clone());
44+
inheritences.append(&mut inheritences_res.clone());
45+
}
46+
}
47+
completes
48+
}
49+
50+
fn get_import_completes(
51+
&self,
52+
imports: Vec<ImportDirective>,
53+
files: &Vec<SolidityAstFile>,
54+
) -> Vec<CompletionItem> {
55+
let mut completes: Vec<CompletionItem> = vec![];
56+
let mut imports_to_check: Vec<ImportDirective> = vec![];
57+
for import in imports {
58+
if import.unit_alias.is_empty() && import.symbol_aliases.is_empty() {
59+
imports_to_check.push(import);
60+
} else if import.unit_alias.is_empty() {
61+
for symbol in import.symbol_aliases {
62+
completes.push(CompletionItem {
63+
label: symbol.foreign.name.clone(),
64+
kind: types::CompletionItemKind::MODULE,
65+
});
66+
}
67+
} else {
68+
completes.push(CompletionItem {
69+
label: import.unit_alias.clone(),
70+
kind: types::CompletionItemKind::MODULE,
71+
});
72+
}
73+
}
74+
let mut import_finder = ImportCompletionVisitor::new(imports_to_check.clone());
75+
let files = import_finder.get_files_from_imports(files);
76+
for file in files {
77+
completes.append(&mut import_finder.find(&file.ast));
78+
}
79+
completes
80+
}
81+
82+
pub fn get_suggestions(
83+
&self,
84+
uri: &str,
85+
position: Position,
86+
files: &Vec<SolidityAstFile>,
87+
) -> Vec<CompletionItem> {
88+
if let Some(file) = files.iter().find(|file| file.file.path == uri) {
89+
let mut scope_finder = PositionScopeVisitor::new(file.file.content.clone(), position);
90+
let (contract, spi, imports) = scope_finder.find(&file.ast);
91+
let mut completes: Vec<CompletionItem> = vec![];
92+
93+
if let Some(contract) = contract {
94+
completes.append(&mut self.while_inherits(&contract, file, files));
95+
}
96+
97+
let spi_finder = SPICompletionProvider::new(spi);
98+
completes.append(&mut spi_finder.inspect());
99+
100+
completes.append(&mut self.get_import_completes(imports, files));
101+
102+
return completes;
103+
}
104+
vec![]
105+
}
106+
}

0 commit comments

Comments
 (0)