Skip to content

Commit 504d3ad

Browse files
committed
wip: show floating suggestions
1 parent 500c751 commit 504d3ad

File tree

4 files changed

+147
-99
lines changed

4 files changed

+147
-99
lines changed

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"onLanguage:solidity",
3131
"onLanguage:json",
3232
"onLanguage:tree"
33-
],
33+
],
3434
"contributes": {
3535
"commands": [
3636
{
@@ -104,13 +104,13 @@
104104
"title": "Solidity Inspector",
105105
"properties": {}
106106
},
107-
"keybindings":[
107+
"keybindings": [
108108
{
109109
"command": "vscode-solidity-inspector.pathIntel",
110110
"key": "ctrl+alt+x",
111111
"mac": "cmd+alt+x",
112112
"when": "editorTextFocus"
113-
}
113+
}
114114
],
115115
"menus": {
116116
"explorer/context": [

src/commands/path-intel.js

Lines changed: 0 additions & 92 deletions
This file was deleted.

src/extension.js

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
/** imports */
88
const vscode = require("vscode");
9+
const path = require("path");
10+
const fs = require("fs");
911

1012
const {
1113
irOptimizerActiveFile,
@@ -39,7 +41,7 @@ const { treeFilesCodeActionProvider, treeFilesDiagnosticCollection } = require("
3941

4042
const { scaffoldActiveFile, scaffoldContextMenu } = require("./commands/bulloak-scaffold");
4143

42-
const { pathIntel } = require("./commands/path-intel");
44+
const { findSolidityFiles } = require("./helpers");
4345

4446

4547
/** global vars */
@@ -151,14 +153,78 @@ function onActivate(context) {
151153
context.subscriptions.push(scaffoldActiveFileSubscription);
152154
context.subscriptions.push(scaffoldContextMenuSubscription);
153155

154-
pathIntel(context);
156+
157+
158+
async function provideCompletionItems(document, position) {
159+
const linePrefix = document.lineAt(position).text.substring(0, position.character);
160+
if (!linePrefix.startsWith('import')) {
161+
return undefined;
162+
}
163+
164+
// Step 1: Read and parse remappings
165+
const workspaceFolders = vscode.workspace.workspaceFolders;
166+
if (!workspaceFolders) return undefined; // No workspace folder open
167+
168+
const rootPath = workspaceFolders[0].uri.fsPath;
169+
const remappingsPath = path.join(rootPath, 'remappings.txt');
170+
let remappings = {};
171+
172+
if (fs.existsSync(remappingsPath)) {
173+
const remappingsContent = fs.readFileSync(remappingsPath, 'utf8');
174+
remappingsContent.split('\n').forEach(line => {
175+
const [key, val] = line.split('=');
176+
remappings[key.trim()] = val.trim();
177+
});
178+
}
179+
180+
// Step 2: Apply remappings to import paths
181+
const solidityFiles = await findSolidityFiles();
182+
const currentFilePath = document.uri.fsPath;
183+
const currentDir = path.dirname(currentFilePath);
184+
185+
186+
const completionItems = solidityFiles.map(file => {
187+
let filePath = vscode.workspace.asRelativePath(file, false);
188+
let remappedPath = filePath; // Start with the original path
189+
190+
// Apply remappings
191+
Object.entries(remappings).forEach(([key, value]) => {
192+
if (filePath.startsWith(value)) {
193+
// Replace the matching part of the path with the remapping key
194+
remappedPath = filePath.replace(value, key);
195+
}
196+
});
197+
198+
// Determine if the path was remapped
199+
const isRemapped = remappedPath !== filePath;
200+
201+
// Use the remapped path if available, otherwise use the relative path
202+
const finalPath = isRemapped ? remappedPath : `./${path.relative(currentDir, file).split(path.sep).join('/')}`;
203+
204+
const contractName = path.basename(file, '.sol');
205+
const completionItem = new vscode.CompletionItem(`${contractName} from "${finalPath}"`, vscode.CompletionItemKind.File);
206+
207+
// Format the insert text based on whether the path was remapped
208+
completionItem.insertText = `{${contractName}} from "${finalPath}";`;
209+
210+
return completionItem;
211+
});
212+
213+
214+
return completionItems;
215+
}
216+
217+
context.subscriptions.push(vscode.languages.registerCompletionItemProvider('solidity', { provideCompletionItems }, ['"', "{"]));
218+
155219

156220
vscode.window.visibleTextEditors.map(editor => {
157221
if (editor && editor.document && editor.document.languageId == "solidity") {
158222
unusedImportsActiveFile(editor);
159223
}
160224
});
161-
225+
162226
}
227+
228+
163229
/* exports */
164230
exports.activate = onActivate;

src/helpers.js

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,80 @@ function newWindowBeside(content) {
2323
vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)
2424
);
2525
}
26+
27+
28+
async function provideImportSuggestions(document, position) {
29+
const linePrefix = document.lineAt(position).text.substring(0, position.character);
30+
console.log("lineprefix", linePrefix);
31+
if (!linePrefix.startsWith('import')) {
32+
return undefined;
33+
}
34+
35+
// Step 1: Read and parse remappings
36+
const workspaceFolders = vscode.workspace.workspaceFolders;
37+
if (!workspaceFolders) return undefined; // No workspace folder open
38+
39+
const rootPath = workspaceFolders[0].uri.fsPath;
40+
const remappingsPath = path.join(rootPath, 'remappings.txt');
41+
let remappings = {};
42+
43+
if (fs.existsSync(remappingsPath)) {
44+
const remappingsContent = fs.readFileSync(remappingsPath, 'utf8');
45+
remappingsContent.split('\n').forEach(line => {
46+
const [key, val] = line.split('=');
47+
remappings[key.trim()] = val.trim();
48+
});
49+
}
50+
51+
// Step 2: Apply remappings to import paths
52+
const solidityFiles = await findSolidityFiles();
53+
const currentFilePath = document.uri.fsPath;
54+
const currentDir = path.dirname(currentFilePath);
55+
56+
57+
const completionItems = solidityFiles.map(file => {
58+
let filePath = vscode.workspace.asRelativePath(file, false);
59+
let remappedPath = filePath; // Start with the original path
60+
61+
// Apply remappings
62+
Object.entries(remappings).forEach(([key, value]) => {
63+
if (filePath.startsWith(value)) {
64+
// Replace the matching part of the path with the remapping key
65+
remappedPath = filePath.replace(value, key);
66+
}
67+
});
68+
69+
// Determine if the path was remapped
70+
const isRemapped = remappedPath !== filePath;
71+
72+
// Use the remapped path if available, otherwise use the relative path
73+
const finalPath = isRemapped ? remappedPath : `./${path.relative(currentDir, file).split(path.sep).join('/')}`;
74+
75+
const contractName = path.basename(file, '.sol');
76+
const completionItem = new vscode.CompletionItem(`${contractName} from "${finalPath}"`, vscode.CompletionItemKind.File);
77+
78+
// Format the insert text based on whether the path was remapped
79+
completionItem.insertText = `{${contractName}} from "${finalPath}";`;
80+
81+
return completionItem;
82+
});
83+
84+
85+
return completionItems;
86+
}
87+
88+
function findSolidityFiles() {
89+
// Define the glob pattern for Solidity files
90+
const solidityFilePattern = '**/*.sol';
91+
// Exclude files from the node_modules folder
92+
const excludePattern = '**/node_modules/**';
93+
94+
// Use findFiles to search for files matching the Solidity pattern, excluding undesired paths
95+
return vscode.workspace.findFiles(solidityFilePattern, excludePattern)
96+
.then(files => files.map(file => file.fsPath)); // Convert URIs to file system paths
97+
98+
}
99+
26100
const networkMap = {
27101
"1": "Ethereum",
28102
"8": "Ubiq",
@@ -121,4 +195,4 @@ const networkMap = {
121195

122196

123197

124-
module.exports = { newWindowBeside, getContractRootDir, LANGID, networkMap };
198+
module.exports = { newWindowBeside, getContractRootDir, LANGID, networkMap, provideImportSuggestions, findSolidityFiles };

0 commit comments

Comments
 (0)