Skip to content

Commit

Permalink
Merge pull request #40 from PraneshASP/staging
Browse files Browse the repository at this point in the history
Version 1.3.0
  • Loading branch information
PraneshASP authored Feb 12, 2024
2 parents b121e30 + 15e24c6 commit 5563e62
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 7 deletions.
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

# VSCode Solidity Inspector • [![license](https://img.shields.io/badge/MIT-brown.svg?label=license)](https://github.com/PraneshASP/vscode-solidity-inspector/blob/main/LICENSE)

An extension for VSCode editor to inspect the Solidity smartcontracts and generate yul/asm outputs to inspect what's happening under-the-hood. Read 0age's [tweet](https://twitter.com/z0age/status/1578443876615929857), it is the inspiration for this extension.
An extension for VSCode editor that offers multiple utilities to work with the Solidity smart-contracts.

> Note: This extension is not tested across multiple platforms yet.Only the contracts under foundry project are supported for now.
> Note: This extension is not tested across multiple platforms yet. Only the contracts under foundry project are supported for now.
---

## Motivation:

0age 👑 dropped the optimization alpha in his [tweet](https://twitter.com/z0age/status/1578443876615929857) and when I tried it out for the first time I thought it was really a cool trick. The tweet has the configuration only for hardhat projects. But forge helps to do the same thing in a single command. So I thought instead of typing out the command for each contract in the CLI, it would be handy for the buildooors if there's an extension to inspect solidity contracts and generate low-level code for the contracts. The o/p generated is very useful for gas optimizations.
0age 👑 dropped the optimization alpha in his [tweet](https://twitter.com/z0age/status/1578443876615929857) and when I tried it out for the first time I thought it was really a cool trick. The tweet has the configuration only for hardhat projects. But forge helps to do the same thing in a single command. So I thought instead of typing out the command for each contract in the CLI, it would be handy for the buildooors if there's an extension to inspect solidity contracts and generate low-level code for the contracts. The o/p generated is very useful for gas optimizations. Later I started adding more features to this extension.

TL;DR, this is my first VSCode extension, so feel free to provide feedback as I know that there's a plenty of room for improvements, as always^^

Expand All @@ -24,6 +24,7 @@ TL;DR, this is my first VSCode extension, so feel free to provide feedback as I
- Generate and view Foundry deployment report in a clean and concise table format.
- Syntax highlighting of for `.tree` files.
- Generate foundry test stub using [bulloak](https://github.com/alexfertel/bulloak)'s `scaffold` command.
- Auto-complete path suggestions for importing files and dependencies (with forge remappings support).

---

Expand Down Expand Up @@ -69,6 +70,15 @@ https://github.com/PraneshASP/vscode-solidity-inspector/assets/42379522/cfaf987e

https://github.com/PraneshASP/vscode-solidity-inspector/assets/42379522/2a3d591b-bc80-46cc-88c9-7e4faa0bb043

---

#### File import auto-complete suggestions (with forge remappings support):

> [!TIP]
> If you have updated your remappings.txt file, you can press `CMD+CTRL+X` to refresh remappings.
![](./assets/auto-import.gif)


---

Expand Down
Binary file added assets/auto-import.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 12 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "vscode-solidity-inspector",
"displayName": "Solidity Inspector",
"description": "A vscode extension used to inspect Solidity files",
"version": "1.2.1",
"version": "1.3.0",
"engines": {
"vscode": "^1.72.0"
},
Expand All @@ -12,8 +12,9 @@
"keywords": [
"ethereum",
"solidity",
"solidity-inspector",
"forge-inspector"
"blockchain",
"EVM",
"smart-contracts"
],
"publisher": "PraneshASP",
"homepage": "https://github.com/PraneshASP/vscode-solidity-inspector",
Expand Down Expand Up @@ -104,6 +105,14 @@
"title": "Solidity Inspector",
"properties": {}
},
"keybindings": [
{
"command": "vscode-solidity-inspector.resetRemappings",
"key": "ctrl+alt+x",
"mac": "cmd+alt+x",
"when": "editorTextFocus"
}
],
"menus": {
"explorer/context": [
{
Expand Down
15 changes: 15 additions & 0 deletions src/extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
/** imports */
const vscode = require("vscode");


const {
irOptimizerActiveFile,
irOptimizerContextMenu,
Expand Down Expand Up @@ -39,6 +40,9 @@ const { treeFilesCodeActionProvider, treeFilesDiagnosticCollection } = require("

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

const { provideCompletionItems, resetRemappings } = require("./helpers");


/** global vars */
const EXTENSION_PREFIX = "vscode-solidity-inspector";

Expand Down Expand Up @@ -148,11 +152,22 @@ function onActivate(context) {
context.subscriptions.push(scaffoldActiveFileSubscription);
context.subscriptions.push(scaffoldContextMenuSubscription);


// Import suggestions.
context.subscriptions.push(vscode.languages.registerCompletionItemProvider('solidity', { provideCompletionItems }, ['"', "{"]));
context.subscriptions.push(vscode.commands.registerCommand(EXTENSION_PREFIX + '.resetRemappings', () => {
resetRemappings();
vscode.window.showInformationMessage('Remappings have been refreshed!');
}));

vscode.window.visibleTextEditors.map(editor => {
if (editor && editor.document && editor.document.languageId == "solidity") {
unusedImportsActiveFile(editor);
}
});

}


/* exports */
exports.activate = onActivate;
95 changes: 94 additions & 1 deletion src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,99 @@ function newWindowBeside(content) {
vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)
);
}

let remappings = null; // Cache remappings globally

async function loadRemappings(rootPath) {
const remappingsPath = path.join(rootPath, 'remappings.txt');
try {
const remappingsContent = await vscode.workspace.fs.readFile(vscode.Uri.file(remappingsPath));
return remappingsContent.toString().split('\n').reduce((acc, line) => {
const [key, val] = line.split('=');
if (key && val) {
acc[key.trim()] = val.trim();
}
return acc;
}, {});
} catch (error) {
console.error('Error reading remappings:', error);
return {};
}
}


async function provideCompletionItems(document, position) {
const linePrefix = document.lineAt(position).text.substring(0, position.character);
if (!linePrefix.startsWith('import')) {
return undefined;
}

// Step 1: Read and parse remappings
const workspaceFolders = vscode.workspace.workspaceFolders;
if (!workspaceFolders) return undefined; // No workspace folder open

const rootPath = workspaceFolders[0].uri.fsPath;

if (remappings === null) { // Load remappings if not already loaded
remappings = await loadRemappings(rootPath);
}

// Step 2: Apply remappings to import paths
const solidityFiles = await findSolidityFiles();
const currentFilePath = document.uri.fsPath;
const currentDir = path.dirname(currentFilePath);


const completionItems = solidityFiles.map(file => {
let filePath = vscode.workspace.asRelativePath(file, false);
let remappedPath = filePath; // Start with the original path

// Apply remappings
Object.entries(remappings).forEach(([key, value]) => {
if (filePath.startsWith(value)) {
// Replace the matching part of the path with the remapping key
remappedPath = filePath.replace(value, key);
}
});



// Determine if the path was remapped
const isRemapped = remappedPath !== filePath;

// Use the remapped path if available, otherwise use the relative path
const finalPath = isRemapped ? remappedPath : `./${path.relative(currentDir, file).split(path.sep).join('/')}`;

const contractName = path.basename(file, '.sol');
const completionItem = new vscode.CompletionItem(`${contractName} from "${finalPath}"`, vscode.CompletionItemKind.File);

// Format the insert text based on whether the path was remapped
completionItem.insertText = `{${contractName}} from "${finalPath}";`;

return completionItem;
});
return completionItems;
}

function findSolidityFiles() {
// Define the glob pattern for Solidity files
const solidityFilePattern = '**/*.sol';
// Exclude files from the node_modules and out dirs
const excludePattern = '{**/node_modules/**,**/out/**,**/test}';

// Use findFiles to search for files matching the Solidity pattern, excluding undesired paths
return vscode.workspace.findFiles(solidityFilePattern, excludePattern)
.then(files => files.map(file => file.fsPath)); // Convert URIs to file system paths

}

function resetRemappings() {
remappings = null;
}




const networkMap = {
"1": "Ethereum",
"8": "Ubiq",
Expand Down Expand Up @@ -121,4 +214,4 @@ const networkMap = {



module.exports = { newWindowBeside, getContractRootDir, LANGID, networkMap };
module.exports = { newWindowBeside, getContractRootDir, LANGID, networkMap, provideCompletionItems, resetRemappings };

0 comments on commit 5563e62

Please sign in to comment.