diff --git a/.vscode/launch.json b/.vscode/launch.json index bd7615f..63ab3d4 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,20 +1,15 @@ { - "version": "0.2.0", - "configurations": [ - { - "name": "Launch Extension", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceRoot}" - ], - "stopOnEntry": false, - "sourceMaps": true, - "outFiles": [ - "${workspaceRoot}/out/**/*.js" - ], - "preLaunchTask": "npm: install" - } - ] + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Extension", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": ["--extensionDevelopmentPath=${workspaceRoot}"], + "sourceMaps": true, + "outFiles": ["${workspaceRoot}/out/**/*.js"], + "preLaunchTask": "npm: install" + } + ] } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index b63ad74..21fdc09 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,12 +1,12 @@ { - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "label": "npm: install", - "type": "shell", - "command": "npm install" - } - ] -} \ No newline at end of file + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "npm: install", + "type": "shell", + "command": "npm install" + } + ] +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 78725f1..7959e93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,30 @@ Note: Don't forget to check out `preferences → Settings → Solidity Visual Developer` to customize features, look and feel. +## v0.2.0 - 🍂🍁🍃 Booh! 👻🎃🎃🎃🌾👨🏼‍🌾 + +- fix: includes parser performance optimizations with [solidity-workspace@v0.2.1](https://github.com/tintinweb/solidity-workspace/releases/tag/v0.2.1) (🙏 @vquelque) +- update: completely refactored function signature computation - #127 +- fix: performance optimizations - #127 +- new: command `solidity-va.tools.function.signatures.forWorkspace` to show all function signatures for files in the workspace - #127 +- fix: `ftrace` error in cockpit view due to non-existent filepath being passed to surya - #127 +- fix: draw.io/plantuml mistakenly named `receive()|fallback()` as `constructor` - #127 +- fix: function signature extraction only returns `public|external` interfaces - #127 +- fix: external function call list in cockpit view faile to resolve one-liner function declarations - #127 +- fix: inheritance hover showing "object" instead of inherited contract name +- update: dependencies (solidity parser / solidity workspace) +- fix: constructor/fallback showing up as 'null' in cockpit +- fix: redecorate editor only if changes were detected (performance) +- fix: abort decoration if content hash not found in cache (keep current decoration if file is unparseable) +- fix: cockpit view for overridden functions (#138) +- fix: debounce onDidChange events (performance while typing) ## v0.1.5 - 🏂 + - fix: find all references not working - #119 ## v0.1.4 - 🍁 + - fix: incompatibility with vscode update v1.72.0 - Extension "[...] has provided an invalid tree item." - #114 - new: optionally disable highlighting in the overview ruler - #115 @@ -15,50 +34,51 @@ Note: Don't forget to check out `preferences → Settings → Solidity Visual De image image - fix: more consistent highlighting when clicking on an item in the cockpit ExternalCalls/PublicStatechanging views - #110 + - clicking on a function name highlights the first line of the function instead of the full function block in the editor - clicking on an external call/modifier highlights the invocation in the editor - fix: semantic highlighting for supercall and modifier arguments - #112 #117 ## v0.1.3 - 🧸 + - new: customize semantic highlighting mode #105 #108 - `color and symbol` - default (decorate + "arrow") - - `color only` - only decorate identifiers declared in the function argument scope + - `color only` - only decorate identifiers declared in the function argument scope - `symbol only` - only show an "arrow" next to an identifier declared in the function argument scope image -- fix: uml - fix null-deref when parsing 'using-for *' #106 #107 +- fix: uml - fix null-deref when parsing 'using-for \*' #106 #107 - update: configurable trailing "arrow" for semantic function argument highlighting #104 #100 - ## v0.1.2 - new: decorate/highlight immutable state vars (![#9932cc](https://via.placeholder.com/15/9932cc/000000?text=+)) - #97 (thanks @RomiRand) -image + image - update: dependencies (surya@0.4.6) - new: configuration option to enable the `surya.mdreport` "negative Modifiers" feature, see [surya#162](https://github.com/ConsenSys/surya/pull/162) - - enabling `solidity-va.tools.surya.option.negModifiers` will list all modifiers observed in the file with the ones that are not being used with the listed method being ~~striked-through~~ + - enabling `solidity-va.tools.surya.option.negModifiers` will list all modifiers observed in the file with the ones that are not being used with the listed method being ~~striked-through~~ ![image](https://user-images.githubusercontent.com/2998191/155733325-7a6187b8-e63e-4410-a312-aa2a1c940e31.png) - Note that the report can be generated either via the `report` codelense or by selecting files in the `Solidity Visual Developer View → right-click → Surya: generate report`. +Note that the report can be generated either via the `report` codelense or by selecting files in the `Solidity Visual Developer View → right-click → Surya: generate report`. image image - - fix: typos & links to placeholder[.]com - #93 #91 (thanks @almndbtr) ## v0.1.1 - ❄️🎄🏂🎄❄️ - fix: type resolving and declaration link for inherited statevars - update: move language specific logic to a web compatible extension + - https://github.com/tintinweb/vscode-solidity-language (https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-solidity-language) - - The language ships with three security centered Color Themes that can be selected from the **Solidity Language & Themes (only)** extension page or `Code → Preferences → Color Themes` - + - The language ships with three security centered Color Themes that can be selected from the **Solidity Language & Themes (only)** extension page or `Code → Preferences → Color Themes` + ![image](https://user-images.githubusercontent.com/2865694/145625639-a54178d1-5cee-45b6-bf10-44da09875f0e.png) - update: support for latest solidity parser (extension + surya) #84 @@ -73,7 +93,7 @@ Note: Don't forget to check out `preferences → Settings → Solidity Visual De ![image](https://user-images.githubusercontent.com/2865694/122222447-90933880-ceb2-11eb-91c3-c59549d40c8c.png) - new: we can now resolve inherited names (hover: declaration link) - + ![image](https://user-images.githubusercontent.com/2865694/120014274-26d5ec00-bfe2-11eb-99f7-64d4a57277a0.png) - new: we now decorate identifiers that are storage references (treating them like state-vars) @@ -88,7 +108,6 @@ Note: Don't forget to check out `preferences → Settings → Solidity Visual De - fix: function selector is incorrect if there's a comment in the function signature definition #68 - update: code cleanup; refactored decoration logic and moved it to its own submodule - ## v0.0.32 - v0.0.33 Maintenance release until v0.1.0 is ready. @@ -102,7 +121,7 @@ Maintenance release until v0.1.0 is ready. Happy new year 👪🌃🥂🎇! -- new: allow to disable the "find references" provider +- new: allow to disable the "find references" provider - `preferences → Settings → Solidity Visual Developer: solidity-va.findAllReferences.enable` - in case another extension implements a better provider someday :) - new: experimental draw.io uml export to support your threat modelling needs (you're going to ❤ this!) @@ -120,19 +139,21 @@ Happy new year 👪🌃🥂🎇! - keccak ## v0.0.30 + - new: We've finally implemented support for `Right Click → Find All References` for solidity source files! - Please note that this currently performs a lexical search of all source-code files containing the word under the cursor (including comments). This may be subject to change to return more specific results in the future. -
image - +
image - update: dependencies surya / solidity parser - ## v0.0.29 + - sort top level contracts list by filename - fix: VSCode-Error: Proposed API is only available when running out of dev or with the following command line switch... #59 ## v0.0.28 + - new: integration with [tintinweb.vscode-ethover](https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-ethover) + - ethereum address hover - open address in etherscan, fetch bytecode, verified contract - disassemble or decompile bytecode @@ -140,57 +161,66 @@ Happy new year 👪🌃🥂🎇! - customizations/ApiKey: see settings image + - update: `surya` to `0.4.1-dev.2` ## v0.0.27 + - rebirth: `Solidity Visual Auditor` is now `Solidity Visual Developer` 🎉 - new: Ethereum Address hover commands. Hover over an ethereum account address to: - - `open` the account on etherscan.io + - `open` the account on etherscan.io - show the contract `code` - show the `VerifiedContract` source code - `decompile` the byte-code. requires [vscode-decompiler](https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-decompiler)
image ## v0.0.26 + - new: support for solidity `0.6.x` via #53 - new: `cockpit → Workspace: Explorer → Surya: Contract interaction graph` aka `surya.graphSimple` #49
- image
- image + image
+ image - updated: surya to 0.4.0 #49 - updated: `solidity-parser-diligence` to community maintained `@solidity-parser/parser` #53 ## v0.0.25 + - updated: breaking interface with `vscode-interactive-graphviz@v0.0.8`: the render command was renamed from `interactive-graphviz.preview.beside` to `graphviz-interactive-preview.preview.beside` ## v0.0.24 + - new: Solidity Visual Auditor Cockpit panel additions - - Context: show function call trace when clicking into a contract method in the editor - - Flatfiles: List flat files produced by the extension (matches: `**/flat_*.sol`) + - Context: show function call trace when clicking into a contract method in the editor + - Flatfiles: List flat files produced by the extension (matches: `**/flat_*.sol`) - updated: surya (fixed multiple issues when parsing certain smart contracts with `usingFor` statements) - + ## v0.0.23 + - new: Update notifications have arrived! - updated: solidity parser and surya - new: 🔥 Solidity Visual Auditor Cockpit panel - - Workspace Explorer - - Quick-access to extension settings - - Find Top Level Contracts - - Keep track of flattened files - - List public state-changing methods from the current contract - - Show the function call trace for the current method + - Workspace Explorer + - Quick-access to extension settings + - Find Top Level Contracts + - Keep track of flattened files + - List public state-changing methods from the current contract + - Show the function call trace for the current method ## v0.0.22 + - update: solidity parser, surya (#41 [#42](https://github.com/tintinweb/vscode-solidity-auditor/issues/42)) - fix: linter warnings (#40) - fix: configuration changes now take effect immediately (#43) ## v0.0.21 + - fix: Support VSCode for Windows (#38, [#35](https://github.com/tintinweb/vscode-solidity-auditor/issues/35)) - fix: UML arrows (#34) - code cleanup (#39) - allow extension to run on unsaved files/editors (some functionality will not work on unsaved files, e.g. `surya` calls) ## v0.0.20 + - new: released `@audit-tags` as a general purpose extension named [Inline Bookmarks](https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-inline-bookmarks). - obsoletes: `Solidity-va.audit.tags.enable` ... enable/disable audit tags - split up extension dependencies in hard and soft requirements @@ -202,6 +232,7 @@ Happy new year 👪🌃🥂🎇! - (required) [Interactive Graphviz](https://marketplace.visualstudio.com/items?itemName=tintinweb.graphviz-interactive-preview) ## v0.0.19 + - new: constant values that are not symbols are now shown in hover message Screenshot 2019-11-12 at 15 41 48 @@ -210,28 +241,31 @@ Happy new year 👪🌃🥂🎇! - fix: function signature output shows 🔥 even though there are no collisions ## v0.0.18 + - new: UML diagrams just arrived 🎉! auto-generate uml for source-units or contracts. sva_light_vscode - new: codelense next to functions to generate sighash. -- fix: function signature hashes are now generated for all functions (even internal ones, just ignore them for now :)). Canonicalization of types before calculating hashes [#27](https://github.com/tintinweb/vscode-solidity-auditor/issues/27). +- fix: function signature hashes are now generated for all functions (even internal ones, just ignore them for now :)). Canonicalization of types before calculating hashes [#27](https://github.com/tintinweb/vscode-solidity-auditor/issues/27). - new: alert on function sighash collision within the same contract. -sva_light_vscode +sva_light_vscode -- new: AST parser now keeps track of `usingFor`'s +- new: AST parser now keeps track of `usingFor`'s ## v0.0.17 + - new: audit-tags: new `@audit-issue` and `@audit-info` to add informational notes or references to files issues (#23) - update: contract flattener changed from `flaterra` to `truffle-flattener` ([vscode-solidity-flattener](https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-solidity-flattener)) -- new: theme - Solidity Visual auditor light - the vscode standard light theme with visual auditor highlighting (#25) +- new: theme - Solidity Visual auditor light - the vscode standard light theme with visual auditor highlighting (#25) sva_light_vscode theme_light_vs - update: updated theme `solarized-light`, split up color-scheme definitions into multiple files. Changed 'light-theme' natspec color highlighting to be less dramatic (black->greyish). (#24) ## v0.0.16 + - fix: enable graph rendering by default - fix: codelenses are sometimes missing (graph) @@ -243,38 +277,41 @@ Happy new year 👪🌃🥂🎇! - ![vscode-solidity-auditor-interactive-graph](https://user-images.githubusercontent.com/2865694/57710279-e27e8a00-766c-11e9-9ca9-8cde50aa31fc.gif) ## v0.0.14 - aka big surya wedding + - feature: 💒🤵👰 [vscode-solidity-auditor](https://github.com/tintinweb/vscode-solidity-auditor) ⚭ [surya](https://github.com/ConsenSys/surya) by [Gonçalo Sá](https://github.com/gnsps) - feature: codelens (inline code actions) + - file - surya - graph - ![vscode-auditor-surya-graph](https://user-images.githubusercontent.com/2865694/55647206-65decd00-57dd-11e9-856a-1cceed31d18e.gif) + ![vscode-auditor-surya-graph](https://user-images.githubusercontent.com/2865694/55647206-65decd00-57dd-11e9-856a-1cceed31d18e.gif) - surya - generate report - surya - inheritance - - surya - parse file (show AST) - ![vscode-auditor-surya-report](https://user-images.githubusercontent.com/2865694/55647025-e5b86780-57dc-11e9-9cc0-b5197eb075b8.gif) - - flatten sourceUnit using [flaterra](https://github.com/cleanunicorn/flaterra) + - surya - parse file (show AST) + ![vscode-auditor-surya-report](https://user-images.githubusercontent.com/2865694/55647025-e5b86780-57dc-11e9-9cc0-b5197eb075b8.gif) + - flatten sourceUnit using [flaterra](https://github.com/cleanunicorn/flaterra) - contracts + - create unittest stub for contract (e.g. for verifying vulnerabilities) - ![vscode-auditor-unittest](https://user-images.githubusercontent.com/2865694/55646826-72aef100-57dc-11e9-800b-fc649b41b4a9.gif) + ![vscode-auditor-unittest](https://user-images.githubusercontent.com/2865694/55646826-72aef100-57dc-11e9-800b-fc649b41b4a9.gif) + + - surya - dependencies - - surya - dependencies - functions - surya - ftrace - ![vscode-auditor-ftrace](https://user-images.githubusercontent.com/2865694/55646883-983bfa80-57dc-11e9-8e40-6194d1429dac.gif) + ![vscode-auditor-ftrace](https://user-images.githubusercontent.com/2865694/55646883-983bfa80-57dc-11e9-8e40-6194d1429dac.gif) + - feature: command - suggest top level contracts aka "entrypoint contracts" (most derived) - feature: command - flatten current (codelens) or all suggested top level contracts (command) -![vscode-auditor-flaterra](https://user-images.githubusercontent.com/2865694/55907553-5db8d000-5bd7-11e9-8a11-8cef3964e284.gif) + ![vscode-auditor-flaterra](https://user-images.githubusercontent.com/2865694/55907553-5db8d000-5bd7-11e9-8a11-8cef3964e284.gif) - feature: command - list all function signatures (human readable or json format) -![vscode-auditor-funcsigs](https://user-images.githubusercontent.com/2865694/55907153-3f9ea000-5bd6-11e9-8a47-e69a762963e9.gif) + ![vscode-auditor-funcsigs](https://user-images.githubusercontent.com/2865694/55907153-3f9ea000-5bd6-11e9-8a47-e69a762963e9.gif) - feature: command - open remix in external browser - - Note: to enable graphviz dot previews install one of the following vscode extensions: [graphviz-preview](https://marketplace.visualstudio.com/items?itemName=EFanZh.graphviz-preview) or [vscode-graphviz](https://marketplace.visualstudio.com/items?itemName=joaompinto.vscode-graphviz) - Note: to enable markdown previews install the following extension [markdown-preview-enhanced](https://marketplace.visualstudio.com/items?itemName=shd101wyy.markdown-preview-enhanced) - outline - added assembly functions assembly - ## v0.0.13 - feature: vscode.command to generate a unittest stub for the current contract (`cmd`+`shift`+`p` -> `Solidity Visual Auditor: create Unittest stub for current Contract`) @@ -300,6 +337,7 @@ Happy new year 👪🌃🥂🎇! - async functions ## v0.0.12 + - refactored folder structure - bug: check if source-file is actually a solidity file on-change - feature: semantic function argument highlighting diff --git a/README.md b/README.md index fe07092..32905bb 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,30 @@ [get in touch with Consensys Diligence](https://diligence.consensys.net)
-[[ 🌐 ](https://diligence.consensys.net) [ 📩 ](mailto:diligence@consensys.net) [ 🔥 ](https://consensys.github.io/diligence/)] +[[ 🌐 ](https://diligence.consensys.net) [ 📩 ](mailto:diligence@consensys.net) [ 🔥 ](https://consensys.github.io/diligence/)]

- # Solidity Visual Developer -* Advanced Solidity Language Support -* Code Augmentation -* Source Exploration -* Visual Security Linting +- Advanced Solidity Language Support +- Code Augmentation +- Source Exploration +- Visual Security Linting > An extension that supports developers in writing secure and well understood code This extension contributes **security centric** syntax and semantic highlighting, a detailed class outline, specialized views, advanced Solidity code insights and augmentation to Visual Studio Code. -____ +--- **⚠️ Note**: Customize this extension to fit your needs! Show/Hide/Enable/Disable features in `Preference → Settings → Solidity Visual Developer: solidity-va.*`, select one of the customized security-aware color themes in `Preferences → Color Themes`. - We ❤ feedback → [get in touch!](https://github.com/tintinweb/vscode-solidity-auditor/issues) -____ - +--- [Marketplace](https://marketplace.visualstudio.com/items?itemName=tintinweb.solidity-visual-auditor): `ext tintinweb.solidity-visual-auditor` -____ +--- theme_light_vs @@ -37,7 +34,7 @@ ____ vscode-solidity-auditor-uml ---------------------- +--- ## Features @@ -49,104 +46,102 @@ Semantic highlighting and solidity insights for passive security awareness. Most ![light_small](https://user-images.githubusercontent.com/2865694/61187967-d452e700-a678-11e9-8661-7cd7839f88a6.png) ![solarized_small](https://user-images.githubusercontent.com/2865694/61187948-850cb680-a678-11e9-8b16-9616dfc09046.png) -* Visual Auditor Dark - based on the "Atom One" theme -* Visual Auditor Light (Visual Studio) - based on the standard "light (VSCode)" theme -* Visual Auditor Solarized Light - based on the standard "Solarized Light" theme +- Visual Auditor Dark - based on the "Atom One" theme +- Visual Auditor Light (Visual Studio) - based on the standard "light (VSCode)" theme +- Visual Auditor Solarized Light - based on the standard "Solarized Light" theme ##### Syntax Highlighting -* **access modifiers** (`external`, `public`, `payable`, ...) -* security relevant built-ins, globals, methods and user/miner-tainted information (`address.call()`, `tx.origin`, `msg.data`, `block.*`, `now`) -* storage access modifiers (`memory`, `storage`) -* developer notes in comments (`TODO`, `FIXME`, `HACK`, ...) -* custom function modifiers -* contract creation / event invocations -* easily differentiate between arithmetics vs. logical operations -* make **Constructor** and **Fallback** function more prominent +- **access modifiers** (`external`, `public`, `payable`, ...) +- security relevant built-ins, globals, methods and user/miner-tainted information (`address.call()`, `tx.origin`, `msg.data`, `block.*`, `now`) +- storage access modifiers (`memory`, `storage`) +- developer notes in comments (`TODO`, `FIXME`, `HACK`, ...) +- custom function modifiers +- contract creation / event invocations +- easily differentiate between arithmetics vs. logical operations +- make **Constructor** and **Fallback** function more prominent -Code fragments passively draw your attention to statements that typically *reduce risk* ![#c5f015](https://via.placeholder.com/15/ccff00/000000?text=+) or *need your attention* ![#f03c15](https://via.placeholder.com/15/f03c15/000000?text=+). +Code fragments passively draw your attention to statements that typically _reduce risk_ ![#c5f015](https://via.placeholder.com/15/ccff00/000000?text=+) or _need your attention_ ![#f03c15](https://via.placeholder.com/15/f03c15/000000?text=+). ##### Semantic Highlighting -* highlights **StateVars** (constant, inherited) -* detects and alerts about StateVar shadowing -* highlights **function arguments** in the function body - +- highlights **StateVars** (constant, inherited) +- detects and alerts about StateVar shadowing +- highlights **function arguments** in the function body ##### Review Features -* audit annotations/bookmarks - `@audit - ` `@audit-ok - ` (see below) -* generic interface for importing external scanner results - cdili json format (see below) -* codelens inline action: graph, report, dependencies, inheritance, parse, ftrace, flatten, generate unittest stub, function signature hashes, uml +- audit annotations/bookmarks - `@audit - ` `@audit-ok - ` (see below) +- generic interface for importing external scanner results - cdili json format (see below) +- codelens inline action: graph, report, dependencies, inheritance, parse, ftrace, flatten, generate unittest stub, function signature hashes, uml ##### Graph- and Reporting Features -* 💒🤵👰 [vscode-solidity-auditor](https://github.com/tintinweb/vscode-solidity-auditor) ⚭ [Sūrya](https://github.com/ConsenSys/surya) - * access your favorite Sūrya features from within vscode! - * interactive call graphs with call flow highlighting and more! -* 📈🎉 auto-generate UML diagrams from code to support your threat modelling exercises or documentation! +- 💒🤵👰 [vscode-solidity-auditor](https://github.com/tintinweb/vscode-solidity-auditor) ⚭ [Sūrya](https://github.com/ConsenSys/surya) + - access your favorite Sūrya features from within vscode! + - interactive call graphs with call flow highlighting and more! +- 📈🎉 auto-generate UML diagrams from code to support your threat modelling exercises or documentation! ##### Code Augmentation -* Hover over Ethereum Account addresses to download the byte-code, source-code or open it in the browser -* Hover over ASM instructions to show their signatures -* Hover over keywords to show basic Security Notes -* Hover over StateVar's to show declaration information -##### Views +- Hover over Ethereum Account addresses to download the byte-code, source-code or open it in the browser +- Hover over ASM instructions to show their signatures +- Hover over keywords to show basic Security Notes +- Hover over StateVar's to show declaration information -* Cockpit View - * Explore and focus on solidity files in your workspace - * Generate report/graphs for any files/folders selected in the explorer views - * Selectively flatten files - * Search for contracts that are likely to be deployed in the system - * Context-sensitive views: click into a contract in the editor to list public state-changing method - * Get quick access to extension settings -* Outline View - * populates VS Code outline view with sourceUnit and contract layout - * contracts, stateVars, methods, inherited names - * annotates security relevant information (visibility, ...) - * calculates complexity rating - * annotations functions with information about whether they are accessing stateVars +##### Views +- Cockpit View + - Explore and focus on solidity files in your workspace + - Generate report/graphs for any files/folders selected in the explorer views + - Selectively flatten files + - Search for contracts that are likely to be deployed in the system + - Context-sensitive views: click into a contract in the editor to list public state-changing method + - Get quick access to extension settings +- Outline View + - populates VS Code outline view with sourceUnit and contract layout + - contracts, stateVars, methods, inherited names + - annotates security relevant information (visibility, ...) + - calculates complexity rating + - annotations functions with information about whether they are accessing stateVars # Installation +**Method 1:** Install by going to [Visual Studio Market Place](https://marketplace.visualstudio.com/items?itemName=tintinweb.solidity-visual-auditor#overview) and click `Install`. -**Method 1:** Install by going to [Visual Studio Market Place](https://marketplace.visualstudio.com/items?itemName=tintinweb.solidity-visual-auditor#overview) and click `Install`. +**Method 2:** Bring up the Extension view in VS Code and search for `Solidity Visual Developer` and click `Install` -**Method 2:** Bring up the Extension view in VS Code and search for `Solidity Visual Developer` and click `Install` +**Method 3 (Manual)**: -**Method 3 (Manual)**: -1. Download the [latest compiled extension as *.vsix](https://github.com/tintinweb/vscode-solidity-auditor/releases) +1. Download the [latest compiled extension as \*.vsix](https://github.com/tintinweb/vscode-solidity-auditor/releases) 2. Fire up Terminal and install the extension by running `code --install-extension "solidity-visual-auditor-0.0.x.vsix"` 3. vscode --> preferences --> color scheme --> **Solidity Visual Developer Dark** - # Tour Scroll down and take the tour. ![visual_auditor_new](https://user-images.githubusercontent.com/2865694/55153942-f9682c00-5153-11e9-9e88-b3958c134c88.png) -* semantic highlighting for state variables (constant=green, statevar=golden, inherited=blue) -* semantic highlighting for function arguments -* outline view with security annotations and inherited names -* tooltips (asm instruction signatures, security notes) -* `@audit` tags -* graph's and uml -* generic interface to import issues from external scanners -* Cockpit View +- semantic highlighting for state variables (constant=green, statevar=golden, inherited=blue) +- semantic highlighting for function arguments +- outline view with security annotations and inherited names +- tooltips (asm instruction signatures, security notes) +- `@audit` tags +- graph's and uml +- generic interface to import issues from external scanners +- Cockpit View
Feature: Ethereum Account Address Actions ## Ethereum Account Address Actions -- `open` the account on etherscan.io +- `open` the account on etherscan.io - show the contract `code` - show the `VerifiedContract` source code - `decompile` the byte-code. requires [vscode-decompiler](https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-decompiler) - + image
@@ -156,7 +151,7 @@ Scroll down and take the tour. ## Semantic function argument highlighting -* arguments are assigned different colors in the scope of the function +- arguments are assigned different colors in the scope of the function semantic-arg-dark semantic-arg-light @@ -170,8 +165,8 @@ Scroll down and take the tour. This feature is provided by [Inline Bookmarks](https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-inline-bookmarks). -* `@audit - ` ... flag lines for security review or start a security review discussion -* `@audit-ok - ` ... flag that a line was checked for security or a security discussion on that line turned out to be a non-issue +- `@audit - ` ... flag lines for security review or start a security review discussion +- `@audit-ok - ` ... flag that a line was checked for security or a security discussion on that line turned out to be a non-issue audit-tags @@ -182,87 +177,84 @@ This feature is provided by [Inline Bookmarks](https://marketplace.visualstudio. ## Code Augmentation / Annotations / Hover / Tooltip -* additional information for various keywords (including security notes) +- additional information for various keywords (including security notes) code_token_hover -* asm instruction signatures +- asm instruction signatures code_asm_tooltip -* Address hover integration via [tintinweb.vscode-ethover](https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-ethover) - * Open it in etherscan (or whatever you configure) - * Show address balance in hover (mainnet) (note: might be rate-limited, configure your API key in settings) - * Download the bytecode and disassemble it. - * With hover info on instructions - * Representation of data as ASCII and resolving 4bytes to funcsigs, Color code reflects the type of instruction: stack, memory, storage, arithm., logic, system, environment, … - * Download the bytecode and show it. - * With hover info - * Click to see instruction boundaries - * Color coded bytes to reflect type of instruction) - * Show verified contract source (etherscan.io) - * Show reconstructed contract source from eveem.org - * Show reconstructed contract source from [evm.js](https://www.npmjs.com/package/evm) - * run [vscode-decompiler](https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-decompiler) to decompile it manually using panoramix (eveem.org) locally +- Address hover integration via [tintinweb.vscode-ethover](https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-ethover) + - Open it in etherscan (or whatever you configure) + - Show address balance in hover (mainnet) (note: might be rate-limited, configure your API key in settings) + - Download the bytecode and disassemble it. + - With hover info on instructions + - Representation of data as ASCII and resolving 4bytes to funcsigs, Color code reflects the type of instruction: stack, memory, storage, arithm., logic, system, environment, … + - Download the bytecode and show it. + - With hover info + - Click to see instruction boundaries + - Color coded bytes to reflect type of instruction) + - Show verified contract source (etherscan.io) + - Show reconstructed contract source from eveem.org + - Show reconstructed contract source from [evm.js](https://www.npmjs.com/package/evm) + - run [vscode-decompiler](https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-decompiler) to decompile it manually using panoramix (eveem.org) locally image -
Feature: State Variable Highlighting - ## State Variable Highlighting -* highlight contract local stateVars (golden box) +- highlight contract local stateVars (golden box) code_statevar -* alert on a shadowed variable (red box) +- alert on a shadowed variable (red box) code_shadowed -* highlight const stateVar (green box) +- highlight const stateVar (green box) code_const -* highlight inherited stateVar (blue box `Approval`) +- highlight inherited stateVar (blue box `Approval`) code_inherited
-
Feature: CodeLenses ## CodeLenses -* surya - interactive graph +- surya - interactive graph ![vscode-solidity-auditor-interactive-graph](https://user-images.githubusercontent.com/2865694/57710279-e27e8a00-766c-11e9-9ca9-8cde50aa31fc.gif) -* surya - generate report, show inheritance, show AST +- surya - generate report, show inheritance, show AST -![vscode-auditor-surya-report](https://user-images.githubusercontent.com/2865694/55647025-e5b86780-57dc-11e9-9cc0-b5197eb075b8.gif) +![vscode-auditor-surya-report](https://user-images.githubusercontent.com/2865694/55647025-e5b86780-57dc-11e9-9cc0-b5197eb075b8.gif) -* flatten source file with [tintinweb.vscode-solidity-flattener](https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-solidity-flattener) (using [truffle-flattener](https://www.npmjs.com/package/truffle-flattener)) +- flatten source file with [tintinweb.vscode-solidity-flattener](https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-solidity-flattener) (using [truffle-flattener](https://www.npmjs.com/package/truffle-flattener)) ![vscode-auditor-unittest](https://user-images.githubusercontent.com/2865694/55646826-72aef100-57dc-11e9-800b-fc649b41b4a9.gif) -* surya - ftrace +- surya - ftrace ![vscode-auditor-ftrace](https://user-images.githubusercontent.com/2865694/55646883-983bfa80-57dc-11e9-8e40-6194d1429dac.gif) -* UML - auto-generate UML for source-units or specific contracts +- UML - auto-generate UML for source-units or specific contracts vscode-solidity-auditor-uml -* Function Signature Hashes +- Function Signature Hashes -sva_light_vscode +sva_light_vscode
@@ -271,23 +263,23 @@ This feature is provided by [Inline Bookmarks](https://marketplace.visualstudio. ## Outline View -* library with function parameters `T` and declarations +- library with function parameters `T` and declarations outline_lib -* class and events, functions annotated (stateMutability, visibility) +- class and events, functions annotated (stateMutability, visibility) outline_class_event -* class and events, functions annotated (stateMutability, visibility) +- class and events, functions annotated (stateMutability, visibility) outline_class_2 -* inheritance browser - resolves inheritance, only shows inherited names +- inheritance browser - resolves inheritance, only shows inherited names outline_inherit -* extra information (subjective function complexity; accesses stateVar?) +- extra information (subjective function complexity; accesses stateVar?) outline_extra @@ -307,11 +299,11 @@ So, what can you do with it?
imageimage - Conveniently flatten selected files (selected folders or all files in the top-level view) (Note: `truffle-flattener` may require an `npm install` of the project for flattening to work) - Search for contracts that are likely to be deployed in the system (complete workspace or selected folders) -
image +
image - Context-sensitive views: click into a contract in the editor to list public state-changing methods -
image +
image - Get quick access to extension settings -
image +
image And there is more to come 🙌 stay tuned! @@ -324,12 +316,12 @@ And there is more to come 🙌 stay tuned! ## Commands -* suggest top level contracts aka "entrypoint contracts" (most derived) -* flatten current (codelens) or all suggested top level contracts (command) -![vscode-auditor-flaterra](https://user-images.githubusercontent.com/2865694/55907553-5db8d000-5bd7-11e9-8a11-8cef3964e284.gif) -* list all function signatures (human readable or json format) -![vscode-auditor-funcsigs](https://user-images.githubusercontent.com/2865694/55907153-3f9ea000-5bd6-11e9-8a47-e69a762963e9.gif) -* open remix in external browser +- suggest top level contracts aka "entrypoint contracts" (most derived) +- flatten current (codelens) or all suggested top level contracts (command) + ![vscode-auditor-flaterra](https://user-images.githubusercontent.com/2865694/55907553-5db8d000-5bd7-11e9-8a11-8cef3964e284.gif) +- list all function signatures (human readable or json format) + ![vscode-auditor-funcsigs](https://user-images.githubusercontent.com/2865694/55907153-3f9ea000-5bd6-11e9-8a47-e69a762963e9.gif) +- open remix in external browser Please refer to the extension's contribution section to show an up-to-date list of commands. @@ -370,43 +362,42 @@ Please refer to the extension's contribution section to show an up-to-date list -
Configuration: Settings & Customizations ## Extension Settings -* `solidity-va.mode.active` .. Enable/Disable all active components of this extension (emergency master-switch). -* `Solidity-va.parser.parseImports` ... Whether to recursively parse imports or not -* `Solidity-va.hover` ... Enable or Disable generic onHover information (asm instruction signatures, security notes) -* `Solidity-va.deco.statevars` ... decorate statevars in code view (golden, green, blue boxes) -* `Solidity-va.deco.arguments` ... enable/disable or select the mode for semantic highlighting of function arguments. (default: 'enable' = 'color and arrow') -* `Solidity-va.deco.argumentsMode` ... select the mode for semantic highlighting of function arguments (may require a reload) -* `Solidity-va.deco.argumentsSuffix` ... a custom Suffix/Symbol that is appended to the decoration when performing semantic highlighting for function arguments -* `Solidity-va.outline.enable` ... enable/disable outline and symbolprovider -* `Solidity-va.outline.decorations` ... decorate functions according to state mutability function visibility -* `Solidity-va.outline.inheritance.show` ... add inherited functions to outline view -* `Solidity-va.outline.extras` ... annotate functions with extra information (complexity, statevar access) -* `Solidity-va.outline.var.storage_annotations` ... Whether to show/hide storage annotations for variables in the outline view -* `Solidity-va.outline.pragmas.show` ... Whether to show/hide pragmas in the outline view -* `Solidity-va.outline.imports.show` ... Whether to show/hide imports in the outline view -* `Solidity-va.diagnostics.import.cdili-json` ... Automatically import diagnostic issues from external scanners using the `cdili-issue.json` format: - ```json - { - "onInputFile": "contracts/BountiesMetaTxRelayer.sol", - "atLineNr": "10", - "ruleType": "code_smell", - "severity": "major", - "linterVersion": "0.1", - "linterName": "maru", - "message": "State Variable Default Visibility - It is best practice to set the visibility of state variables explicitly. The default visibility for \"bountiesContract\" is internal. Other possible visibility values are public and private.", - "forRule": "State_Variable_Default_Visibility" - } - ``` -* `Solidity-va.codelens.enable` ... enable/disable codelens support (inline code actions) -* `solidity-va.preview.dot` ... open dot output in graphviz rendered form -* `solidity-va.preview.markdown` ... open markdown output in rendered form -* `Solidity-va.tools.surya.input.contracts` ... Define whether surya should take cached files or all contracts in the workspace as input +- `solidity-va.mode.active` .. Enable/Disable all active components of this extension (emergency master-switch). +- `Solidity-va.parser.parseImports` ... Whether to recursively parse imports or not +- `Solidity-va.hover` ... Enable or Disable generic onHover information (asm instruction signatures, security notes) +- `Solidity-va.deco.statevars` ... decorate statevars in code view (golden, green, blue boxes) +- `Solidity-va.deco.arguments` ... enable/disable or select the mode for semantic highlighting of function arguments. (default: 'enable' = 'color and arrow') +- `Solidity-va.deco.argumentsMode` ... select the mode for semantic highlighting of function arguments (may require a reload) +- `Solidity-va.deco.argumentsSuffix` ... a custom Suffix/Symbol that is appended to the decoration when performing semantic highlighting for function arguments +- `Solidity-va.outline.enable` ... enable/disable outline and symbolprovider +- `Solidity-va.outline.decorations` ... decorate functions according to state mutability function visibility +- `Solidity-va.outline.inheritance.show` ... add inherited functions to outline view +- `Solidity-va.outline.extras` ... annotate functions with extra information (complexity, statevar access) +- `Solidity-va.outline.var.storage_annotations` ... Whether to show/hide storage annotations for variables in the outline view +- `Solidity-va.outline.pragmas.show` ... Whether to show/hide pragmas in the outline view +- `Solidity-va.outline.imports.show` ... Whether to show/hide imports in the outline view +- `Solidity-va.diagnostics.import.cdili-json` ... Automatically import diagnostic issues from external scanners using the `cdili-issue.json` format: + ```json + { + "onInputFile": "contracts/BountiesMetaTxRelayer.sol", + "atLineNr": "10", + "ruleType": "code_smell", + "severity": "major", + "linterVersion": "0.1", + "linterName": "maru", + "message": "State Variable Default Visibility - It is best practice to set the visibility of state variables explicitly. The default visibility for \"bountiesContract\" is internal. Other possible visibility values are public and private.", + "forRule": "State_Variable_Default_Visibility" + } + ``` +- `Solidity-va.codelens.enable` ... enable/disable codelens support (inline code actions) +- `solidity-va.preview.dot` ... open dot output in graphviz rendered form +- `solidity-va.preview.markdown` ... open markdown output in rendered form +- `Solidity-va.tools.surya.input.contracts` ... Define whether surya should take cached files or all contracts in the workspace as input Please refer to the extension's contribution section to show an up-to-date list of settings. @@ -414,26 +405,25 @@ Please refer to the extension's contribution section to show an up-to-date list ## FAQ -* **Q:** The `uml` feature does not seem to work. How can I set it up? -* **A:** We are relying on a properly set-up [plantuml](https://plantuml.com/) installation. Please follow the set-up guide at [jebbs-plantuml vscode extension](https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml). - +- **Q:** The `uml` feature does not seem to work. How can I set it up? +- **A:** We are relying on a properly set-up [plantuml](https://plantuml.com/) installation. Please follow the set-up guide at [jebbs-plantuml vscode extension](https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml). + ## Known Issues -* outline view does not always refresh. **TempFix**: modify and save the file to trigger a refresh. -* codelenses do not appear. **TempFix**: modify and save the file to trigger a refresh. -* [github issues](https://github.com/tintinweb/vscode-solidity-auditor/issues) +- outline view does not always refresh. **TempFix**: modify and save the file to trigger a refresh. +- codelenses do not appear. **TempFix**: modify and save the file to trigger a refresh. +- [github issues](https://github.com/tintinweb/vscode-solidity-auditor/issues) # Acknowledgements -* Themes: [Atom One Dark Theme](https://github.com/akamud/vscode-theme-onedark) and an adapted version of built-in `Solarized Light` -* Base Grammar for Solidity: [vscode-solidity](https://github.com/juanfranblanco/vscode-solidity) - +- Themes: [Atom One Dark Theme](https://github.com/akamud/vscode-theme-onedark) and an adapted version of built-in `Solarized Light` +- Base Grammar for Solidity: [vscode-solidity](https://github.com/juanfranblanco/vscode-solidity) # Release Notes [Changelog](https://github.com/tintinweb/vscode-solidity-auditor/blob/master/CHANGELOG.md) - diff --git a/examples/cockpitFunctionOverride.sol b/examples/cockpitFunctionOverride.sol new file mode 100644 index 0000000..310201c --- /dev/null +++ b/examples/cockpitFunctionOverride.sol @@ -0,0 +1,37 @@ +//SPDX-License-Identifier: MIT + +pragma solidity ^0.8.17; + +interface B { + function testCall(uint256 a) external payable; +} + + +contract TestFunctionOverride { + +struct test1 { + uint256 t1; +} + +struct test2 { + string t2; +} + + address test; + function foo() public {} + + function foo(string memory bar2) public {} + + function bar(uint256 t1, uint256 t2) public { + B(test).testCall(t1); + } + function bar(uint256 t2) public payable { + B(test).testCall(t2); + } + + function bar(test1 calldata t1) public { + } + + function bar(test2 calldata t2) public {} + +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 96ef25c..ac8b225 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,1473 +1,1333 @@ { - "name": "solidity-visual-auditor", - "version": "0.1.5", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "solidity-visual-auditor", - "version": "0.1.5", - "dependencies": { - "c3-linearization": "^0.3.0", - "keccak": "^3.0.2", - "solidity-workspace": "^0.1.7", - "surya": "^0.4.6" - }, - "engines": { - "vscode": "^1.26.2" - } - }, - "node_modules/@solidity-parser/parser": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.5.tgz", - "integrity": "sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==", - "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/antlr4ts": { - "version": "0.5.0-alpha.4", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", - "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==" - }, - "node_modules/c3-linearization": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/c3-linearization/-/c3-linearization-0.3.0.tgz", - "integrity": "sha512-eQNsZQhFSJAhrNrITy2FpKh7EHS98q/pniDtQhndWqqsvayiPeqZ9T6I9V9PsHcm0nc+ZYJHKUvI/hh37I33HQ==" - }, - "node_modules/camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/graphviz": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/graphviz/-/graphviz-0.0.9.tgz", - "integrity": "sha512-SmoY2pOtcikmMCqCSy2NO1YsRfu9OO0wpTlOYW++giGjfX1a6gax/m1Fo8IdUd0/3H15cTOfR1SMKwohj4LKsg==", - "dependencies": { - "temp": "~0.4.0" - }, - "engines": { - "node": ">=0.6.8" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/keccak": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.3.tgz", - "integrity": "sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ==", - "hasInstallScript": true, - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dependencies": { - "invert-kv": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dependencies": { - "p-defer": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dependencies": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" - }, - "node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" - }, - "node_modules/node-gyp-build": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", - "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dependencies": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "engines": { - "node": ">=4" - } - }, - "node_modules/p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "engines": { - "node": ">=4" - } - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==" - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, - "node_modules/sha1-file": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/sha1-file/-/sha1-file-1.0.4.tgz", - "integrity": "sha512-IgcUYjTck/UAx0wdtBoTwiy4/yiIZX6do4uaqUtryJY/pBOQC1w3Cb/bZMyC2H3QYnodL5vbX0lY69xlWqeBnA==", - "deprecated": "Version 1.x or earlier is no longer supported." - }, - "node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/solidity-workspace": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/solidity-workspace/-/solidity-workspace-0.1.7.tgz", - "integrity": "sha512-m+9cKL6ZBb2gMTFgTg/LiMsqUC7adB6oWcDnSAwEJAiC7BHVijzLU6SOK1eEXqrHuhF/1wymypM7Dvvoo+MyKQ==", - "dependencies": { - "@solidity-parser/parser": "^0.14.3", - "c3-linearization": "^0.3.0", - "keccak": "^3.0.2", - "yargs": "^17.5.1" - }, - "bin": { - "solidity-workspace": "src/cli.js" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/surya": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/surya/-/surya-0.4.6.tgz", - "integrity": "sha512-zaTYkRbms26cuOWu5jon5l4OsToHX7ZEflqTozXgq/XxUL3VY+tEnxT9Te2WVsA/sYgZPwcH92yQZJgljsss4g==", - "dependencies": { - "@solidity-parser/parser": "^0.14.1", - "c3-linearization": "^0.3.0", - "colors": "^1.4.0", - "graphviz": "0.0.9", - "sha1-file": "^1.0.4", - "treeify": "^1.1.0", - "yargs": "^11.1.1" - }, - "bin": { - "surya": "bin/surya" - } - }, - "node_modules/surya/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/surya/node_modules/cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dependencies": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "node_modules/surya/node_modules/get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" - }, - "node_modules/surya/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/surya/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/surya/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/surya/node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/surya/node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/surya/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/surya/node_modules/wrap-ansi/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/surya/node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/surya/node_modules/y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" - }, - "node_modules/surya/node_modules/yargs": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.1.tgz", - "integrity": "sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw==", - "dependencies": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" - } - }, - "node_modules/surya/node_modules/yargs-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", - "integrity": "sha512-CswCfdOgCr4MMsT1GzbEJ7Z2uYudWyrGX8Bgh/0eyCzj/DXWdKq6a/ADufkzI1WAOIW6jYaXJvRyLhDO0kfqBw==", - "dependencies": { - "camelcase": "^4.1.0" - } - }, - "node_modules/temp": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.4.0.tgz", - "integrity": "sha512-IsFisGgDKk7qzK9erMIkQe/XwiSUdac7z3wYOsjcLkhPBy3k1SlvLoIh2dAHIlEpgA971CgguMrx9z8fFg7tSA==", - "engines": [ - "node >=0.4.0" - ] - }, - "node_modules/treeify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", - "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==" - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "engines": { - "node": ">=12" - } + "name": "solidity-visual-auditor", + "version": "0.2.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "solidity-visual-auditor", + "version": "0.2.0", + "dependencies": { + "solidity-workspace": "^0.2.1", + "surya": "^0.4.6" + }, + "devDependencies": { + "prettier": "^3.0.3" + }, + "engines": { + "vscode": "^1.26.2" + } + }, + "../solidity-workspace": { + "version": "0.1.8", + "extraneous": true, + "license": "MIT", + "dependencies": { + "@solidity-parser/parser": "^0.14.3", + "c3-linearization": "^0.3.0", + "keccak": "^3.0.2", + "yargs": "^17.5.1" + }, + "bin": { + "solidity-workspace": "src/cli.js" + } + }, + "node_modules/@solidity-parser/parser": { + "version": "0.14.3", + "license": "MIT", + "dependencies": { + "antlr4ts": "^0.5.0-alpha.4" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/antlr4ts": { + "version": "0.5.0-alpha.4", + "license": "BSD-3-Clause" + }, + "node_modules/c3-linearization": { + "version": "0.3.0", + "license": "MIT" + }, + "node_modules/camelcase": { + "version": "4.1.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/colors": { + "version": "1.4.0", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/cross-spawn": { + "version": "6.0.5", + "license": "MIT", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/execa": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-up": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-stream": { + "version": "4.1.0", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/graphviz": { + "version": "0.0.9", + "license": "GPL-3.0", + "dependencies": { + "temp": "~0.4.0" + }, + "engines": { + "node": ">=0.6.8" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/invert-kv": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "license": "ISC" + }, + "node_modules/keccak": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", + "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/lcid": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "invert-kv": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/locate-path": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/map-age-cleaner": { + "version": "0.1.3", + "license": "MIT", + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mem": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/nice-try": { + "version": "1.0.5", + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + }, + "node_modules/node-gyp-build": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", + "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "license": "MIT", + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/os-locale": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-defer": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-is-promise": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/p-limit": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-locate": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-try": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-key": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/prettier": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "1.0.1", + "license": "ISC" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } + ] + }, + "node_modules/semver": { + "version": "5.7.1", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "license": "ISC" + }, + "node_modules/sha1-file": { + "version": "1.0.4", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "license": "MIT", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "license": "ISC" + }, + "node_modules/solidity-workspace": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/solidity-workspace/-/solidity-workspace-0.2.1.tgz", + "integrity": "sha512-SyyrdRAcfbSNvNu9Ge8LTTuzIoIvXRELGEssiACzEV97WKY6CaFR1jB/VUa+gDj53tYQOg4+Zdy2WoV7ozEtSA==", + "dependencies": { + "@solidity-parser/parser": "^0.16.1", + "c3-linearization": "^0.3.0", + "keccak": "^3.0.2", + "yargs": "^17.5.1" + }, + "bin": { + "solidity-workspace": "src/cli.js" + } + }, + "node_modules/solidity-workspace/node_modules/@solidity-parser/parser": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.16.1.tgz", + "integrity": "sha512-PdhRFNhbTtu3x8Axm0uYpqOy/lODYQK+MlYSgqIsq2L8SFYEHJPHNUiOTAJbDGzNjjr1/n9AcIayxafR/fWmYw==", + "dependencies": { + "antlr4ts": "^0.5.0-alpha.4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/surya": { + "version": "0.4.6", + "license": "Apache-2.0", + "dependencies": { + "@solidity-parser/parser": "^0.14.1", + "c3-linearization": "^0.3.0", + "colors": "^1.4.0", + "graphviz": "0.0.9", + "sha1-file": "^1.0.4", + "treeify": "^1.1.0", + "yargs": "^11.1.1" + }, + "bin": { + "surya": "bin/surya" + } + }, + "node_modules/surya/node_modules/ansi-regex": { + "version": "3.0.1", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/surya/node_modules/cliui": { + "version": "4.1.0", + "license": "ISC", + "dependencies": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/surya/node_modules/get-caller-file": { + "version": "1.0.3", + "license": "ISC" + }, + "node_modules/surya/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/surya/node_modules/string-width": { + "version": "2.1.1", + "license": "MIT", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/surya/node_modules/strip-ansi": { + "version": "4.0.0", + "license": "MIT", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/surya/node_modules/wrap-ansi": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/surya/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/surya/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/surya/node_modules/wrap-ansi/node_modules/string-width": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/surya/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "3.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/surya/node_modules/y18n": { + "version": "3.2.2", + "license": "ISC" + }, + "node_modules/surya/node_modules/yargs": { + "version": "11.1.1", + "license": "MIT", + "dependencies": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" + } + }, + "node_modules/surya/node_modules/yargs-parser": { + "version": "9.0.2", + "license": "ISC", + "dependencies": { + "camelcase": "^4.1.0" + } + }, + "node_modules/temp": { + "version": "0.4.0", + "engines": [ + "node >=0.4.0" + ] + }, + "node_modules/treeify": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/which": { + "version": "1.3.1", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "license": "ISC" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "license": "ISC" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + } + }, + "dependencies": { + "@solidity-parser/parser": { + "version": "0.14.3", + "requires": { + "antlr4ts": "^0.5.0-alpha.4" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "antlr4ts": { + "version": "0.5.0-alpha.4" }, - "dependencies": { + "c3-linearization": { + "version": "0.3.0" + }, + "camelcase": { + "version": "4.1.0" + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "code-point-at": { + "version": "1.1.0" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "colors": { + "version": "1.4.0" + }, + "cross-spawn": { + "version": "6.0.5", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "decamelize": { + "version": "1.2.0" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "end-of-stream": { + "version": "1.4.4", + "requires": { + "once": "^1.4.0" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "execa": { + "version": "1.0.0", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "requires": { + "locate-path": "^2.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-stream": { + "version": "4.1.0", + "requires": { + "pump": "^3.0.0" + } + }, + "graphviz": { + "version": "0.0.9", + "requires": { + "temp": "~0.4.0" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "invert-kv": { + "version": "2.0.0" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-stream": { + "version": "1.1.0" + }, + "isexe": { + "version": "2.0.0" + }, + "keccak": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", + "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", + "requires": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" + } + }, + "lcid": { + "version": "2.0.0", + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "requires": { + "p-defer": "^1.0.0" + } + }, + "mem": { + "version": "4.3.0", + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mimic-fn": { + "version": "2.1.0" + }, + "nice-try": { + "version": "1.0.5" + }, + "node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + }, + "node-gyp-build": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", + "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==" + }, + "npm-run-path": { + "version": "2.0.2", + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1" + }, + "once": { + "version": "1.4.0", + "requires": { + "wrappy": "1" + } + }, + "os-locale": { + "version": "3.1.0", + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-defer": { + "version": "1.0.0" + }, + "p-finally": { + "version": "1.0.0" + }, + "p-is-promise": { + "version": "2.1.0" + }, + "p-limit": { + "version": "1.3.0", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0" + }, + "path-exists": { + "version": "3.0.0" + }, + "path-key": { + "version": "2.0.1" + }, + "prettier": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "require-directory": { + "version": "2.1.1" + }, + "require-main-filename": { + "version": "1.0.1" + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "semver": { + "version": "5.7.1" + }, + "set-blocking": { + "version": "2.0.0" + }, + "sha1-file": { + "version": "1.0.4" + }, + "shebang-command": { + "version": "1.2.0", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0" + }, + "signal-exit": { + "version": "3.0.7" + }, + "solidity-workspace": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/solidity-workspace/-/solidity-workspace-0.2.1.tgz", + "integrity": "sha512-SyyrdRAcfbSNvNu9Ge8LTTuzIoIvXRELGEssiACzEV97WKY6CaFR1jB/VUa+gDj53tYQOg4+Zdy2WoV7ozEtSA==", + "requires": { + "@solidity-parser/parser": "^0.16.1", + "c3-linearization": "^0.3.0", + "keccak": "^3.0.2", + "yargs": "^17.5.1" + }, + "dependencies": { "@solidity-parser/parser": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.5.tgz", - "integrity": "sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==", - "requires": { - "antlr4ts": "^0.5.0-alpha.4" - } - }, + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.16.1.tgz", + "integrity": "sha512-PdhRFNhbTtu3x8Axm0uYpqOy/lODYQK+MlYSgqIsq2L8SFYEHJPHNUiOTAJbDGzNjjr1/n9AcIayxafR/fWmYw==", + "requires": { + "antlr4ts": "^0.5.0-alpha.4" + } + } + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-eof": { + "version": "1.0.0" + }, + "surya": { + "version": "0.4.6", + "requires": { + "@solidity-parser/parser": "^0.14.1", + "c3-linearization": "^0.3.0", + "colors": "^1.4.0", + "graphviz": "0.0.9", + "sha1-file": "^1.0.4", + "treeify": "^1.1.0", + "yargs": "^11.1.1" + }, + "dependencies": { "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "antlr4ts": { - "version": "0.5.0-alpha.4", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", - "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==" - }, - "c3-linearization": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/c3-linearization/-/c3-linearization-0.3.0.tgz", - "integrity": "sha512-eQNsZQhFSJAhrNrITy2FpKh7EHS98q/pniDtQhndWqqsvayiPeqZ9T6I9V9PsHcm0nc+ZYJHKUvI/hh37I33HQ==" - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==" + "version": "3.0.1" }, "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "requires": { - "once": "^1.4.0" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "requires": { - "locate-path": "^2.0.0" - } + "version": "4.1.0", + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } }, "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "requires": { - "pump": "^3.0.0" - } - }, - "graphviz": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/graphviz/-/graphviz-0.0.9.tgz", - "integrity": "sha512-SmoY2pOtcikmMCqCSy2NO1YsRfu9OO0wpTlOYW++giGjfX1a6gax/m1Fo8IdUd0/3H15cTOfR1SMKwohj4LKsg==", - "requires": { - "temp": "~0.4.0" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" + "version": "1.0.3" }, "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "keccak": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.3.tgz", - "integrity": "sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ==", - "requires": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" - } - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "requires": { - "invert-kv": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "requires": { - "p-defer": "^1.0.0" - } - }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" - }, - "node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" - }, - "node-gyp-build": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", - "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==" - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "requires": { - "path-key": "^2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==" - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==" - }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==" - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==" - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==" - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, - "sha1-file": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/sha1-file/-/sha1-file-1.0.4.tgz", - "integrity": "sha512-IgcUYjTck/UAx0wdtBoTwiy4/yiIZX6do4uaqUtryJY/pBOQC1w3Cb/bZMyC2H3QYnodL5vbX0lY69xlWqeBnA==" - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==" - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "solidity-workspace": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/solidity-workspace/-/solidity-workspace-0.1.7.tgz", - "integrity": "sha512-m+9cKL6ZBb2gMTFgTg/LiMsqUC7adB6oWcDnSAwEJAiC7BHVijzLU6SOK1eEXqrHuhF/1wymypM7Dvvoo+MyKQ==", - "requires": { - "@solidity-parser/parser": "^0.14.3", - "c3-linearization": "^0.3.0", - "keccak": "^3.0.2", - "yargs": "^17.5.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } + "version": "2.0.0" }, "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } + "version": "2.1.1", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } }, "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==" - }, - "surya": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/surya/-/surya-0.4.6.tgz", - "integrity": "sha512-zaTYkRbms26cuOWu5jon5l4OsToHX7ZEflqTozXgq/XxUL3VY+tEnxT9Te2WVsA/sYgZPwcH92yQZJgljsss4g==", - "requires": { - "@solidity-parser/parser": "^0.14.1", - "c3-linearization": "^0.3.0", - "colors": "^1.4.0", - "graphviz": "0.0.9", - "sha1-file": "^1.0.4", - "treeify": "^1.1.0", - "yargs": "^11.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==" - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" - }, - "yargs": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.1.tgz", - "integrity": "sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw==", - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" - } - }, - "yargs-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", - "integrity": "sha512-CswCfdOgCr4MMsT1GzbEJ7Z2uYudWyrGX8Bgh/0eyCzj/DXWdKq6a/ADufkzI1WAOIW6jYaXJvRyLhDO0kfqBw==", - "requires": { - "camelcase": "^4.1.0" - } - } - } - }, - "temp": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.4.0.tgz", - "integrity": "sha512-IsFisGgDKk7qzK9erMIkQe/XwiSUdac7z3wYOsjcLkhPBy3k1SlvLoIh2dAHIlEpgA971CgguMrx9z8fFg7tSA==" - }, - "treeify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", - "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==" + "version": "4.0.0", + "requires": { + "ansi-regex": "^3.0.0" + } }, "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "version": "2.1.0", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "requires": { + "ansi-regex": "^2.0.0" + } } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + } }, "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + "version": "3.2.2" }, "yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } + "version": "11.1.1", + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" + } }, "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" + "version": "9.0.2", + "requires": { + "camelcase": "^4.1.0" + } } + } + }, + "temp": { + "version": "0.4.0" + }, + "treeify": { + "version": "1.1.0" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "which": { + "version": "1.3.1", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0" + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" } + } } diff --git a/package.json b/package.json index 02e92a7..8a8a436 100644 --- a/package.json +++ b/package.json @@ -1,547 +1,557 @@ { - "name": "solidity-visual-auditor", - "displayName": "Solidity Visual Developer", - "description": "Ethereum Solidity Language customized for developers and auditors using Visual Studio Code", - "keywords": [ - "solidity", - "ethereum", - "blockchain", - "security", - "audit", - "review", - "developer", - "solidity security", - "solidity audit" - ], - "version": "0.1.5", - "publisher": "tintinweb", - "icon": "images/icon.png", - "engines": { - "vscode": "^1.26.2" - }, - "categories": [ - "Programming Languages" - ], - "bugs": { - "url": "https://github.com/tintinweb/vscode-solidity-auditor/issues" - }, - "repository": { - "type": "git", - "url": "https://github.com/tintinweb/vscode-solidity-auditor" + "name": "solidity-visual-auditor", + "displayName": "Solidity Visual Developer", + "description": "Ethereum Solidity Language customized for developers and auditors using Visual Studio Code", + "keywords": [ + "solidity", + "ethereum", + "blockchain", + "security", + "audit", + "review", + "developer", + "solidity security", + "solidity audit" + ], + "version": "0.2.0", + "publisher": "tintinweb", + "icon": "images/icon.png", + "engines": { + "vscode": "^1.26.2" + }, + "categories": [ + "Programming Languages" + ], + "bugs": { + "url": "https://github.com/tintinweb/vscode-solidity-auditor/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/tintinweb/vscode-solidity-auditor" + }, + "activationEvents": [ + "onLanguage:solidity", + "onCommand:solidity-va.whatsNew.show", + "onCommand:solidity-va.surya.graph", + "onCommand:solidity-va.surya.inheritance", + "onCommand:solidity-va.insights.topLevelContracts", + "onCommand:solidity-va.tools.flaterra", + "onCommand:solidity-va.cockpit.explorer.context.flatten", + "onCommand:solidity-va.tools.flattenCandidates", + "onCommand:solidity-va.tools.function.signatures", + "onCommand:solidity-va.tools.function.signatures.json", + "onCommand:solidity-va.tools.function.signatures.forWorkspace", + "onCommand:solidity-va.tools.function.signatures.forWorkspace.json", + "onCommand:solidity-va.tools.remix.openExternal", + "onCommand:solidity-va.cockpit.explorer.refresh", + "onCommand:solidity-va.cockpit.topLevelContracts.refresh", + "onCommand:solidity-va.cockpit.settings.toggle", + "onCommand:solidity-va.etherscan.getSource", + "onView:solidity-va-cockpit", + "onView:solidity-va-cockpit-explorer", + "onView:solidity-va-cockpit-topLevelContracts", + "onView:solidity-va-cockpit-flatFiles", + "onView:solidity-va-cockpit-settings", + "onView:solidity-va-cockpit-ftrace", + "onView:solidity-va-cockpit-publicMethods", + "onView:solidity-va-cockpit-externalCalls" + ], + "main": "./src/extension", + "capabilities": { + "hoverProvider": "true" + }, + "contributes": { + "viewsContainers": { + "activitybar": [ + { + "id": "solidity-va-cockpit", + "title": "Solidity Visual Developer", + "icon": "images/glass3.png" + } + ] }, - "activationEvents": [ - "onLanguage:solidity", - "onCommand:solidity-va.whatsNew.show", - "onCommand:solidity-va.surya.graph", - "onCommand:solidity-va.surya.inheritance", - "onCommand:solidity-va.insights.topLevelContracts", - "onCommand:solidity-va.tools.flaterra", - "onCommand:solidity-va.cockpit.explorer.context.flatten", - "onCommand:solidity-va.tools.flattenCandidates", - "onCommand:solidity-va.tools.function.signatures", - "onCommand:solidity-va.tools.function.signatures.json", - "onCommand:solidity-va.tools.function.signatures.forWorkspace.json", - "onCommand:solidity-va.tools.remix.openExternal", - "onCommand:solidity-va.cockpit.explorer.refresh", - "onCommand:solidity-va.cockpit.topLevelContracts.refresh", - "onCommand:solidity-va.cockpit.settings.toggle", - "onCommand:solidity-va.etherscan.getSource", - "onView:solidity-va-cockpit", - "onView:solidity-va-cockpit-explorer", - "onView:solidity-va-cockpit-topLevelContracts", - "onView:solidity-va-cockpit-flatFiles", - "onView:solidity-va-cockpit-settings", - "onView:solidity-va-cockpit-ftrace", - "onView:solidity-va-cockpit-publicMethods", - "onView:solidity-va-cockpit-externalCalls" - ], - "main": "./src/extension", - "capabilities": { - "hoverProvider": "true" + "views": { + "solidity-va-cockpit": [ + { + "id": "solidity-va-cockpit-explorer", + "name": "Workspace: Explorer" + }, + { + "id": "solidity-va-cockpit-topLevelContracts", + "name": "Workspace: Top Level Contracts" + }, + { + "id": "solidity-va-cockpit-flatFiles", + "name": "Workspace: */flat_* Files" + }, + { + "id": "solidity-va-cockpit-publicMethods", + "name": "Context: Public State-Changing Methods" + }, + { + "id": "solidity-va-cockpit-externalCalls", + "name": "Context: External Calls" + }, + { + "id": "solidity-va-cockpit-ftrace", + "name": "Context: Function Call Trace" + }, + { + "id": "solidity-va-cockpit-settings", + "name": "Settings" + } + ] }, - "contributes": { - "viewsContainers": { - "activitybar": [ - { - "id": "solidity-va-cockpit", - "title": "Solidity Visual Developer", - "icon": "images/glass3.png" - } - ] - }, - "views": { - "solidity-va-cockpit": [ - { - "id": "solidity-va-cockpit-explorer", - "name": "Workspace: Explorer" - }, - { - "id": "solidity-va-cockpit-topLevelContracts", - "name": "Workspace: Top Level Contracts" - }, - { - "id": "solidity-va-cockpit-flatFiles", - "name": "Workspace: */flat_* Files" - }, - { - "id": "solidity-va-cockpit-publicMethods", - "name": "Context: Public StateChanging Methods" - }, - { - "id": "solidity-va-cockpit-externalCalls", - "name": "Context: External Calls" - }, - { - "id": "solidity-va-cockpit-ftrace", - "name": "Context: Function Call Trace" - }, - { - "id": "solidity-va-cockpit-settings", - "name": "Settings" - } - ] - }, - "menus": { - "view/title": [ - { - "command": "solidity-va.cockpit.explorer.refresh", - "when": "view == solidity-va-cockpit-explorer", - "group": "navigation" - }, - { - "command": "solidity-va.cockpit.topLevelContracts.refresh", - "when": "view == solidity-va-cockpit-topLevelContracts", - "group": "navigation" - }, - { - "command": "solidity-va.cockpit.topLevelContracts.flatten", - "when": "view == solidity-va-cockpit-topLevelContracts", - "group": "navigation" - }, - { - "command": "solidity-va.cockpit.flatFiles.refresh", - "when": "view == solidity-va-cockpit-flatFiles", - "group": "navigation" - } - ], - "view/item/context": [ - { - "group": "solidity", - "command": "solidity-va.cockpit.topLevelContracts.refresh", - "when": "view == solidity-va-cockpit-explorer && viewItem =~ /^((?!\\.sol).)*$/" - }, - { - "group": "solidity", - "command": "solidity-va.cockpit.explorer.context.flatten", - "when": "view == solidity-va-cockpit-explorer && viewItem =~ /\\.sol/ || view == solidity-va-cockpit-topLevelContracts" - }, - { - "group": "solidity", - "command": "solidity-va.surya.mdreport", - "when": "view == solidity-va-cockpit-explorer || view == solidity-va-cockpit-topLevelContracts || view == solidity-va-cockpit-flatFiles" - }, - { - "group": "solidity", - "command": "solidity-va.surya.graph", - "when": "view == solidity-va-cockpit-explorer || view == solidity-va-cockpit-topLevelContracts || view == solidity-va-cockpit-flatFiles" - }, - { - "group": "solidity", - "command": "solidity-va.surya.graphSimple", - "when": "view == solidity-va-cockpit-explorer || view == solidity-va-cockpit-topLevelContracts || view == solidity-va-cockpit-flatFiles" - }, - { - "group": "solidity", - "command": "solidity-va.surya.inheritance", - "when": "view == solidity-va-cockpit-explorer || view == solidity-va-cockpit-topLevelContracts || view == solidity-va-cockpit-flatFiles" - } - ] - }, - "commands": [ - { - "command": "solidity-va.test.createTemplate", - "title": "Unittest - create stub for current contract", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.surya.mdreport", - "title": "Surya - generate report", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.surya.describe", - "title": "Surya - describe", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.surya.graph", - "title": "Surya - call graph", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.surya.graphThis", - "title": "Surya - call graph for active editor (graph this)", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.surya.graphSimple", - "title": "Surya - contract interaction graph", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.surya.inheritance", - "title": "Surya - show inheritance graph", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.insights.topLevelContracts", - "title": "Tools - list suggested top level / entry point contracts", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.tools.flaterra", - "title": "Tools - flatten current file", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.cockpit.explorer.context.flatten", - "title": "Solidity - Flatten Selected File(s)", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.cockpit.topLevelContracts.flatten", - "title": "Flatten", - "category": "Solidity Visual Developer", - "icon": { - "light": "images/cmd-flatten.svg", - "dark": "images/cmd-flatten.svg" - } - }, - { - "command": "solidity-va.tools.flattenCandidates", - "title": "Tools - flatten all suggested top level contracts", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.tools.function.signatures", - "title": "Tools - list function signatures", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.tools.function.signatures.json", - "title": "Tools - list function signatures (json)", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.tools.function.signatures.forWorkspace.json", - "title": "Tools - list function signatures for all solidity files in workspace (json)", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.tools.remix.openExternal", - "title": "Tools - launch Remix-IDE", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.cockpit.explorer.refresh", - "title": "Scan Workspace", - "category": "Solidity Visual Developer", - "icon": { - "light": "images/refresh-light.svg", - "dark": "images/refresh-dark.svg" - } - }, - { - "command": "solidity-va.cockpit.topLevelContracts.refresh", - "title": "Find Top Level Contracts", - "category": "Solidity Visual Developer", - "icon": { - "light": "images/refresh-light.svg", - "dark": "images/refresh-dark.svg" - } - }, - { - "command": "solidity-va.cockpit.flatFiles.refresh", - "title": "Scan Workspace", - "category": "Solidity Visual Developer", - "icon": { - "light": "images/refresh-light.svg", - "dark": "images/refresh-dark.svg" - } - }, - { - "command": "solidity-va.cockpit.settings.toggle", - "title": "Toggle Setting", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.whatsNew.show", - "title": "Extension - What's New", - "category": "Solidity Visual Developer" - }, - { - "command": "solidity-va.etherscan.getSource", - "title": "EtherScan - get contract source for address", - "category": "Solidity Visual Developer" - } - ], - "configuration": { - "type": "object", - "title": "Solidity Visual Developer configuration", - "properties": { - "solidity-va.hover": { - "type": "boolean", - "default": true, - "description": "Whether to enable/disable Solidity hover." - }, - "solidity-va.deco.statevars": { - "type": "boolean", - "default": true, - "description": "Whether to enable/disable Solidity statevar decoration" - }, - "solidity-va.deco.arguments": { - "type": "boolean", - "default": true, - "description": "Whether to enable/disable semantic highlighting for function arguments. (May require a reload)." - }, - "solidity-va.deco.argumentsMode": { - "type": "string", - "enum": [ - "color and symbol", - "color only", - "symbol only" - ], - "default": "color and symbol", - "description": "Select the mode for semantic highlighting of function arguments. (May require a reload)." - }, - "solidity-va.deco.argumentsSuffix": { - "type": "string", - "default": "⬆", - "description": "A custom Suffix/Symbol that is appended to the decoration when performing semantic highlighting for function arguments" - }, - "solidity-va.deco.warn.reserved": { - "type": "boolean", - "default": true, - "description": "Enable/Disable warning decoration when overriding reserved names" - }, - "solidity-va.deco.warn.externalCalls": { - "type": "boolean", - "default": true, - "description": "Enable/Disable gutter-icon decorations for lines performing external address calls" - }, - "solidity-va.outline.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable outline / symbolprovider" - }, - "solidity-va.outline.decorations": { - "type": "boolean", - "default": true, - "description": "Whether to enable/disable Function Mutability/Accessibility decoration in the outline view" - }, - "solidity-va.outline.inheritance.show": { - "type": "boolean", - "default": true, - "description": "Whether to show/hide inherited names in the outline view" - }, - "solidity-va.outline.extras": { - "type": "boolean", - "default": true, - "description": "Whether to show/hide extras (complexity, state var access) for functions in the outline view" - }, - "solidity-va.outline.var.storage_annotations": { - "type": "boolean", - "default": true, - "description": "Whether to show/hide storage annotations for variables in the outline view" - }, - "solidity-va.outline.pragmas.show": { - "type": "boolean", - "default": true, - "description": "Whether to show/hide pragmas in the outline view" - }, - "solidity-va.outline.imports.show": { - "type": "boolean", - "default": true, - "description": "Whether to show/hide imports in the outline view" - }, - "solidity-va.overviewruler.decorations.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable decorations in the overview ruler (requires reload)" - }, - "solidity-va.parser.parseImports": { - "type": "boolean", - "default": true, - "description": "Whether to recursively parse imports or not" - }, - "solidity-va.diagnostics.cdili_json.import": { - "type": "boolean", - "default": false, - "description": "Recursively search for CDILI format *-issues.json from external scanners and visualize findings as diagnostics in vscode" - }, - "solidity-va.tools.surya.input.contracts": { - "type": "string", - "enum": [ - "cached", - "workspace" - ], - "default": "cached", - "description": "Define whether surya should take cached files or all contracts in the workspace as input" - }, - "solidity-va.tools.surya.option.negModifiers": { - "type": "boolean", - "default": false, - "description": "Surya.mdreport: Also list modifiers that are not present ( ~~strikedthrough~~). This may help catch issues relating to missing modifiers." - }, - "solidity-va.preview.dot": { - "type": "boolean", - "default": true, - "description": "Open dot output in graphviz rendered form (relies on a graphviz preview extension to be installed)" - }, - "solidity-va.preview.markdown": { - "type": "boolean", - "default": false, - "description": "Open markdown output in rendered form (relies on a markdown preview extension to be installed)" - }, - "solidity-va.codelens.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable all codelenses - inline action (master switch)" - }, - "solidity-va.codelens.report.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable codelens 'report'" - }, - "solidity-va.codelens.graph.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable codelens 'graph'" - }, - "solidity-va.codelens.graphThis.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable codelens 'graphThis'" - }, - "solidity-va.codelens.inheritance.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable codelens 'inheritance'" - }, - "solidity-va.codelens.parse.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable codelens 'parse'" - }, - "solidity-va.codelens.flatten.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable codelens 'report'" - }, - "solidity-va.codelens.funcSigs.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable codelens 'funcSigs'" - }, - "solidity-va.codelens.uml.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable codelens 'uml'" - }, - "solidity-va.codelens.unittestStub.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable codelens 'UnitTest Stub'" - }, - "solidity-va.codelens.dependencies.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable codelens 'report'" - }, - "solidity-va.codelens.ftrace.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable codelens 'ftrace'" - }, - "solidity-va.codelens.drawio.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable codelens 'draw.io' uml export" - }, - "solidity-va.findAllReferences.enable": { - "type": "boolean", - "default": true, - "description": "Enable/Disable right-click -> Find All References. Note: This allows you to disable the built-in reference provider in favor of one of another extension. Takes effect after restart." - }, - "solidity-va.mode.active": { - "type": "boolean", - "default": true, - "description": "Enable/Disable all active components of this extension (emergency)." - }, - "solidity-va.uml.options": { - "type": "text", - "default": "", - "description": "Add custom uml options" - }, - "solidity-va.uml.actors.enable": { - "type": "boolean", - "default": false, - "description": "Enable/Disable actors in uml" - }, - "solidity-va.cockpit.view.topLevelContracts.listStyle": { - "type": "string", - "enum": [ - "flat", - "tree" - ], - "default": "flat", - "description": "Select TopLevelContracts view list style." - }, - "solidity-va.whatsNew.disabled": { - "type": "boolean", - "default": false, - "description": "Enable/Disable update notifications" - }, - "solidity-va.test.defaultUnittestTemplate": { - "type": "string", - "enum": [ - "hardhat", - "truffle" - ], - "default": "truffle", - "description": "Select which default template to use when creating a unitTest stub (e.g. truffle, hardhat)" - }, - "solidity-va.debug.parser.showExceptions": { - "type": "boolean", - "default": false, - "description": "Enable/Disable printing parser error / stacktraces to console log (noisy)" - }, - "solidity-va.flatten.mode": { - "type": "string", - "enum": [ - "internal (lexical)", - "truffle" - ], - "default": "default", - "description": "Select which flattener to use (e.g. default=lexical flattener, truffle=truffle-flattener)" - } - } + "menus": { + "view/title": [ + { + "command": "solidity-va.cockpit.explorer.refresh", + "when": "view == solidity-va-cockpit-explorer", + "group": "navigation" + }, + { + "command": "solidity-va.cockpit.topLevelContracts.refresh", + "when": "view == solidity-va-cockpit-topLevelContracts", + "group": "navigation" + }, + { + "command": "solidity-va.cockpit.topLevelContracts.flatten", + "when": "view == solidity-va-cockpit-topLevelContracts", + "group": "navigation" + }, + { + "command": "solidity-va.cockpit.flatFiles.refresh", + "when": "view == solidity-va-cockpit-flatFiles", + "group": "navigation" } + ], + "view/item/context": [ + { + "group": "solidity", + "command": "solidity-va.cockpit.topLevelContracts.refresh", + "when": "view == solidity-va-cockpit-explorer && viewItem =~ /^((?!\\.sol).)*$/" + }, + { + "group": "solidity", + "command": "solidity-va.cockpit.explorer.context.flatten", + "when": "view == solidity-va-cockpit-explorer && viewItem =~ /\\.sol/ || view == solidity-va-cockpit-topLevelContracts" + }, + { + "group": "solidity", + "command": "solidity-va.surya.mdreport", + "when": "view == solidity-va-cockpit-explorer || view == solidity-va-cockpit-topLevelContracts || view == solidity-va-cockpit-flatFiles" + }, + { + "group": "solidity", + "command": "solidity-va.surya.graph", + "when": "view == solidity-va-cockpit-explorer || view == solidity-va-cockpit-topLevelContracts || view == solidity-va-cockpit-flatFiles" + }, + { + "group": "solidity", + "command": "solidity-va.surya.graphSimple", + "when": "view == solidity-va-cockpit-explorer || view == solidity-va-cockpit-topLevelContracts || view == solidity-va-cockpit-flatFiles" + }, + { + "group": "solidity", + "command": "solidity-va.surya.inheritance", + "when": "view == solidity-va-cockpit-explorer || view == solidity-va-cockpit-topLevelContracts || view == solidity-va-cockpit-flatFiles" + } + ] }, - "extensionDependencies": [ - "tintinweb.vscode-solidity-language", - "tintinweb.graphviz-interactive-preview" - ], - "extensionPack": [ - "tintinweb.vscode-solidity-flattener", - "jebbs.plantuml", - "tintinweb.vscode-inline-bookmarks", - "tintinweb.vscode-ethover" + "commands": [ + { + "command": "solidity-va.test.createTemplate", + "title": "Unittest - create stub for current contract", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.surya.mdreport", + "title": "Surya - generate report", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.surya.describe", + "title": "Surya - describe", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.surya.graph", + "title": "Surya - call graph", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.surya.graphThis", + "title": "Surya - call graph for active editor (graph this)", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.surya.graphSimple", + "title": "Surya - contract interaction graph", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.surya.inheritance", + "title": "Surya - show inheritance graph", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.insights.topLevelContracts", + "title": "Tools - list suggested top level / entry point contracts", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.tools.flaterra", + "title": "Tools - flatten current file", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.cockpit.explorer.context.flatten", + "title": "Solidity - Flatten Selected File(s)", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.cockpit.topLevelContracts.flatten", + "title": "Flatten", + "category": "Solidity Visual Developer", + "icon": { + "light": "images/cmd-flatten.svg", + "dark": "images/cmd-flatten.svg" + } + }, + { + "command": "solidity-va.tools.flattenCandidates", + "title": "Tools - flatten all suggested top level contracts", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.tools.function.signatures", + "title": "Tools - list function signatures", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.tools.function.signatures.json", + "title": "Tools - list function signatures (json)", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.tools.function.signatures.forWorkspace", + "title": "Tools - list function signatures for all solidity files in workspace", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.tools.function.signatures.forWorkspace.json", + "title": "Tools - list function signatures for all solidity files in workspace (json)", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.tools.remix.openExternal", + "title": "Tools - launch Remix-IDE", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.cockpit.explorer.refresh", + "title": "Scan Workspace", + "category": "Solidity Visual Developer", + "icon": { + "light": "images/refresh-light.svg", + "dark": "images/refresh-dark.svg" + } + }, + { + "command": "solidity-va.cockpit.topLevelContracts.refresh", + "title": "Find Top Level Contracts", + "category": "Solidity Visual Developer", + "icon": { + "light": "images/refresh-light.svg", + "dark": "images/refresh-dark.svg" + } + }, + { + "command": "solidity-va.cockpit.flatFiles.refresh", + "title": "Scan Workspace", + "category": "Solidity Visual Developer", + "icon": { + "light": "images/refresh-light.svg", + "dark": "images/refresh-dark.svg" + } + }, + { + "command": "solidity-va.cockpit.settings.toggle", + "title": "Toggle Setting", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.whatsNew.show", + "title": "Extension - What's New", + "category": "Solidity Visual Developer" + }, + { + "command": "solidity-va.etherscan.getSource", + "title": "EtherScan - get contract source for address", + "category": "Solidity Visual Developer" + } ], - "dependencies": { - "c3-linearization": "^0.3.0", - "keccak": "^3.0.2", - "solidity-workspace": "^0.1.7", - "surya": "^0.4.6" + "configuration": { + "type": "object", + "title": "Solidity Visual Developer configuration", + "properties": { + "solidity-va.hover": { + "type": "boolean", + "default": true, + "description": "Whether to enable/disable Solidity hover." + }, + "solidity-va.deco.statevars": { + "type": "boolean", + "default": true, + "description": "Whether to enable/disable Solidity statevar decoration" + }, + "solidity-va.deco.arguments": { + "type": "boolean", + "default": true, + "description": "Whether to enable/disable semantic highlighting for function arguments. (May require a reload)." + }, + "solidity-va.deco.argumentsMode": { + "type": "string", + "enum": [ + "color and symbol", + "color only", + "symbol only" + ], + "default": "color and symbol", + "description": "Select the mode for semantic highlighting of function arguments. (May require a reload)." + }, + "solidity-va.deco.argumentsSuffix": { + "type": "string", + "default": "⬆", + "description": "A custom Suffix/Symbol that is appended to the decoration when performing semantic highlighting for function arguments" + }, + "solidity-va.deco.warn.reserved": { + "type": "boolean", + "default": true, + "description": "Enable/Disable warning decoration when overriding reserved names" + }, + "solidity-va.deco.warn.externalCalls": { + "type": "boolean", + "default": true, + "description": "Enable/Disable gutter-icon decorations for lines performing external address calls" + }, + "solidity-va.outline.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable outline / symbolprovider" + }, + "solidity-va.outline.decorations": { + "type": "boolean", + "default": true, + "description": "Whether to enable/disable Function Mutability/Accessibility decoration in the outline view" + }, + "solidity-va.outline.inheritance.show": { + "type": "boolean", + "default": true, + "description": "Whether to show/hide inherited names in the outline view" + }, + "solidity-va.outline.extras": { + "type": "boolean", + "default": true, + "description": "Whether to show/hide extras (complexity, state var access) for functions in the outline view" + }, + "solidity-va.outline.var.storage_annotations": { + "type": "boolean", + "default": true, + "description": "Whether to show/hide storage annotations for variables in the outline view" + }, + "solidity-va.outline.pragmas.show": { + "type": "boolean", + "default": true, + "description": "Whether to show/hide pragmas in the outline view" + }, + "solidity-va.outline.imports.show": { + "type": "boolean", + "default": true, + "description": "Whether to show/hide imports in the outline view" + }, + "solidity-va.overviewruler.decorations.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable decorations in the overview ruler (requires reload)" + }, + "solidity-va.parser.parseImports": { + "type": "boolean", + "default": true, + "description": "Whether to recursively parse imports or not" + }, + "solidity-va.diagnostics.cdili_json.import": { + "type": "boolean", + "default": false, + "description": "Recursively search for CDILI format *-issues.json from external scanners and visualize findings as diagnostics in vscode" + }, + "solidity-va.tools.surya.input.contracts": { + "type": "string", + "enum": [ + "cached", + "workspace" + ], + "default": "cached", + "description": "Define whether surya should take cached files or all contracts in the workspace as input" + }, + "solidity-va.tools.surya.option.negModifiers": { + "type": "boolean", + "default": false, + "description": "Surya.mdreport: Also list modifiers that are not present ( ~~strikedthrough~~). This may help catch issues relating to missing modifiers." + }, + "solidity-va.preview.dot": { + "type": "boolean", + "default": true, + "description": "Open dot output in graphviz rendered form (relies on a graphviz preview extension to be installed)" + }, + "solidity-va.preview.markdown": { + "type": "boolean", + "default": false, + "description": "Open markdown output in rendered form (relies on a markdown preview extension to be installed)" + }, + "solidity-va.codelens.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable all codelenses - inline action (master switch)" + }, + "solidity-va.codelens.report.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable codelens 'report'" + }, + "solidity-va.codelens.graph.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable codelens 'graph'" + }, + "solidity-va.codelens.graphThis.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable codelens 'graphThis'" + }, + "solidity-va.codelens.inheritance.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable codelens 'inheritance'" + }, + "solidity-va.codelens.parse.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable codelens 'parse'" + }, + "solidity-va.codelens.flatten.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable codelens 'report'" + }, + "solidity-va.codelens.funcSigs.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable codelens 'funcSigs'" + }, + "solidity-va.codelens.uml.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable codelens 'uml'" + }, + "solidity-va.codelens.unittestStub.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable codelens 'UnitTest Stub'" + }, + "solidity-va.codelens.dependencies.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable codelens 'report'" + }, + "solidity-va.codelens.ftrace.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable codelens 'ftrace'" + }, + "solidity-va.codelens.drawio.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable codelens 'draw.io' uml export" + }, + "solidity-va.findAllReferences.enable": { + "type": "boolean", + "default": true, + "description": "Enable/Disable right-click -> Find All References. Note: This allows you to disable the built-in reference provider in favor of one of another extension. Takes effect after restart." + }, + "solidity-va.mode.active": { + "type": "boolean", + "default": true, + "description": "Enable/Disable all active components of this extension (emergency)." + }, + "solidity-va.uml.options": { + "type": "text", + "default": "", + "description": "Add custom uml options" + }, + "solidity-va.uml.actors.enable": { + "type": "boolean", + "default": false, + "description": "Enable/Disable actors in uml" + }, + "solidity-va.cockpit.view.topLevelContracts.listStyle": { + "type": "string", + "enum": [ + "flat", + "tree" + ], + "default": "flat", + "description": "Select TopLevelContracts view list style." + }, + "solidity-va.whatsNew.disabled": { + "type": "boolean", + "default": false, + "description": "Enable/Disable update notifications" + }, + "solidity-va.test.defaultUnittestTemplate": { + "type": "string", + "enum": [ + "hardhat", + "truffle" + ], + "default": "truffle", + "description": "Select which default template to use when creating a unitTest stub (e.g. truffle, hardhat)" + }, + "solidity-va.debug.parser.showExceptions": { + "type": "boolean", + "default": false, + "description": "Enable/Disable printing parser error / stacktraces to console log (noisy)" + }, + "solidity-va.flatten.mode": { + "type": "string", + "enum": [ + "internal (lexical)", + "truffle" + ], + "default": "default", + "description": "Select which flattener to use (e.g. default=lexical flattener, truffle=truffle-flattener)" + } + } } + }, + "extensionDependencies": [ + "tintinweb.vscode-solidity-language", + "tintinweb.graphviz-interactive-preview" + ], + "extensionPack": [ + "tintinweb.vscode-solidity-flattener", + "jebbs.plantuml", + "tintinweb.vscode-inline-bookmarks", + "tintinweb.vscode-ethover" + ], + "scripts": { + "format": "prettier --write ." + }, + "dependencies": { + "solidity-workspace": "^0.2.1", + "surya": "^0.4.6" + }, + "devDependencies": { + "prettier": "^3.0.3" + } } diff --git a/src/extension.js b/src/extension.js index 51ae9fe..992247d 100644 --- a/src/extension.js +++ b/src/extension.js @@ -1,580 +1,410 @@ -'use strict'; -/** +"use strict"; +/** * @author github.com/tintinweb * @license GPLv3 - * - * + * + * * */ /** imports */ -const vscode = require('vscode'); -const { CancellationTokenSource } = require('vscode'); -const path = require('path'); - -//const mod_codelens = require('./features/codelens'); -const mod_hover = require('./features/hover'); -const mod_decorator = require('./features/deco'); -const { SolidityDocumentSymbolProvider, getAstValueForExpression } = require('./features/symbols'); -const mod_parser = require('solidity-workspace'); -const { DiliDiagnosticCollection } = require('./features/genericDiag'); -const { Commands } = require('./features/commands'); -const { SolidityCodeLensProvider } = require('./features/codelens'); -const settings = require('./settings'); -const { Cockpit } = require('./features/cockpit.js'); -const { SolidityReferenceProvider } = require('./features/references'); - -const { WhatsNewHandler } = require('./features/whatsnew/whatsNew'); +const vscode = require("vscode"); +const { CancellationTokenSource } = require("vscode"); +const path = require("path"); + +const mod_hover = require("./features/hover"); +const mod_decorator = require("./features/deco"); +const { + SolidityDocumentSymbolProvider, +} = require("./features/symbols"); +const mod_parser = require("solidity-workspace"); +const { DiliDiagnosticCollection } = require("./features/genericDiag"); +const { Commands } = require("./features/commands"); +const { + StaticLensProvider, + ParserLensProvider, +} = require("./features/codelens"); +const settings = require("./settings"); +const { Cockpit } = require("./features/cockpit.js"); +const { SolidityReferenceProvider } = require("./features/references"); + +const { WhatsNewHandler } = require("./features/whatsnew/whatsNew"); /** globals - const */ const languageId = settings.languageId; const docSelector = settings.docSelector; -const g_workspace = new mod_parser.Workspace(vscode.workspace.workspaceFolders.map(wf => wf.uri.fsPath)); +const g_workspace = new mod_parser.Workspace( + vscode.workspace.workspaceFolders.map((wf) => wf.uri.fsPath), +); var activeEditor; var g_diagnostics; - +var g_debounce = { + timerId: undefined, + armed: false, + wait: 500 +}; const currentCancellationTokens = { - onDidChange: new CancellationTokenSource(), - onDidSave: new CancellationTokenSource() + onDidChange: new CancellationTokenSource(), + onDidSave: new CancellationTokenSource(), }; - /** helper */ function editorJumptoRange(editor, range) { - let revealType = vscode.TextEditorRevealType.InCenter; - let selection = new vscode.Selection(range.start.line, range.start.character, range.end.line, range.end.character); - if (range.start.line === editor.selection.active.line) { - revealType = vscode.TextEditorRevealType.InCenterIfOutsideViewport; - } - - editor.selection = selection; - editor.revealRange(selection, revealType); -} - -async function setDecorations(editor, decorations) { - if (!editor) { - return; - } - let deco_map = {}; - - for (var styleKey in mod_decorator.styles) { - deco_map[styleKey] = []; - } - - decorations.forEach(function (deco) { - deco_map[deco.decoStyle].push(deco); - }); - - for (let styleKey in deco_map) { - editor.setDecorations(mod_decorator.styles[styleKey], deco_map[styleKey]); - } + let revealType = vscode.TextEditorRevealType.InCenter; + let selection = new vscode.Selection( + range.start.line, + range.start.character, + range.end.line, + range.end.character, + ); + if (range.start.line === editor.selection.active.line) { + revealType = vscode.TextEditorRevealType.InCenterIfOutsideViewport; + } + + editor.selection = selection; + editor.revealRange(selection, revealType); } - - /*** EVENTS *********************************************** */ function onInitModules(context, type) { - mod_decorator.init(context); + mod_decorator.init(context); - //globals init - g_diagnostics = new DiliDiagnosticCollection(context, vscode.workspace.rootPath); + //globals init + g_diagnostics = new DiliDiagnosticCollection( + context, + vscode.workspace.rootPath, + ); } -/** func decs */ - -function checkReservedIdentifiers(identifiers) { - let decorations = []; - if (!identifiers) { - return decorations; - } - - if (typeof identifiers.forEach !== "function") { - identifiers = Object.values(identifiers); - } - identifiers.forEach(function (ident) { - if (mod_parser.RESERVED_KEYWORDS.indexOf(ident.name) >= 0) { - decorations.push(mod_decorator.CreateDecoStyle.reserved(ident)); - } +function analyzeSourceUnit( + cancellationToken, + document, + editor, + initialLoad = false, + onFinished = () => {}, +) { + console.log("inspect ..."); + + if (!document) { + console.error("-BUG- cannot analyze empty document!"); + return; + } + + g_workspace + .add(document.fileName, + { content: document.getText(), cancellationToken: cancellationToken.token }) + .then((sourceUnit) => { + console.log(`✓ inspect ${sourceUnit.filePath} ${sourceUnit.hash}`); + }) + .catch((e) => { + console.warn( + `Error adding file or one of its dependencies to workspace (parser error): ${document.fileName}`, + ); + if (settings.extensionConfig().debug.parser.showExceptions) { + console.error(e); + } }); - return decorations; -} -function analyzeSourceUnit(cancellationToken, document, editor) { - console.log("inspect ..."); - if (!document) { - console.error("-BUG- cannot analyze empty document!"); + g_workspace + .withParserReady(document.fileName, initialLoad) + .then((finished) => { + console.log("✓ workspace ready (linearized, resolved deps, ..)"); + const wantHash = mod_parser.SourceUnit.getHash(document.getText()); + if ( + cancellationToken.isCancellationRequested || + !finished.some( + (fp) => fp.value && fp.value.filePath === document.fileName && fp.value.hash === wantHash, + ) + ) { + //abort - new analysis running already OR our finished task is not in the tasklist :/ + onFinished(); return; - } - - try { - g_workspace.add(document.fileName, { content: document.getText()}).then( - (sourceUnit) => { - console.log(`✓ inspect ${sourceUnit.filePath}`); - } - ).catch(e => { - console.warn(`Error adding file or one of its dependencies to workspace (parser error): ${document.fileName}`); - if(settings.extensionConfig().debug.parser.showExceptions){ - console.error(e); - } - }); - } catch (e){ - console.warn(`Error adding file or one of its dependencies to workspace (parser error): ${document.fileName}`); - if(settings.extensionConfig().debug.parser.showExceptions){ - console.error(e); - } - } - - - g_workspace.withParserReady().then((finished) => { - - console.log("✓ workspace ready (linearized, resolved deps, ..)"); - - if (cancellationToken.isCancellationRequested || !finished.some(fp => fp.value && fp.value.filePath === document.fileName)) { - //abort - new analysis running already OR our finished task is not in the tasklist :/ - return; - } - - let currentConfig = settings.extensionConfig(); - let shouldDecorate = currentConfig.deco.statevars || currentConfig.deco.arguments || currentConfig.deco.warn.reserved; - - if (shouldDecorate && editor) { - var decorations = []; - - let this_sourceUnit = g_workspace.get(document.fileName); - - console.log("+ (decorate) in sourceunit: " + this_sourceUnit.filePath); - - if (settings.extensionConfig().deco.warn.externalCalls) { - decorations = decorations.concat(this_sourceUnit.getExternalCalls().map(c => { - return mod_decorator.CreateDecoStyle.extCall(c._node); - })); - console.log("✓ highlight external calls"); - } - - - for (var contract of Object.values(this_sourceUnit.contracts)) { - console.log("+ in contract: " + contract.name); - console.log("resolve inheritance.."); - //merge all contracts into one - contract.linearizedDependencies.forEach(subcontract => { - if(!subcontract || typeof subcontract !== "object") { - console.error("ERROR - contract object not available " + contract.name); - return; - } - if (subcontract.name == contract.name) { - return; //skip self - } - if (subcontract._node.kind === "interface"){ - return; //skip inherited names from interfaces - } - - for (let _var in subcontract.stateVars) { - if (subcontract.stateVars[_var].visibility != "private") { - contract.inherited_names[_var] = subcontract; - } - } - for (let _var of subcontract.functions) { - if (_var._node.visibility != "private") { - contract.inherited_names[_var.name] = subcontract; - } - } - for (let _var of subcontract.events) { - if (_var._node.visibility != "private") { - contract.inherited_names[_var.name] = subcontract; - } - } - for (let _var in subcontract.modifiers) { - if (subcontract.modifiers[_var].visibility != "private") { - contract.inherited_names[_var] = subcontract; - } - } - for (let _var in subcontract.enums) { - if (subcontract.enums[_var].visibility != "private") { - contract.inherited_names[_var] = subcontract; - } - } - for (let _var in subcontract.structs) { - if (subcontract.structs[_var].visibility != "private") { - contract.inherited_names[_var] = subcontract; - } - } - for (let _var in subcontract.mappings) { - if (subcontract.mappings[_var].visibility != "private") { - contract.inherited_names[_var] = subcontract; - } - } - - }); - console.log("✓ resolve inheritance"); - - /** todo fixme: rework */ - if(currentConfig.deco.statevars) { - for (var stateVar in contract.stateVars) { - let svar = contract.stateVars[stateVar]; - //check for shadowing - decorations.push(mod_decorator.CreateDecoStyle.stateVarDecl(svar, document, contract)); - - /*** annotate all identifiers */ - //console.log(svar.usedAt) - svar.extra.usedAt.forEach(ident => { - //check shadow in local declaration - if (typeof ident.extra.inFunction.declarations[ident.name] == "undefined") { - // no local declaration. annotate as statevar - decorations.push(mod_decorator.CreateDecoStyle.stateVarIdent(ident, document, contract, svar)); - } else { - //shadowed! - console.log("SHADOWED STATEVAR --> " + ident.name); - decorations.push(mod_decorator.CreateDecoStyle.shadowedStateVar(ident, document, contract, svar)); - //declaration - let declaration = ident.extra.inFunction.declarations[ident.name]; - decorations.push(mod_decorator.CreateDecoStyle.shadowedStateVar(declaration, document, contract, svar)); - - } - }); - } - console.log("✓ decorate scope"); - - - /*** inherited vars */ - /** have to get all identifiers :// */ - /** fixme ugly hack ... */ - for (let func of contract.functions) { - //all functions - let highlightIdentifiers = []; - - func.identifiers.forEach(ident => { - if (ident.name === undefined) { - return; - } //skip assemblyCall has no attrib .name - // all idents in function - - const is_declared_locally = !!ident.extra.inFunction.declarations[ident.name]; - const is_state_var = !!contract.stateVars[ident.name]; - const is_inherited = !!(contract.inherited_names[ident.name] && contract.inherited_names[ident.name] != contract); - - if (is_declared_locally && !is_inherited && !is_state_var) { - // local declaration - switch (ident.extra.scope) { - case "argument": - case "super": - highlightIdentifiers.push(ident); - break; - case "returns": - case "body": - break; - case "storageRef": - decorations.push(mod_decorator.CreateDecoStyle.stateVarIdent(ident, document, contract, ident.extra.declaration)); - break; - case "stateVar": - console.log("!!!! shadowed statevar"); // handled in a previous loop already - break; - case "inheritedName": - console.log("!!!!! shadowed derived var"); - decorations.push(mod_decorator.CreateDecoStyle.shadowedInheritedStateVar(ident, document, contract)); - break; - default: - break; - } - } else if (is_declared_locally && is_inherited) { - console.log("!!!!! shadowed derived var"); - decorations.push(mod_decorator.CreateDecoStyle.shadowedInheritedStateVar(ident, document, contract)); - } else if (is_state_var && is_inherited) { - // no local declaration -> direct use of stateVar - //shadowed inherited var - console.log("!!! statevar shadows inherited"); - console.log("!!!!! shadowed derived var"); - decorations.push(mod_decorator.CreateDecoStyle.shadowedInheritedStateVar(ident, document, contract)); - } else if (is_inherited) { - // normal inherited var - decorations.push(mod_decorator.CreateDecoStyle.inheritedStateVar(ident, document, contract)); - } - //annotate external calls? - }); - if (settings.extensionConfig().deco.arguments) { - decorations = decorations.concat(mod_decorator.semanticHighlightFunctionParameters(highlightIdentifiers)); - } - - if (settings.extensionConfig().deco.warn.reserved) { - decorations = decorations.concat(checkReservedIdentifiers(func.identifiers)); - decorations = decorations.concat(checkReservedIdentifiers(func.arguments)); - decorations = decorations.concat(checkReservedIdentifiers(func.returns)); - } - } - //decorate modifiers (fixme copy pasta) - for (let functionName in contract.modifiers) { - //all modifiers - let highlightIdentifiers = []; - contract.modifiers[functionName].identifiers.forEach(ident => { - if (ident.name === undefined) { - return; - } //skip assemblyCall has no attrib .name - - const is_declared_locally = !!ident.extra.inFunction.declarations[ident.name]; - const is_state_var = !!contract.stateVars[ident.name]; - const is_inherited = !!(contract.inherited_names[ident.name] && contract.inherited_names[ident.name] != contract); - - if (is_declared_locally && !is_inherited && !is_state_var) { - // local declaration - switch (ident.extra.scope) { - case "argument": - highlightIdentifiers.push(ident); - break; - case "returns": - case "body": - break; - case "storageRef": - decorations.push(mod_decorator.CreateDecoStyle.stateVarIdent(ident, document, contract, ident.extra.declaration)); - break; - case "stateVar": - console.log("!!!! shadowed statevar"); // handled in a previous loop already - break; - case "inheritedName": - console.log("!!!!! shadowed derived var"); - decorations.push(mod_decorator.CreateDecoStyle.shadowedInheritedStateVar(ident, document, contract)); - break; - default: - break; - } - } else if (is_declared_locally && is_inherited) { - console.log("!!!!! shadowed derived var"); - decorations.push(mod_decorator.CreateDecoStyle.shadowedInheritedStateVar(ident, document, contract)); - } else if (is_state_var && is_inherited) { - // no local declaration -> direct use of stateVar - //shadowed inherited var - console.log("!!! statevar shadows inherited"); - console.log("!!!!! shadowed derived var"); - decorations.push(mod_decorator.CreateDecoStyle.shadowedInheritedStateVar(ident, document, contract)); - } else if (is_inherited) { - // normal inherited var - decorations.push(mod_decorator.CreateDecoStyle.inheritedStateVar(ident, document, contract)); - } - - //annotate external calls? - }); - if (settings.extensionConfig().deco.arguments ) { - decorations = decorations.concat(mod_decorator.semanticHighlightFunctionParameters(highlightIdentifiers)); - } - - if (settings.extensionConfig().deco.warn.reserved) { - decorations = decorations.concat(checkReservedIdentifiers(contract.modifiers[functionName].identifiers)); - decorations = decorations.concat(checkReservedIdentifiers(contract.modifiers[functionName].arguments)); - decorations = decorations.concat(checkReservedIdentifiers(contract.modifiers[functionName].returns)); - } - - } - //decorate events - for (var eventDef of contract.events) { - if (settings.extensionConfig().deco.warn.reserved) { - decorations = decorations.concat(checkReservedIdentifiers(eventDef.arguments)); - } - } - console.log("✓ decorate scope (new) - identifier "); - } - } - console.log("✓ decorate scope done "); - if (cancellationToken.isCancellationRequested) { - //abort - new analysis running already - return; - } - - - setDecorations(editor, decorations); - console.log("✓ apply decorations - scope"); - } - console.log("✓ analyzeSourceUnit - done"); - + } + + let currentConfig = settings.extensionConfig(); + let shouldDecorate = + currentConfig.deco.statevars || + currentConfig.deco.arguments || + currentConfig.deco.warn.reserved; + + if (shouldDecorate && editor) { + let this_sourceUnit = g_workspace.get(document.fileName); + mod_decorator.decorateSourceUnit(document, editor, this_sourceUnit); + //decorate + } + onFinished(); + console.log("✓ analyzeSourceUnit - done"); }); } /** events */ function onDidSave(document) { - currentCancellationTokens.onDidSave.dispose(); - currentCancellationTokens.onDidSave = new CancellationTokenSource(); - // check if there are any - if (settings.extensionConfig().diagnostics.cdili_json.import && g_diagnostics) { - g_diagnostics.updateIssues(currentCancellationTokens.onDidSave.token); - } + currentCancellationTokens.onDidSave.dispose(); + currentCancellationTokens.onDidSave = new CancellationTokenSource(); + // check if there are any + if ( + settings.extensionConfig().diagnostics.cdili_json.import && + g_diagnostics + ) { + g_diagnostics.updateIssues(currentCancellationTokens.onDidSave.token); + } +} + +function debounce(target){ + if(!g_debounce.armed){ + // unarmed: first time use + g_debounce.armed = true; // arm for next run to enable debounce + setTimeout(() => { + target(); + }, 0); + } else { + // armed: debounce next calls + clearTimeout(g_debounce.timerId) // clear timer & schedule new + g_debounce.timerId = setTimeout(() => { + target(); + }, g_debounce.wait); + } } -function onDidChange(editor) { - let document = editor && editor.document ? editor.document : vscode.window.activeTextEditor ? vscode.window.activeTextEditor.document : undefined; - if (!document) { - console.warn("change event on non-document"); - return; - } - if (document.languageId != languageId) { - console.log("ondidchange: wrong langid"); - return; - } - currentCancellationTokens.onDidChange.dispose(); - currentCancellationTokens.onDidChange = new CancellationTokenSource(); +function refresh(editor, initialLoad = false) { + let document = + editor && editor.document + ? editor.document + : vscode.window.activeTextEditor + ? vscode.window.activeTextEditor.document + : undefined; + if (!document) { + console.warn("change event on non-document"); + return; + } + if (document.languageId != languageId) { + console.log("ondidchange: wrong langid"); + return; + } + currentCancellationTokens.onDidChange.cancel(); + currentCancellationTokens.onDidChange = new CancellationTokenSource(); + + debounce(() => { console.log("--- on-did-change"); try { - analyzeSourceUnit(currentCancellationTokens.onDidChange.token, document, editor); - } catch (err) { - if (typeof err !== "object") { //CancellationToken - throw err; + analyzeSourceUnit( + currentCancellationTokens.onDidChange, + document, + editor, + initialLoad, + /* onFinished */ () => { + // cleanup + g_debounce.armed = false; // unarm debounce + g_debounce.timerId = undefined; } + ); + } catch (err) { + if (typeof err !== "object") { + //CancellationToken + throw err; + } } - console.log("✓✓✓ on-did-change - resolved"); + }); + + } -function onActivate(context) { +function onDidChange(editor) { + refresh(editor); +} - activeEditor = vscode.window.activeTextEditor; +function onActivate(context) { + activeEditor = vscode.window.activeTextEditor; - console.log("onActivate"); + console.log("onActivate"); - registerDocType(languageId, docSelector); + registerDocType(languageId, docSelector); - new WhatsNewHandler().show(context); + new WhatsNewHandler().show(context); - async function registerDocType(type, docSel) { - context.subscriptions.push( - vscode.languages.reg - ); + async function registerDocType(type, docSel) { + context.subscriptions.push(vscode.languages.reg); - if (!settings.extensionConfig().mode.active) { - console.log("ⓘ activate extension: entering passive mode. not registering any active code augmentation support."); - return; - } - /** module init */ - onInitModules(context, type); - onDidChange(); - - let commands = new Commands(g_workspace); - let cockpit = new Cockpit(commands); - - /** command setup */ - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.whatsNew.show', - function () { - new WhatsNewHandler().showMessage(context); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.test.createTemplate', - function (doc, contractName) { - commands.generateUnittestStubForContract(doc || vscode.window.activeTextEditor.document, contractName); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.surya.mdreport', - function (doc, multiSelectTreeItems) { - doc = multiSelectTreeItems || doc; - commands.surya(doc || vscode.window.activeTextEditor.document, "mdreport"); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.surya.graph', - function (doc, files) { - if (files && typeof files[0] === "object" && files[0].hasOwnProperty("children")) { - //treeItem or fspaths - doc = files; - files = undefined; - } - commands.surya(doc || vscode.window.activeTextEditor.document, "graph", files); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.surya.graphThis', - function () { - commands.surya(vscode.window.activeTextEditor.document, "graph", [vscode.window.activeTextEditor.document.uri.fsPath]); - } - ) - ); - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.surya.graphSimple', - function (doc, files) { - if (files && typeof files[0] === "object" && files[0].hasOwnProperty("children")) { - //treeItem or fspaths - doc = files; - files = undefined; - } - commands.surya(doc || vscode.window.activeTextEditor.document, "graphSimple", files); - } - ) - ); - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.surya.inheritance', - function (doc, multiSelectTreeItems) { - doc = multiSelectTreeItems || doc; - commands.surya(doc || vscode.window.activeTextEditor.document, "inheritance"); - } - ) - ); - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.surya.parse', - function (doc) { - commands.surya(doc || vscode.window.activeTextEditor.document, "parse"); - } - ) - ); - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.surya.dependencies', - function (doc, ContractName) { - commands.surya(doc || vscode.window.activeTextEditor.document, "dependencies", [ContractName]); - } - ) - ); - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.surya.ftrace', - function (doc, contractName, functionName, mode) { - commands.surya(doc || vscode.window.activeTextEditor.document, "ftrace", [contractName, functionName, mode]); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.insights.topLevelContracts', - function () { - commands.findTopLevelContracts(); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.tools.flaterra', - function (doc) { - commands.solidityFlattener([doc && doc.uri || vscode.window.activeTextEditor.document.uri]); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.cockpit.explorer.context.flatten', - async function (treeItem, multiSelectTreeItems) { - multiSelectTreeItems = multiSelectTreeItems || []; - [...multiSelectTreeItems, treeItem].forEach(async treeItem => { - commands.solidityFlattener([treeItem.resource]); - /* + if (!settings.extensionConfig().mode.active) { + console.log( + "ⓘ activate extension: entering passive mode. not registering any active code augmentation support.", + ); + return; + } + /** module init */ + onInitModules(context, type); + refresh(activeEditor, true); + + let commands = new Commands(g_workspace); + let cockpit = new Cockpit(commands); + + /** command setup */ + context.subscriptions.push( + vscode.commands.registerCommand("solidity-va.whatsNew.show", function () { + new WhatsNewHandler().showMessage(context); + }), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.test.createTemplate", + function (doc, contractName) { + commands.generateUnittestStubForContract( + doc || vscode.window.activeTextEditor.document, + contractName, + ); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.surya.mdreport", + function (doc, multiSelectTreeItems) { + doc = multiSelectTreeItems || doc; + commands.surya( + doc || vscode.window.activeTextEditor.document, + "mdreport", + ); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.surya.graph", + function (doc, files) { + if ( + files && + typeof files[0] === "object" && + files[0].hasOwnProperty("children") + ) { + //treeItem or fspaths + doc = files; + files = undefined; + } + commands.surya( + doc || vscode.window.activeTextEditor.document, + "graph", + files, + ); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.surya.graphThis", + function () { + commands.surya(vscode.window.activeTextEditor.document, "graph", [ + vscode.window.activeTextEditor.document.uri.fsPath, + ]); + }, + ), + ); + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.surya.graphSimple", + function (doc, files) { + if ( + files && + typeof files[0] === "object" && + files[0].hasOwnProperty("children") + ) { + //treeItem or fspaths + doc = files; + files = undefined; + } + commands.surya( + doc || vscode.window.activeTextEditor.document, + "graphSimple", + files, + ); + }, + ), + ); + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.surya.inheritance", + function (doc, multiSelectTreeItems) { + doc = multiSelectTreeItems || doc; + commands.surya( + doc || vscode.window.activeTextEditor.document, + "inheritance", + ); + }, + ), + ); + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.surya.parse", + function (doc) { + commands.surya( + doc || vscode.window.activeTextEditor.document, + "parse", + ); + }, + ), + ); + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.surya.dependencies", + function (doc, ContractName) { + commands.surya( + doc || vscode.window.activeTextEditor.document, + "dependencies", + [ContractName], + ); + }, + ), + ); + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.surya.ftrace", + function (doc, contractName, functionName, mode) { + commands.surya( + doc || vscode.window.activeTextEditor.document, + "ftrace", + [contractName, functionName, mode], + ); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.insights.topLevelContracts", + function () { + commands.findTopLevelContracts(); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.tools.flaterra", + function (doc) { + commands.solidityFlattener([ + (doc && doc.uri) || vscode.window.activeTextEditor.document.uri, + ]); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.cockpit.explorer.context.flatten", + async function (treeItem, multiSelectTreeItems) { + multiSelectTreeItems = multiSelectTreeItems || []; + [...multiSelectTreeItems, treeItem].forEach(async (treeItem) => { + commands.solidityFlattener([treeItem.resource]); + /* await vscode.extensions .getExtension('tintinweb.vscode-solidity-flattener') .activate() @@ -585,216 +415,297 @@ function onActivate(context) { .then(async (done) => { }); }); */ - }); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.tools.flattenCandidates', - function () { - commands.flattenCandidates(); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.cockpit.topLevelContracts.flatten', - function () { - let sourceFiles = cockpit.views.topLevelContracts.dataProvider.data.reduce(function (obj, item) { - obj[path.basename(item.path, ".sol")] = vscode.Uri.file(item.path); - return obj; - }, {}); - commands.flattenCandidates(sourceFiles); - cockpit.views.flatFiles.refresh(); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.tools.function.signatures', - function (doc, asJson) { - commands.listFunctionSignatures(doc || vscode.window.activeTextEditor.document, asJson); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.tools.function.signatures.json', - function (doc) { - commands.listFunctionSignatures(doc || vscode.window.activeTextEditor.document, true); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.tools.function.signatures.forWorkspace.json', - function (doc) { - commands.listFunctionSignaturesForWorkspace(true); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.tools.function.signatureForAstItem', - function (item) { - commands.listFunctionSignatureForAstItem(item); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.tools.remix.openExternal', - function () { - vscode.env.openExternal(vscode.Uri.parse("https://remix.ethereum.org")); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.uml.contract.outline', - function (doc, contractObjects) { - commands.umlContractsOutline(contractObjects); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - 'solidity-va.uml.contract.export.drawio.csv', - function (doc, contractObjects) { - commands.drawioContractsOutlineAsCSV(contractObjects); - } - ) - ); - - context.subscriptions.push( - vscode.commands.registerCommand("solidity-va.cockpit.topLevelContracts.refresh", async (treeItem, multiSelectTreeItems) => { - if (multiSelectTreeItems) { - cockpit.views.topLevelContracts.refresh(multiSelectTreeItems.filter(t => !t.path.endsWith(".sol")).map(t => t.path)); - } else { - cockpit.views.topLevelContracts.refresh(treeItem && treeItem.path); - } - }) - ); - - context.subscriptions.push( - vscode.commands.registerCommand("solidity-va.cockpit.explorer.refresh", async () => { - cockpit.views.explorer.refresh(); - }) - ); - - context.subscriptions.push( - vscode.commands.registerCommand("solidity-va.cockpit.flatFiles.refresh", async () => { - cockpit.views.flatFiles.refresh(); - }) - ); - - context.subscriptions.push( - vscode.commands.registerCommand("solidity-va.cockpit.jumpToRange", (documentUri, range) => { - vscode.workspace.openTextDocument(documentUri).then(doc => { - vscode.window.showTextDocument(doc).then(editor => { - if (range) { - editorJumptoRange(editor, range); - } - }); - }); - }) - ); - - context.subscriptions.push( - vscode.commands.registerCommand("solidity-va.cockpit.settings.toggle", async (treeItem) => { - let cfg = vscode.workspace.getConfiguration(treeItem.metadata.extension); - let current = cfg.get(treeItem.metadata.section); - await cfg.update(treeItem.metadata.section, !current); - cockpit.views.settings.refresh(); - }) - ); - - /** event setup */ - /***** DidChange */ - vscode.window.onDidChangeActiveTextEditor(editor => { - activeEditor = editor; - if (editor && editor.document && editor.document.languageId == type) { - onDidChange(editor); - } - }, null, context.subscriptions); - vscode.workspace.onDidChangeTextDocument(event => { - if (activeEditor && event.document === activeEditor.document && event.document.languageId == type) { - onDidChange(activeEditor); - } - }, null, context.subscriptions); - - /***** OnSave */ - vscode.workspace.onDidSaveTextDocument(document => { - onDidSave(document); - }, null, context.subscriptions); - - /****** OnOpen */ - vscode.workspace.onDidOpenTextDocument(document => { - onDidSave(document); - }, null, context.subscriptions); - - /****** onDidChangeTextEditorSelection */ - vscode.window.onDidChangeTextEditorSelection(event /* TextEditorVisibleRangesChangeEvent */ => { - cockpit.onDidSelectionChange(event); // let cockpit handle the event - }, null, context.subscriptions); - - - context.subscriptions.push( - vscode.languages.registerHoverProvider(type, { - provideHover(document, position, token) { - return mod_hover.provideHoverHandler(document, position, token, type, g_workspace); - } - }) - ); - - /** experimental */ - if (settings.extensionConfig().outline.enable) { - context.subscriptions.push( - vscode.languages.registerDocumentSymbolProvider( - docSel, - new SolidityDocumentSymbolProvider(g_workspace, analyzeSourceUnit/* TODO hack hack hack move the inheritance part to parser*/) - ) + }); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.tools.flattenCandidates", + function () { + commands.flattenCandidates(); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.cockpit.topLevelContracts.flatten", + function () { + let sourceFiles = + cockpit.views.topLevelContracts.dataProvider.data.reduce(function ( + obj, + item, + ) { + obj[path.basename(item.path, ".sol")] = vscode.Uri.file( + item.path, + ); + return obj; + }, {}); + commands.flattenCandidates(sourceFiles); + cockpit.views.flatFiles.refresh(); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.tools.function.signatures", + function (doc, asJson) { + commands.listFunctionSignatures( + doc || vscode.window.activeTextEditor.document, + asJson, + ); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.tools.function.signatures.json", + function (doc) { + commands.listFunctionSignatures( + doc || vscode.window.activeTextEditor.document, + true, + ); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.tools.function.signatures.forWorkspace", + function (doc) { + commands.listFunctionSignaturesForWorkspace(false); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.tools.function.signatures.forWorkspace.json", + function (doc) { + commands.listFunctionSignaturesForWorkspace(true); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.tools.function.signatureForAstItem", + function (item) { + commands.signatureForAstItem(item); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.tools.remix.openExternal", + function () { + vscode.env.openExternal( + vscode.Uri.parse("https://remix.ethereum.org"), + ); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.uml.contract.outline", + function (doc, contractObjects) { + commands.umlContractsOutline(contractObjects); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.uml.contract.export.drawio.csv", + function (doc, contractObjects) { + commands.drawioContractsOutlineAsCSV(contractObjects); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.cockpit.topLevelContracts.refresh", + async (treeItem, multiSelectTreeItems) => { + if (multiSelectTreeItems) { + cockpit.views.topLevelContracts.refresh( + multiSelectTreeItems + .filter((t) => !t.path.endsWith(".sol")) + .map((t) => t.path), ); + } else { + cockpit.views.topLevelContracts.refresh(treeItem && treeItem.path); + } + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.cockpit.explorer.refresh", + async () => { + cockpit.views.explorer.refresh(); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.cockpit.flatFiles.refresh", + async () => { + cockpit.views.flatFiles.refresh(); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.cockpit.jumpToRange", + (documentUri, range) => { + vscode.workspace.openTextDocument(documentUri).then((doc) => { + vscode.window.showTextDocument(doc).then((editor) => { + if (range) { + editorJumptoRange(editor, range); + } + }); + }); + }, + ), + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + "solidity-va.cockpit.settings.toggle", + async (treeItem) => { + let cfg = vscode.workspace.getConfiguration( + treeItem.metadata.extension, + ); + let current = cfg.get(treeItem.metadata.section); + await cfg.update(treeItem.metadata.section, !current); + cockpit.views.settings.refresh(); + }, + ), + ); + + /** event setup */ + /***** DidChange */ + vscode.window.onDidChangeActiveTextEditor( + (editor) => { + activeEditor = editor; + if (editor && editor.document && editor.document.languageId == type) { + onDidChange(editor); } - - if (settings.extensionConfig().codelens.enable) { - context.subscriptions.push( - vscode.languages.registerCodeLensProvider( - docSel, - new SolidityCodeLensProvider(g_workspace, analyzeSourceUnit) - ) - ); + }, + null, + context.subscriptions, + ); + vscode.workspace.onDidChangeTextDocument( + (event) => { + if ( + activeEditor && + event.contentChanges.length > 0 && // only redecorate when there are content changes + event.document === activeEditor.document && + event.document.languageId == type + ) { + onDidChange(activeEditor) } + }, + null, + context.subscriptions, + ); + + /***** OnSave */ + vscode.workspace.onDidSaveTextDocument( + (document) => { + onDidSave(document); + }, + null, + context.subscriptions, + ); + + /****** OnOpen */ + vscode.workspace.onDidOpenTextDocument( + (document) => { + onDidSave(document); + }, + null, + context.subscriptions, + ); + + /****** onDidChangeTextEditorSelection */ + vscode.window.onDidChangeTextEditorSelection( + (event) /* TextEditorVisibleRangesChangeEvent */ => { + cockpit.onDidSelectionChange(event); // let cockpit handle the event + }, + null, + context.subscriptions, + ); + + context.subscriptions.push( + vscode.languages.registerHoverProvider(type, { + provideHover(document, position, token) { + return mod_hover.provideHoverHandler( + document, + position, + token, + type, + g_workspace, + ); + }, + }), + ); + + /** experimental */ + if (settings.extensionConfig().outline.enable) { + context.subscriptions.push( + vscode.languages.registerDocumentSymbolProvider( + docSel, + new SolidityDocumentSymbolProvider(g_workspace), + ), + ); + } - if (settings.extensionConfig().findAllReferences.enable) { - context.subscriptions.push( - vscode.languages.registerReferenceProvider( - docSel, - new SolidityReferenceProvider() - ) - ); - } + if (settings.extensionConfig().codelens.enable) { + context.subscriptions.push( + vscode.languages.registerCodeLensProvider( + docSel, + new StaticLensProvider(g_workspace), + ), + ); + + context.subscriptions.push( + vscode.languages.registerCodeLensProvider( + docSel, + new ParserLensProvider(g_workspace), + ), + ); + } - /** - * trigger decorations for visible editors - */ - vscode.window.visibleTextEditors.map(editor => { - if (editor && editor.document && editor.document.languageId == type) { - onDidChange(editor); - } - }); + if (settings.extensionConfig().findAllReferences.enable) { + context.subscriptions.push( + vscode.languages.registerReferenceProvider( + docSel, + new SolidityReferenceProvider(), + ), + ); } + + /** + * trigger decorations for visible editors + */ + vscode.window.visibleTextEditors.map((editor) => { + if (editor && editor.document && editor.document.languageId == type) { + onDidChange(editor); + } + }); + } } /* exports */ -exports.activate = onActivate; \ No newline at end of file +exports.activate = onActivate; diff --git a/src/features/cockpit.js b/src/features/cockpit.js index e36d910..e496976 100644 --- a/src/features/cockpit.js +++ b/src/features/cockpit.js @@ -1,267 +1,277 @@ -'use strict'; -/** +"use strict"; +/** * @author github.com/tintinweb * @license GPLv3 - * - * + * + * * */ -const vscode = require('vscode'); -const settings = require('../settings.js'); -const surya = require('surya'); -const path = require('path'); -const fs = require('fs'); - -function elemLocToRange(elem){ - return new vscode.Range( - new vscode.Position(elem.loc.start.line-1, elem.loc.start.column), - new vscode.Position(elem.loc.end.line-1, elem.loc.end.column) - ); +const vscode = require("vscode"); +const settings = require("../settings.js"); +const surya = require("surya"); +const path = require("path"); +const fs = require("fs"); + +function elemLocToRange(elem) { + return new vscode.Range( + new vscode.Position(elem.loc.start.line - 1, elem.loc.start.column), + new vscode.Position(elem.loc.end.line - 1, elem.loc.end.column), + ); } -function elemLocToFirstLineRange(elem){ - return new vscode.Range( - new vscode.Position(elem.loc.start.line-1, elem.loc.start.column), - new vscode.Position(elem.loc.start.line-1, elem.loc.start.column) - ); +function elemLocToFirstLineRange(elem) { + return new vscode.Range( + new vscode.Position(elem.loc.start.line - 1, elem.loc.start.column), + new vscode.Position(elem.loc.start.line - 1, elem.loc.start.column), + ); } -function nodeTypeName(node){ - if(!node.typeName && node.type==="Identifier"){ - return node.name; - } - return node.typeName.type === "ElementaryTypeName" ? node.typeName.name : node.typeName.namePath; +function nodeTypeName(node) { + if (!node.typeName && node.type === "Identifier") { + return node.name; + } + return node.typeName.type === "ElementaryTypeName" + ? node.typeName.name + : node.typeName.namePath; } - /** views */ class BaseView { - async refresh(value) { - this.treeView.message = undefined; // clear the treeview message - return this.dataProvider.refresh(value); - } - async onDidSelectionChange(event) { } + async refresh(value) { + this.treeView.message = undefined; // clear the treeview message + return this.dataProvider.refresh(value); + } + async onDidSelectionChange(event) {} } class BaseDataProvider { - async dataGetRoot() { - return []; - } - - dataGetChildren(element) { - return null; - } - - /** tree methods */ - getChildren(element) { - return element ? this.dataGetChildren(element) : this.dataGetRoot(); - } - - getParent(element) { - return element.parent; - } - - getTreeItem(element) { - let ret = new vscode.TreeItem(element.label, element.collapsibleState); - ret.resourceUri = element.resource; - ret.iconPath = element.iconPath; - ret.children = element.children; - ret.command = element.command || { - command: 'solidity-va.cockpit.jumpToRange', - arguments: [element.resource], - title: 'JumpTo' - } - return ret; - } - - /** other methods */ - refresh() { - return new Promise((resolve, reject) => { - this._onDidChangeTreeData.fire(); - resolve(); - }); - } + async dataGetRoot() { + return []; + } + + dataGetChildren(element) { + return null; + } + + /** tree methods */ + getChildren(element) { + return element ? this.dataGetChildren(element) : this.dataGetRoot(); + } + + getParent(element) { + return element.parent; + } + + getTreeItem(element) { + let ret = new vscode.TreeItem(element.label, element.collapsibleState); + ret.resourceUri = element.resource; + ret.iconPath = element.iconPath; + ret.children = element.children; + + ret.command = element.command || { + command: "solidity-va.cockpit.jumpToRange", + arguments: [element.resource], + title: "JumpTo", + }; + + return ret; + } + + /** other methods */ + refresh() { + return new Promise((resolve, reject) => { + this._onDidChangeTreeData.fire(); + resolve(); + }); + } } /** Generic Data Provider */ /* helper */ class FilePathTreeDataProvider extends BaseDataProvider { - constructor(listStyle, separator) { - super(); - this.listStyle = listStyle; - this._separator = separator || path.sep; - this.data = []; - } - - async dataGetRoot() { - return this.data; + constructor(listStyle, separator) { + super(); + this.listStyle = listStyle; + this._separator = separator || path.sep; + this.data = []; + } + + async dataGetRoot() { + return this.data; + } + + dataGetChildren(element) { + if (!element) { + return this.data; } - - dataGetChildren(element) { - if (!element) { - return this.data; + // element provided? - + return element.children; + } + + dataGetParent(element) { + return element.parent; + } + + _addPathTree(uri) { + //strip workspace path + let workspacePath = vscode.workspace.getWorkspaceFolder(uri).uri.fsPath; + let pathSegments = path + .relative(workspacePath, uri.fsPath) + .split(this._separator); + let parent = this.data; + + for (let idx = 0; idx < pathSegments.length; idx++) { + let name = pathSegments[idx]; + if (name == "") { + continue; + } + let pathObj = parent.find((p) => p.name == name); + + if (!pathObj) { + //create a new one + let _path = pathSegments.slice(0, idx + 1).join(this._separator); + let _abspath = path.join(workspacePath, _path); + let _type = FilePathTreeDataProvider.TYPE_FILE; + try { + _type = fs.lstatSync(_abspath).isDirectory() + ? FilePathTreeDataProvider.TYPE_DIRECTORY + : FilePathTreeDataProvider.TYPE_FILE; + } catch (err) { + console.warn(err); //fallback to type file } - // element provided? - - return element.children; - } - dataGetParent(element) { - return element.parent; + pathObj = { + name: name, + path: _path, + resource: vscode.Uri.file(_abspath), + children: [], + parent: parent, + type: _type, + workspace: workspacePath, + collapsibleState: + _type === FilePathTreeDataProvider.TYPE_DIRECTORY + ? vscode.TreeItemCollapsibleState.Collapsed + : 0, + }; + parent.push(pathObj); + } + parent = pathObj.children; } - - _addPathTree(uri) { - //strip workspace path - let workspacePath = vscode.workspace.getWorkspaceFolder(uri).uri.fsPath; - let pathSegments = path.relative(workspacePath, uri.fsPath).split(this._separator); - let parent = this.data; - - for (let idx = 0; idx < pathSegments.length; idx++) { - let name = pathSegments[idx]; - if (name == "") { - continue; - } - let pathObj = parent.find(p => p.name == name); - - if (!pathObj) { - //create a new one - let _path = pathSegments.slice(0, idx + 1).join(this._separator); - let _abspath = path.join(workspacePath, _path); - let _type = FilePathTreeDataProvider.TYPE_FILE; - try { - _type = fs.lstatSync(_abspath).isDirectory() ? FilePathTreeDataProvider.TYPE_DIRECTORY : FilePathTreeDataProvider.TYPE_FILE; - } catch (err) { - console.warn(err); //fallback to type file - } - - pathObj = { - name: name, - path: _path, - resource: vscode.Uri.file(_abspath), - children: [], - parent: parent, - type: _type, - workspace: workspacePath, - collapsibleState: _type === FilePathTreeDataProvider.TYPE_DIRECTORY ? vscode.TreeItemCollapsibleState.Collapsed : 0, - }; - parent.push(pathObj); - } - parent = pathObj.children; - } + } + + _addPathFlat(uri) { + let pathSegments = uri.fsPath.split(this._separator); + let workspacePath = vscode.workspace.getWorkspaceFolder(uri).uri.fsPath; + this.data.push({ + name: pathSegments[pathSegments.length - 1], + path: uri.fsPath, + resource: uri, + children: [], + parent: null, + type: FilePathTreeDataProvider.TYPE_FILE, + workspace: workspacePath, + collapsibleState: 0, + }); + } + + addPath(uri) { + if (uri.scheme === undefined) { + uri = vscode.Uri.file(uri); } - - _addPathFlat(uri) { - let pathSegments = uri.fsPath.split(this._separator); - let workspacePath = vscode.workspace.getWorkspaceFolder(uri).uri.fsPath; - this.data.push( - { - name: pathSegments[pathSegments.length - 1], - path: uri.fsPath, - resource: uri, - children: [], - parent: null, - type: FilePathTreeDataProvider.TYPE_FILE, - workspace: workspacePath, - collapsibleState: 0, - } - ); - } - - addPath(uri) { - if (uri.scheme === undefined) { - uri = vscode.Uri.file(uri); - } - if (this.listStyle === "flat") { - this._addPathFlat(uri); - } else { - this._addPathTree(uri); - } + if (this.listStyle === "flat") { + this._addPathFlat(uri); + } else { + this._addPathTree(uri); } + } - load(paths) { - this.data = []; - for (let p of paths) { - this.addPath(p); - } + load(paths) { + this.data = []; + for (let p of paths) { + this.addPath(p); } + } } FilePathTreeDataProvider.TYPE_DIRECTORY = 1; FilePathTreeDataProvider.TYPE_FILE = 2; class VirtualPathTreeDataProvider extends FilePathTreeDataProvider { - - _addPathTree(s, metadata) { - //strip workspace path - let pathSegments = s.split(this._separator); - let parent = this.data; - - for (let idx = 0; idx < pathSegments.length; idx++) { - let name = pathSegments[idx]; - if (name == "") { - continue; - } - var pathObj = parent.find(p => p.name == name); - - if (!pathObj) { - //create a new one - let _path = pathSegments.slice(0, idx + 1).join(this._separator); - let _type = idx == pathSegments.length - 1 ? VirtualPathTreeDataProvider.TYPE_LEAF : VirtualPathTreeDataProvider.TYPE_NODE; - pathObj = { - name: name, - path: _path, - label: name, - metadata: metadata, - resource: null, - children: [], - parent: parent, - type: _type, - collapsibleState: _type == VirtualPathTreeDataProvider.TYPE_LEAF ? 0 : vscode.TreeItemCollapsibleState.Collapsed, - }; - parent.push(pathObj); - } - parent = pathObj.children; - } - } - - _addPathFlat(s, metadata) { - let pathSegments = s.split(this._separator); - this.data.push( - { - name: pathSegments[pathSegments.length - 1], - path: s, - label: s, - metadata: metadata, - resource: null, - children: [], - parent: null, - type: VirtualPathTreeDataProvider.TYPE_LEAF, - collapsibleState: 0, - } - ); + _addPathTree(s, metadata) { + //strip workspace path + let pathSegments = s.split(this._separator); + let parent = this.data; + + for (let idx = 0; idx < pathSegments.length; idx++) { + let name = pathSegments[idx]; + if (name == "") { + continue; + } + var pathObj = parent.find((p) => p.name == name); + + if (!pathObj) { + //create a new one + let _path = pathSegments.slice(0, idx + 1).join(this._separator); + let _type = + idx == pathSegments.length - 1 + ? VirtualPathTreeDataProvider.TYPE_LEAF + : VirtualPathTreeDataProvider.TYPE_NODE; + pathObj = { + name: name, + path: _path, + label: name, + metadata: metadata, + resource: null, + children: [], + parent: parent, + type: _type, + collapsibleState: + _type == VirtualPathTreeDataProvider.TYPE_LEAF + ? 0 + : vscode.TreeItemCollapsibleState.Collapsed, + }; + parent.push(pathObj); + } + parent = pathObj.children; } - - addPath(s, metadata) { - if (this.listStyle === "flat") { - this._addPathFlat(s, metadata); - } else { - this._addPathTree(s, metadata); - } + } + + _addPathFlat(s, metadata) { + let pathSegments = s.split(this._separator); + this.data.push({ + name: pathSegments[pathSegments.length - 1], + path: s, + label: s, + metadata: metadata, + resource: null, + children: [], + parent: null, + type: VirtualPathTreeDataProvider.TYPE_LEAF, + collapsibleState: 0, + }); + } + + addPath(s, metadata) { + if (this.listStyle === "flat") { + this._addPathFlat(s, metadata); + } else { + this._addPathTree(s, metadata); } - - load(paths) { - this.data = []; - - if (Array.isArray(paths)) { - for (let p of paths) { - this.addPath(p); - } - } else { - for (let p of Object.keys(paths)) { - this.addPath(p, paths[p]); - } - } - + } + + load(paths) { + this.data = []; + + if (Array.isArray(paths)) { + for (let p of paths) { + this.addPath(p); + } + } else { + for (let p of Object.keys(paths)) { + this.addPath(p, paths[p]); + } } + } } VirtualPathTreeDataProvider.TYPE_NODE = 1; VirtualPathTreeDataProvider.TYPE_LEAF = 2; @@ -269,689 +279,799 @@ VirtualPathTreeDataProvider.TYPE_LEAF = 2; /* TopLevelContracts View */ class TopLevelContractsViewDataProvider extends FilePathTreeDataProvider { - - constructor(treeView) { - super(settings.extensionConfig().cockpit.view.topLevelContracts.listStyle); - this.treeView = treeView; - this._onDidChangeTreeData = new vscode.EventEmitter(); - this.onDidChangeTreeData = this._onDidChangeTreeData.event; - - this.data = null; - } - - async dataGetRoot() { - return this.data || []; - } - - /** events */ - - /** tree methods */ - // inherited. - - getTreeItem(element) { - let ret = new vscode.TreeItem(element.label, element.collapsibleState); - ret.resourceUri = element.resource; - ret.iconPath = element.iconPath; - ret.command = element.type === FilePathTreeDataProvider.TYPE_FILE ? { - command: 'solidity-va.cockpit.jumpToRange', - arguments: [element.resource], - title: 'JumpTo' - } : 0; - return ret; - } - - /** other methods */ - refresh(workspaceRelativeBaseDir) { - return new Promise((resolve, reject) => { - this.treeView.cockpit.commands._findTopLevelContracts(undefined, undefined, workspaceRelativeBaseDir).then(data => { - this.load(Object.values(data).sort((a, b) => { - a = a.path.split('/').pop(); - b = b.path.split('/').pop(); - if (a == b) { return 0; } - return a < b ? -1 : 1; - }) - ); - this._onDidChangeTreeData.fire(); - resolve(); - }); + constructor(treeView) { + super(settings.extensionConfig().cockpit.view.topLevelContracts.listStyle); + this.treeView = treeView; + this._onDidChangeTreeData = new vscode.EventEmitter(); + this.onDidChangeTreeData = this._onDidChangeTreeData.event; + + this.data = null; + } + + async dataGetRoot() { + return this.data || []; + } + + /** events */ + + /** tree methods */ + // inherited. + + getTreeItem(element) { + let ret = new vscode.TreeItem(element.label, element.collapsibleState); + ret.resourceUri = element.resource; + ret.iconPath = element.iconPath; + ret.command = + element.type === FilePathTreeDataProvider.TYPE_FILE + ? { + command: "solidity-va.cockpit.jumpToRange", + arguments: [element.resource], + title: "JumpTo", + } + : 0; + return ret; + } + + /** other methods */ + refresh(workspaceRelativeBaseDir) { + return new Promise((resolve, reject) => { + this.treeView.cockpit.commands + ._findTopLevelContracts(undefined, undefined, workspaceRelativeBaseDir) + .then((data) => { + this.load( + Object.values(data).sort((a, b) => { + a = a.path.split("/").pop(); + b = b.path.split("/").pop(); + if (a == b) { + return 0; + } + return a < b ? -1 : 1; + }), + ); + this._onDidChangeTreeData.fire(); + resolve(); }); - } + }); + } } class TopLevelContractsView extends BaseView { - constructor(cockpit) { - super(); - this.cockpit = cockpit; - this.id = "topLevelContracts"; - this.dataProvider = new TopLevelContractsViewDataProvider(this); - this.treeView = vscode.window.createTreeView(`solidity-va-cockpit-${this.id}`, { treeDataProvider: this.dataProvider }); - this.treeView.message = "click ↻ to scan for contracts..."; - } + constructor(cockpit) { + super(); + this.cockpit = cockpit; + this.id = "topLevelContracts"; + this.dataProvider = new TopLevelContractsViewDataProvider(this); + this.treeView = vscode.window.createTreeView( + `solidity-va-cockpit-${this.id}`, + { treeDataProvider: this.dataProvider }, + ); + this.treeView.message = "click ↻ to scan for contracts..."; + } } /* FTrace View */ class FTraceViewDataProvider extends BaseDataProvider { - - constructor(treeView) { - super(); - this.treeView = treeView; - this._onDidChangeTreeData = new vscode.EventEmitter(); - this.onDidChangeTreeData = this._onDidChangeTreeData.event; - - this.data = null; //json {item: {a:object, b:object, c:object}} - this.documentUri = null; - } - - async dataGetRoot() { - if (this.data === null || this.documentUri === null) { - return []; - } - return Object.keys(this.data).map(k => { - let children = typeof this.data[k] === "object" ? this.data[k] : {}; - return { - children: children, - resource: this.documentUri, //uri - label: k, - tooltip: k, - name: k, - parent: null, - iconPath: vscode.ThemeIcon.File, - collapsibleState: children && Object.keys(children).length > 0 ? vscode.TreeItemCollapsibleState.Expanded : 0, - }; - }); + constructor(treeView) { + super(); + this.treeView = treeView; + this._onDidChangeTreeData = new vscode.EventEmitter(); + this.onDidChangeTreeData = this._onDidChangeTreeData.event; + + this.data = null; //json {item: {a:object, b:object, c:object}} + this.documentUri = null; + } + + async dataGetRoot() { + if (this.data === null || this.documentUri === null) { + return []; } - - dataGetChildren(element) { - if (!element) { - return this.data; - } - - if (!element.children) { - return []; - } - // element provided? - - return Object.keys(element.children).map(k => { - let children = typeof element.children[k] === "object" ? element.children[k] : {}; - return { - children: children, - resource: this.documentUri, //uri - label: k, - tooltip: k, - name: k, - parent: null, - iconPath: vscode.ThemeIcon.File, - collapsibleState: children && Object.keys(children).length > 0 ? vscode.TreeItemCollapsibleState.Expanded : 0, - }; - }); + return Object.keys(this.data).map((k) => { + let children = typeof this.data[k] === "object" ? this.data[k] : {}; + return { + children: children, + resource: this.documentUri, //uri + label: k, + tooltip: k, + name: k, + parent: null, + iconPath: vscode.ThemeIcon.File, + collapsibleState: + children && Object.keys(children).length > 0 + ? vscode.TreeItemCollapsibleState.Expanded + : 0, + }; + }); + } + + dataGetChildren(element) { + if (!element) { + return this.data; } - - dataGetParent(element) { - return element.parent; + if (!element.children) { + return []; } - - /** events */ - - /** tree methods */ - // inherited. - + // element provided? - + return Object.keys(element.children).map((k) => { + let children = + typeof element.children[k] === "object" ? element.children[k] : {}; + return { + children: children, + resource: this.documentUri, //uri + label: k, + tooltip: k, + name: k, + parent: null, + iconPath: vscode.ThemeIcon.File, + collapsibleState: + children && Object.keys(children).length > 0 + ? vscode.TreeItemCollapsibleState.Expanded + : 0, + }; + }); + } + + dataGetParent(element) { + return element.parent; + } + + /** events */ + + /** tree methods */ + // inherited. } class FTraceView extends BaseView { - constructor(cockpit) { - super(); - this.cockpit = cockpit; - this.id = "ftrace"; - this.dataProvider = new FTraceViewDataProvider(this); - this.treeView = vscode.window.createTreeView(`solidity-va-cockpit-${this.id}`, { treeDataProvider: this.dataProvider, showCollapseAll: true }); - this.treeView.message = "click into the editor to update view..."; - } - - async onDidSelectionChange(event) { - - let documentUri = event.textEditor.document.uri; - let focus = event.selections[0].anchor; - let commands = this.cockpit.commands; - - let contractObj = commands.g_workspace.sourceUnits[documentUri.fsPath]; - let knownFiles = Object.keys(commands.g_workspace.sourceUnits).filter(f => f.endsWith(".sol")); + constructor(cockpit) { + super(); + this.cockpit = cockpit; + this.id = "ftrace"; + this.dataProvider = new FTraceViewDataProvider(this); + this.treeView = vscode.window.createTreeView( + `solidity-va-cockpit-${this.id}`, + { treeDataProvider: this.dataProvider, showCollapseAll: true }, + ); + this.treeView.message = "click into the editor to update view..."; + } + async onDidSelectionChange(event) { + let documentUri = event.textEditor.document.uri; + let focus = event.selections[0].anchor; + let commands = this.cockpit.commands; - if (!contractObj) { - console.warn("surya.ftrace: not a file: " + documentUri.fsPath); - return; - } + let contractObj = commands.g_workspace.sourceUnits[documentUri.fsPath]; + let knownFiles = Object.keys(commands.g_workspace.sourceUnits).filter((f) => + f.endsWith(".sol"), + ); - let focusSolidityElement = contractObj.getFunctionAtLocation(focus.line, focus.character); - if (!focusSolidityElement) { - console.warn("surya.ftrace: contract not found: " + documentUri.fsPath); - return; - } - let contractName = focusSolidityElement.contract._node.name; + if (!contractObj) { + console.warn("surya.ftrace: not a file: " + documentUri.fsPath); + return; + } - if (!focusSolidityElement.function) { - return; - } + let focusSolidityElement = contractObj.getFunctionAtLocation( + focus.line, + focus.character, + ); + if (!focusSolidityElement) { + console.warn("surya.ftrace: contract not found: " + documentUri.fsPath); + return; + } + let contractName = focusSolidityElement.contract._node.name; - let functionName = focusSolidityElement.function._node.name; + if (!focusSolidityElement.function) { + return; + } - let files; - if (settings.extensionConfig().tools.surya.input.contracts == "workspace") { - await vscode.workspace.findFiles("**/*.sol", settings.DEFAULT_FINDFILES_EXCLUDES, 500) - .then(uris => { - files = uris.map(function (uri) { - return uri.fsPath; - }); - }); - } else { - files = [documentUri.fsPath, ...knownFiles]; //better only add imported files. need to resolve that somehow - } + let functionName = focusSolidityElement.function._node.name; - // contract::func, all, files - if (functionName === null) { - functionName = ""; - } else if (functionName === "") { - functionName = ""; - } + let files; + if (settings.extensionConfig().tools.surya.input.contracts == "workspace") { + await vscode.workspace + .findFiles("**/*.sol", settings.DEFAULT_FINDFILES_EXCLUDES, 500) + .then((uris) => { + files = uris.map(function (uri) { + return uri.fsPath; + }); + }); + } else { + files = [... new Set([documentUri.fsPath, ...knownFiles])]; //better only add imported files. need to resolve that somehow + } - let retj = {}; - try { - retj = surya.ftrace(contractName + "::" + functionName, 'all', files, { jsonOutput: true }, true); - } catch (e) { - //console.error(e); - retj = { "💣💥 - sorry! we've encountered an unrecoverable error :/ Please file an issue in our github repository and provide (mention codebase). thanks!": null }; - } - this.dataProvider.documentUri = documentUri; - this.dataProvider.data = retj; - this.refresh(); + // contract::func, all, files + if (functionName === null) { + functionName = ""; + } else if (functionName === "") { + functionName = ""; + } + let retj = {}; + try { + retj = surya.ftrace( + contractName + "::" + functionName, + "all", + files, + { jsonOutput: true }, + true, + ); + } catch (e) { + //console.error(e); + retj = { + "💣💥 - sorry! we've encountered an unrecoverable error :/ Please file an issue in our github repository and provide (mention codebase). thanks!": + null, + }; + retj[`${e.message}`] = null; //print error to user } + this.dataProvider.documentUri = documentUri; + this.dataProvider.data = retj; + this.refresh(); + } } /* Methods View */ - class PublicMethodsViewDataProvider extends BaseDataProvider { - - constructor(treeView) { - super(); - this.treeView = treeView; - this._onDidChangeTreeData = new vscode.EventEmitter(); - this.onDidChangeTreeData = this._onDidChangeTreeData.event; - - this.data = null; - this.documentUri = null; + constructor(treeView) { + super(); + this.treeView = treeView; + this._onDidChangeTreeData = new vscode.EventEmitter(); + this.onDidChangeTreeData = this._onDidChangeTreeData.event; + + this.data = null; + this.documentUri = null; + } + + async dataGetRoot() { + if (this.data === null || this.documentUri === null) { + return []; } - async dataGetRoot() { - if (this.data === null || this.documentUri === null) { - return []; - } - - return Object.keys(this.data) - .reduce((ret, key) => { - let element = this.data[key]; - let range = elemLocToRange(element._node) - let modifiers = Object.keys(element.modifiers); - let item = { - resource: element.resource, - contextValue: element.resource.fsPath, - range: range, - label: element._node.stateMutability == "payable" ? key + " 💰 " : key, - tooltip: key, - name: key, - iconPath: vscode.ThemeIcon.File, - collapsibleState: modifiers.length > 0 ? vscode.TreeItemCollapsibleState.Collapsed : 0, - parent: null, - children: modifiers.map(name => { - return { - //resource: element.resource, - label: "Ⓜ " + name, - //iconPath: 0, - command: { - command: 'solidity-va.cockpit.jumpToRange', - arguments: [element.resource, elemLocToRange(element.modifiers[name])], - title: 'JumpTo' - } - }; - }), - command: { - command: 'solidity-va.cockpit.jumpToRange', - arguments: [element.resource, elemLocToFirstLineRange(element._node)], - title: 'JumpTo' - }, - }; - ret.push(item); - return ret; - }, []); - } - - dataGetChildren(element) { - return element.children; - } - - /** events */ - - /** tree methods */ - // inherited. - + return Object.keys(this.data).reduce((ret, key) => { + const funcs = this.data[key]; + const items = funcs.map((f) => { + const range = elemLocToRange(f._node); + const modifiers = Object.keys(f.modifiers); + return { + resource: f.resource, + contextValue: f.resource.fsPath, + range: range, + label: `${f._node.stateMutability == "payable" ? "💰" : ""} ${ + f.name || key + }`, + tooltip: f.name || key, + name: f.name || key, + iconPath: vscode.ThemeIcon.File, + collapsibleState: + modifiers.length > 0 + ? vscode.TreeItemCollapsibleState.Collapsed + : 0, + parent: null, + children: modifiers.map((name) => { + return { + label: "Ⓜ " + name, + //iconPath: 0, + command: { + command: "solidity-va.cockpit.jumpToRange", + arguments: [f.resource, elemLocToRange(f.modifiers[name])], + title: "JumpTo", + }, + }; + }), + command: { + command: "solidity-va.cockpit.jumpToRange", + arguments: [f.resource, elemLocToFirstLineRange(f._node)], + title: "JumpTo", + }, + }; + }); + ret.push(...items); + return ret; + }, []); + } + + dataGetChildren(element) { + return element.children; + } + + /** events */ + + /** tree methods */ + // inherited. } class PublicMethodsView extends BaseView { - constructor(cockpit) { - super(); - this.cockpit = cockpit; - this.id = "publicMethods"; - this.dataProvider = new PublicMethodsViewDataProvider(this); - this.treeView = vscode.window.createTreeView(`solidity-va-cockpit-${this.id}`, { treeDataProvider: this.dataProvider }); - this.treeView.message = "click into the editor to update view..."; - } + constructor(cockpit) { + super(); + this.cockpit = cockpit; + this.id = "publicMethods"; + this.dataProvider = new PublicMethodsViewDataProvider(this); + this.treeView = vscode.window.createTreeView( + `solidity-va-cockpit-${this.id}`, + { treeDataProvider: this.dataProvider }, + ); + this.treeView.message = "click into the editor to update view..."; + } - async onDidSelectionChange(event) { + async onDidSelectionChange(event) { + let documentUri = event.textEditor.document.uri; + let focus = event.selections[0].anchor; + let commands = this.cockpit.commands; - let documentUri = event.textEditor.document.uri; - let focus = event.selections[0].anchor; - let commands = this.cockpit.commands; + let contractObj = commands.g_workspace.sourceUnits[documentUri.fsPath]; - let contractObj = commands.g_workspace.sourceUnits[documentUri.fsPath]; + if (!contractObj) { + console.warn("cockpit.methods: not a file: " + documentUri.fsPath); + return; + } + let currentContract = contractObj.getContractAtLocation( + focus.line, + focus.character, + ); + if (!currentContract) { + console.warn( + "cockpit.methods: contract not found: " + documentUri.fsPath, + ); + return; + } - if (!contractObj) { - console.warn("cockpit.methods: not a file: " + documentUri.fsPath); - return; - } + let filterNotVisibility = ["private", "internal"]; + let filterNotStateMutability = ["view", "pure", "constant"]; - let focusSolidityElement = contractObj.getFunctionAtLocation(focus.line, focus.character); - if (!focusSolidityElement) { - console.warn("cockpit.methods: contract not found: " + documentUri.fsPath); - return; + let publicFunctions = currentContract.functions + .filter((f) => { + let node = f._node; + //filter only for state changing public functions + return ( + !filterNotVisibility.includes(node.visibility) && + !filterNotStateMutability.includes(node.stateMutability) + ); + }) + .reduce((obj, func) => { + let key = func.name; + + if (key === null || func._node.isConstructor) { + key = ""; + } else if (key === "" || func._node.isFallback) { + key = ""; } - - let filterNotVisibility = ["private", "internal"]; - let filterNotStateMutability = ["view", "pure", "constant"]; - - let publicFunctions = focusSolidityElement.contract.functions - .filter(f => { - let node = f._node; - //filter only for state changing public functions - return !filterNotVisibility.includes(node.visibility) && !filterNotStateMutability.includes(node.stateMutability); - }) - .reduce((obj, func) => { - let newKey = func.name; - - if (newKey === null || func._node.isConstructor) { - newKey = ""; - } else if (newKey === "" || func._node.isFallback) { - newKey = ""; - } - func.resource = documentUri; - obj[newKey] = func; - return obj; - }, {}); - // contract::func, all, files - this.dataProvider.documentUri = documentUri; - this.dataProvider.data = publicFunctions; - this.refresh(); - } + func.resource = documentUri; + if (!obj[key]) { + obj[key] = [func]; //we use an array to handle function override + } else { + obj[key].push(func); + } + return obj; + }, {}); + // contract::func, all, files + this.dataProvider.documentUri = documentUri; + this.dataProvider.data = publicFunctions; + this.refresh(); + } } - /* Solidity Files View */ class ExplorerViewDataProvider extends FilePathTreeDataProvider { - constructor(treeView) { - super("tree"); - this.treeView = treeView; - this._onDidChangeTreeData = new vscode.EventEmitter(); - this.onDidChangeTreeData = this._onDidChangeTreeData.event; - - this.data = null; - } - - async dataGetRoot() { - if (this.data === null) { - this.refresh(); - } - return this.data || []; - } - - /** events */ - - /** tree methods */ - // inherited. - - getTreeItem(element) { - let ret = new vscode.TreeItem(element.label, element.collapsibleState); - ret.resourceUri = element.resource; - ret.contextValue = element.resource.fsPath; - ret.iconPath = element.iconPath; - ret.command = element.type === FilePathTreeDataProvider.TYPE_FILE ? { - command: 'solidity-va.cockpit.jumpToRange', - arguments: [element.resource], - title: 'JumpTo' - } : 0; - return ret; + constructor(treeView) { + super("tree"); + this.treeView = treeView; + this._onDidChangeTreeData = new vscode.EventEmitter(); + this.onDidChangeTreeData = this._onDidChangeTreeData.event; + + this.data = null; + } + + async dataGetRoot() { + if (this.data === null) { + this.refresh(); } - - /** other methods */ - refresh() { - return new Promise((resolve, reject) => { - vscode.workspace.findFiles("{**/*.sol}", settings.DEFAULT_FINDFILES_EXCLUDES_ALLOWFLAT, 5000) - .then((solfiles) => { - this.load(solfiles); - this._onDidChangeTreeData.fire(); - resolve(); - }); + return this.data || []; + } + + /** events */ + + /** tree methods */ + // inherited. + + getTreeItem(element) { + let ret = new vscode.TreeItem(element.label, element.collapsibleState); + ret.resourceUri = element.resource; + ret.contextValue = element.resource.fsPath; + ret.iconPath = element.iconPath; + ret.command = + element.type === FilePathTreeDataProvider.TYPE_FILE + ? { + command: "solidity-va.cockpit.jumpToRange", + arguments: [element.resource], + title: "JumpTo", + } + : 0; + return ret; + } + + /** other methods */ + refresh() { + return new Promise((resolve, reject) => { + vscode.workspace + .findFiles( + "{**/*.sol}", + settings.DEFAULT_FINDFILES_EXCLUDES_ALLOWFLAT, + 5000, + ) + .then((solfiles) => { + this.load(solfiles); + this._onDidChangeTreeData.fire(); + resolve(); }); - } + }); + } } class ExplorerView extends BaseView { - constructor(cockpit) { - super(); - this.cockpit = cockpit; - this.id = "explorer"; - this.dataProvider = new ExplorerViewDataProvider(this); - this.treeView = vscode.window.createTreeView(`solidity-va-cockpit-${this.id}`, { treeDataProvider: this.dataProvider, showCollapseAll: true, canSelectMany: true }); - } + constructor(cockpit) { + super(); + this.cockpit = cockpit; + this.id = "explorer"; + this.dataProvider = new ExplorerViewDataProvider(this); + this.treeView = vscode.window.createTreeView( + `solidity-va-cockpit-${this.id}`, + { + treeDataProvider: this.dataProvider, + showCollapseAll: true, + canSelectMany: true, + }, + ); + } } class FlatFilesDataProvider extends FilePathTreeDataProvider { - constructor(treeView) { - super("tree"); - this.treeView = treeView; - this._onDidChangeTreeData = new vscode.EventEmitter(); - this.onDidChangeTreeData = this._onDidChangeTreeData.event; - - this.data = null; - } - - async dataGetRoot() { - if (this.data === null) { - this.refresh(); - } - return this.data || []; + constructor(treeView) { + super("tree"); + this.treeView = treeView; + this._onDidChangeTreeData = new vscode.EventEmitter(); + this.onDidChangeTreeData = this._onDidChangeTreeData.event; + + this.data = null; + } + + async dataGetRoot() { + if (this.data === null) { + this.refresh(); } - - /** events */ - - /** tree methods */ - // inherited. - - getTreeItem(element) { - let ret = new vscode.TreeItem(element.label, element.collapsibleState) - ret.resourceUri = element.resource; - ret.contextValue = element.resource.fsPath; - ret.iconPath = element.iconPath; - ret.command = element.type === FilePathTreeDataProvider.TYPE_FILE ? { - command: 'solidity-va.cockpit.jumpToRange', - arguments: [element.resource], - title: 'JumpTo' - } : 0; - return ret; - } - - /** other methods */ - refresh() { - return new Promise((resolve, reject) => { - vscode.workspace.findFiles("{**/*_flat.sol,**/flat_*.sol}", settings.DEFAULT_FINDFILES_EXCLUDES_ALLOWFLAT, 500) - .then((solfiles) => { - this.load(solfiles); - this._onDidChangeTreeData.fire(); - resolve(); - }); + return this.data || []; + } + + /** events */ + + /** tree methods */ + // inherited. + + getTreeItem(element) { + let ret = new vscode.TreeItem(element.label, element.collapsibleState); + ret.resourceUri = element.resource; + ret.contextValue = element.resource.fsPath; + ret.iconPath = element.iconPath; + ret.command = + element.type === FilePathTreeDataProvider.TYPE_FILE + ? { + command: "solidity-va.cockpit.jumpToRange", + arguments: [element.resource], + title: "JumpTo", + } + : 0; + return ret; + } + + /** other methods */ + refresh() { + return new Promise((resolve, reject) => { + vscode.workspace + .findFiles( + "{**/*_flat.sol,**/flat_*.sol}", + settings.DEFAULT_FINDFILES_EXCLUDES_ALLOWFLAT, + 500, + ) + .then((solfiles) => { + this.load(solfiles); + this._onDidChangeTreeData.fire(); + resolve(); }); - } + }); + } } class FlatFilesView extends BaseView { - constructor(cockpit) { - super(); - this.cockpit = cockpit; - this.id = "flatFiles"; - this.dataProvider = new FlatFilesDataProvider(this); - this.treeView = vscode.window.createTreeView(`solidity-va-cockpit-${this.id}`, { treeDataProvider: this.dataProvider, showCollapseAll: true, canSelectMany: true }); - } + constructor(cockpit) { + super(); + this.cockpit = cockpit; + this.id = "flatFiles"; + this.dataProvider = new FlatFilesDataProvider(this); + this.treeView = vscode.window.createTreeView( + `solidity-va-cockpit-${this.id}`, + { + treeDataProvider: this.dataProvider, + showCollapseAll: true, + canSelectMany: true, + }, + ); + } } /* settings view */ class SettingsViewDataProvider extends VirtualPathTreeDataProvider { - constructor(treeView) { - super("tree", "."); - this.treeView = treeView; - this._onDidChangeTreeData = new vscode.EventEmitter(); - this.onDidChangeTreeData = this._onDidChangeTreeData.event; - - this.data = null; - - let pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "..", 'package.json'))); - let properties = pkg.contributes.configuration.properties; - this.settings = Object.keys(properties) - .filter(key => properties[key].type === "boolean") - .reduce((obj, key) => { - obj[key] = properties[key]; - return obj; - }, {}); - } + constructor(treeView) { + super("tree", "."); + this.treeView = treeView; + this._onDidChangeTreeData = new vscode.EventEmitter(); + this.onDidChangeTreeData = this._onDidChangeTreeData.event; - async dataGetRoot() { - if (this.data === null) { - this.refresh(); - } - return this.data || []; - } + this.data = null; - /** events */ + let pkg = JSON.parse( + fs.readFileSync(path.join(__dirname, "..", "..", "package.json")), + ); + let properties = pkg.contributes.configuration.properties; + this.settings = Object.keys(properties) + .filter((key) => properties[key].type === "boolean") + .reduce((obj, key) => { + obj[key] = properties[key]; + return obj; + }, {}); + } + + async dataGetRoot() { + if (this.data === null) { + this.refresh(); + } + return this.data || []; + } - /** tree methods */ - // inherited. + /** events */ - getTreeItem(element) { - let ret = new vscode.TreeItem( - element.type === VirtualPathTreeDataProvider.TYPE_LEAF ? (element.metadata.currentValue === true ? "☑ " : "☐ ") + element.label : element.label, - element.collapsibleState - ); - ret.resourceUri = element.resource; - ret.metadata = element.metadata; - ret.contextValue = element.type; - //tooltip: element.type === VirtualPathTreeDataProvider.TYPE_LEAF ? element.metadata.description : null, /* fixes proposed api warning */ - ret.iconPath = element.iconPath; - ret.command = element.type === VirtualPathTreeDataProvider.TYPE_LEAF ? { - command: 'solidity-va.cockpit.settings.toggle', - arguments: [element], - title: 'Toggle' - } : 0; - return ret; - } + /** tree methods */ + // inherited. - /** other methods */ - refresh() { - return new Promise((resolve, reject) => { - let settingsState = Object.keys(this.settings) - .reduce((obj, key) => { - obj[key] = this.settings[key]; - let k = key.split("."); - obj[key].extension = k[0]; - obj[key].section = k.slice(1).join("."); - obj[key].currentValue = vscode.workspace.getConfiguration(obj[key].extension).get(obj[key].section); - return obj; - }, {}); - this.load(settingsState); - this._onDidChangeTreeData.fire(); - resolve(); - }); - } + getTreeItem(element) { + let ret = new vscode.TreeItem( + element.type === VirtualPathTreeDataProvider.TYPE_LEAF + ? (element.metadata.currentValue === true ? "☑ " : "☐ ") + + element.label + : element.label, + element.collapsibleState, + ); + ret.resourceUri = element.resource; + ret.metadata = element.metadata; + ret.contextValue = element.type; + //tooltip: element.type === VirtualPathTreeDataProvider.TYPE_LEAF ? element.metadata.description : null, /* fixes proposed api warning */ + ret.iconPath = element.iconPath; + ret.command = + element.type === VirtualPathTreeDataProvider.TYPE_LEAF + ? { + command: "solidity-va.cockpit.settings.toggle", + arguments: [element], + title: "Toggle", + } + : 0; + return ret; + } + + /** other methods */ + refresh() { + return new Promise((resolve, reject) => { + let settingsState = Object.keys(this.settings).reduce((obj, key) => { + obj[key] = this.settings[key]; + let k = key.split("."); + obj[key].extension = k[0]; + obj[key].section = k.slice(1).join("."); + obj[key].currentValue = vscode.workspace + .getConfiguration(obj[key].extension) + .get(obj[key].section); + return obj; + }, {}); + this.load(settingsState); + this._onDidChangeTreeData.fire(); + resolve(); + }); + } } class SettingsView extends BaseView { - constructor(cockpit) { - super(); - this.cockpit = cockpit; - this.id = "settings"; - this.dataProvider = new SettingsViewDataProvider(this); - this.treeView = vscode.window.createTreeView(`solidity-va-cockpit-${this.id}`, { treeDataProvider: this.dataProvider, showCollapseAll: true }); - } + constructor(cockpit) { + super(); + this.cockpit = cockpit; + this.id = "settings"; + this.dataProvider = new SettingsViewDataProvider(this); + this.treeView = vscode.window.createTreeView( + `solidity-va-cockpit-${this.id}`, + { treeDataProvider: this.dataProvider, showCollapseAll: true }, + ); + } } /* ExtCall View */ class ExtCallViewDataProvider extends BaseDataProvider { - - constructor(treeView) { - super(); - this.treeView = treeView; - this._onDidChangeTreeData = new vscode.EventEmitter(); - this.onDidChangeTreeData = this._onDidChangeTreeData.event; - - this.data = null; - this.documentUri = null; - } - - async dataGetRoot() { - if (this.data === null || this.documentUri === null) { - return []; - } - - return Object.keys(this.data) - .reduce((ret, key) => { - - if (this.data[key].length <= 0) { - return ret; - } - - let first = this.data[key][0]; - - let item = { - resource: first.resource, - contextValue: first.resource.fsPath, - range: elemLocToRange(first.parent.function._node), - label: first.parent.function._node.stateMutability == "payable" ? key + " 💰 " : key, - tooltip: key, - name: key, - iconPath: vscode.ThemeIcon.File, - collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, - parent: null, - children: this.data[key].map(element => { - return { - //resource: element.resource, - label: `⇢ ${element.call.declaration.name ? element.call.declaration.name : ""}.${element.call.name} (${nodeTypeName(element.call.declaration) || ""})`, - //iconPath: 0, - command: { - command: 'solidity-va.cockpit.jumpToRange', - arguments: [element.resource, elemLocToRange(element.call._node)], - title: 'JumpTo' - } - }; - }), - command: { - command: 'solidity-va.cockpit.jumpToRange', - arguments: [first.resource, elemLocToFirstLineRange(first.parent.function._node)], - title: 'JumpTo' - }, - }; - ret.push(item); - return ret; - }, []); - } - - dataGetChildren(element) { - return element.children; + constructor(treeView) { + super(); + this.treeView = treeView; + this._onDidChangeTreeData = new vscode.EventEmitter(); + this.onDidChangeTreeData = this._onDidChangeTreeData.event; + + this.data = null; + this.documentUri = null; + } + + async dataGetRoot() { + if (this.data === null || this.documentUri === null) { + return []; } - /** events */ - - /** tree methods */ - // inherited. - + return Object.keys(this.data).reduce((ret, key) => { + if (this.data[key].length <= 0) { + return ret; + } + + let first = this.data[key][0]; + const inFunction = first.parent; + + let redableName = inFunction.name; + if (redableName === null || inFunction._node.isConstructor) { + redableName = ""; + } else if (key === "" || inFunction._node.isFallback) { + redableName = ""; + } + + let item = { + resource: first.resource, + contextValue: first.resource.fsPath, + range: elemLocToRange(first.parent._node), + label: `${redableName}${ + inFunction._node.stateMutability === "payable" ? " 💰" : "" + }`, + tooltip: redableName, //in function name + name: redableName, + iconPath: vscode.ThemeIcon.File, + collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, + parent: null, + children: this.data[key].map((element) => { + return { + //resource: element.resource, + label: `⇢ ${ + element.call.declaration.name ? element.call.declaration.name : "" + }.${element.call.name} (${ + nodeTypeName(element.call.declaration) || "" + })`, + //iconPath: 0, + command: { + command: "solidity-va.cockpit.jumpToRange", + arguments: [element.resource, elemLocToRange(element.call._node)], + title: "JumpTo", + }, + }; + }), + command: { + command: "solidity-va.cockpit.jumpToRange", + arguments: [ + first.resource, + elemLocToFirstLineRange(first.parent._node), + ], + title: "JumpTo", + }, + }; + ret.push(item); + return ret; + }, []); + } + + dataGetChildren(element) { + return element.children; + } + + /** events */ + + /** tree methods */ + // inherited. } class ExtCallView extends BaseView { - constructor(cockpit) { - super(); - this.cockpit = cockpit; - this.id = "externalCalls"; - this.dataProvider = new ExtCallViewDataProvider(this); - this.treeView = vscode.window.createTreeView(`solidity-va-cockpit-${this.id}`, { treeDataProvider: this.dataProvider }); - this.treeView.message = "click into the editor to update view..."; - } - - async onDidSelectionChange(event) { - - let documentUri = event.textEditor.document.uri; - let commands = this.cockpit.commands; - let focus = event.selections[0].anchor; - - let sourceUnit = commands.g_workspace.sourceUnits[documentUri.fsPath]; - - if (!sourceUnit) { - console.warn("cockpit.extcall: not a file: " + documentUri.fsPath); - return; - } - - let focusSolidityElement = sourceUnit.getContractAtLocation(focus.line, focus.character); - if (!focusSolidityElement) { - console.warn("surya.ftrace: contract not found: " + documentUri.fsPath); - return; - } - - // data format: obj[contract][function][calls]=[target, target]; - let extcalls = focusSolidityElement.getExternalCalls().reduce((obj, c) => { + constructor(cockpit) { + super(); + this.cockpit = cockpit; + this.id = "externalCalls"; + this.dataProvider = new ExtCallViewDataProvider(this); + this.treeView = vscode.window.createTreeView( + `solidity-va-cockpit-${this.id}`, + { treeDataProvider: this.dataProvider }, + ); + this.treeView.message = "click into the editor to update view..."; + } - let result = sourceUnit.getFunctionAtLocation(c._node.loc.start.line, 0); - let key = `${result.function.name}`; - let data = obj[key]; + async onDidSelectionChange(event) { + let documentUri = event.textEditor.document.uri; + let commands = this.cockpit.commands; + let focus = event.selections[0].anchor; - if (!data) { - data = []; - } + let sourceUnit = commands.g_workspace.sourceUnits[documentUri.fsPath]; - data.push({ resource: documentUri, call: c, parent: result }); + if (!sourceUnit) { + console.warn("cockpit.extcall: not a file: " + documentUri.fsPath); + return; + } - obj[key] = data; - return obj; - }, []); - // contract::func, all, files - this.dataProvider.documentUri = documentUri; - this.dataProvider.data = extcalls; - this.refresh(); + let focusSolidityElement = sourceUnit.getContractAtLocation( + focus.line, + focus.character, + ); + if (!focusSolidityElement) { + console.warn( + "cockpit.extcall: contract not found: " + documentUri.fsPath, + ); + return; } -} + // data format: obj[contract][function][calls]=[target, target]; + let extcalls = focusSolidityElement.getExternalCalls().reduce((obj, c) => { + const functionNode = c.inFunction; + const key = functionNode.id; + let data = obj[key]; //use function id instead of name to handle overriden functions + + if (!data) { + data = []; + } + + data.push({ resource: documentUri, call: c, parent: functionNode }); + + obj[key] = data; + return obj; + }, []); + // contract::func, all, files + this.dataProvider.documentUri = documentUri; + this.dataProvider.data = extcalls; + this.refresh(); + } +} /** -- cockpit handler -- */ class Cockpit { - - constructor(commands) { - this.commands = commands; - this.views = {}; - - this.registerView(new ExplorerView(this)); - this.registerView(new TopLevelContractsView(this)); - this.registerView(new FlatFilesView(this)); - this.registerView(new FTraceView(this)); - this.registerView(new SettingsView(this)); - this.registerView(new PublicMethodsView(this)); - this.registerView(new ExtCallView(this)); - } - - registerView(view) { - this.views[view.id] = view; + constructor(commands) { + this.commands = commands; + this.views = {}; + + this.registerView(new ExplorerView(this)); + this.registerView(new TopLevelContractsView(this)); + this.registerView(new FlatFilesView(this)); + this.registerView(new FTraceView(this)); + this.registerView(new SettingsView(this)); + this.registerView(new PublicMethodsView(this)); + this.registerView(new ExtCallView(this)); + } + + registerView(view) { + this.views[view.id] = view; + } + + async onDidSelectionChange(event) { + if ( + !event || + !event.textEditor || + !event.textEditor.visibleRanges || + event.textEditor.visibleRanges.length <= 0 || + !event.selections || + event.selections.length <= 0 + ) { + return; // no visible range open; no selection } - async onDidSelectionChange(event) { - - if (!event || !event.textEditor || !event.textEditor.visibleRanges || event.textEditor.visibleRanges.length <= 0 || !event.selections || event.selections.length <= 0) { - return; // no visible range open; no selection - } - - Object.values(this.views).filter(v => v.treeView.visible).forEach(v => { - v.onDidSelectionChange(event); - }); - } + Object.values(this.views) + .filter((v) => v.treeView.visible) + .forEach((v) => { + v.onDidSelectionChange(event); + }); + } } - module.exports = { - Cockpit: Cockpit -}; \ No newline at end of file + Cockpit: Cockpit, +}; diff --git a/src/features/codelens.js b/src/features/codelens.js index d59c0e5..312aea1 100644 --- a/src/features/codelens.js +++ b/src/features/codelens.js @@ -1,50 +1,48 @@ -'use strict'; -/** +"use strict"; +/** * @author github.com/tintinweb * @license GPLv3 - * - * + * + * * */ -const vscode = require('vscode'); -const settings = require('../settings.js'); +const vscode = require("vscode"); +const settings = require("../settings.js"); /* await window.showInputBox({prompt: 'prompt for something',}) */ -function elemLocToRange(elem){ - let name = elem.name?elem.name:Object(elem.name).toString(); - return new vscode.Range( - new vscode.Position(elem.loc.start.line-1, elem.loc.start.column), - new vscode.Position(elem.loc.start.line-1, elem.loc.start.column+name.length) - ); +function elemLocToRange(elem) { + let name = elem.name ? elem.name : Object(elem.name).toString(); + return new vscode.Range( + new vscode.Position(elem.loc.start.line - 1, elem.loc.start.column), + new vscode.Position( + elem.loc.start.line - 1, + elem.loc.start.column + name.length, + ), + ); } -class SolidityCodeLensProvider { - constructor(g_workspace, cb_analyze) { - this.g_workspace = g_workspace; - this.cb_analyze = cb_analyze; - } - - async provideCodeLenses(document, token) { - let codeLens = []; - let firstLine = new vscode.Range(0, 0, 0, 0); +class StaticLensProvider { + constructor(g_workspace) { + this.g_workspace = g_workspace; + this.codeLenses = []; + } - //kick-off analysis even though this might be overlapping :/ we'll fix that later - await this.cb_analyze(token, document); + init(document, item) { + const codeLens = []; + const firstLine = new vscode.Range(0, 0, 0, 0); + const config = settings.extensionConfig().codelens; - let config = settings.extensionConfig().codelens; - - /** top level lenses */ - config.report.enable && codeLens.push( - new vscode.CodeLens( - firstLine, { - command: 'solidity-va.surya.mdreport', - title: 'report' - } - ) - ); - /* does not yet return values but writes to console + /** top level lenses */ + config.report.enable && + codeLens.push( + new vscode.CodeLens(firstLine, { + command: "solidity-va.surya.mdreport", + title: "report", + }), + ); + /* does not yet return values but writes to console codeLens.push( new vscode.CodeLens( firstLine, { @@ -55,175 +53,224 @@ class SolidityCodeLensProvider { ) ) */ - config.graphThis.enable && codeLens.push( - new vscode.CodeLens( - firstLine, { - command: 'solidity-va.surya.graph', - title: 'graph (this)', - arguments: [document, [document.uri.fsPath]] - } - ) - ); - config.graph.enable && codeLens.push( - new vscode.CodeLens( - firstLine, { - command: 'solidity-va.surya.graph', - title: 'graph', - arguments: [document] //auto-loads all parsed files - } - ) - ); - config.inheritance.enable && codeLens.push( - new vscode.CodeLens( - firstLine, { - command: 'solidity-va.surya.inheritance', - title: 'inheritance', - arguments: [document] - } - ) - ); - config.parse.enable && codeLens.push( - new vscode.CodeLens( - firstLine, { - command: 'solidity-va.surya.parse', - title: 'parse', - arguments: [document] - } - ) - ); + config.graphThis.enable && + codeLens.push( + new vscode.CodeLens(firstLine, { + command: "solidity-va.surya.graph", + title: "graph (this)", + arguments: [document, [document.uri.fsPath]], + }), + ); + config.graph.enable && + codeLens.push( + new vscode.CodeLens(firstLine, { + command: "solidity-va.surya.graph", + title: "graph", + arguments: [document], //auto-loads all parsed files + }), + ); + config.inheritance.enable && + codeLens.push( + new vscode.CodeLens(firstLine, { + command: "solidity-va.surya.inheritance", + title: "inheritance", + arguments: [document], + }), + ); + config.parse.enable && + codeLens.push( + new vscode.CodeLens(firstLine, { + command: "solidity-va.surya.parse", + title: "parse", + arguments: [document], + }), + ); - config.flatten.enable && codeLens.push( - new vscode.CodeLens( - firstLine, { - command: 'solidity-va.tools.flaterra', - title: 'flatten', - arguments: [document] - } - ) - ); + config.flatten.enable && + codeLens.push( + new vscode.CodeLens(firstLine, { + command: "solidity-va.tools.flaterra", + title: "flatten", + arguments: [document], + }), + ); + return codeLens; + } - config.funcSigs.enable && codeLens.push( - new vscode.CodeLens( - firstLine, { - command: 'solidity-va.tools.function.signatures', - title: 'funcSigs', - arguments: [document] - } - ) - ); + async provideCodeLenses(document, token) { + if (this.codeLenses.length == 0) { + this.codeLenses = this.init(document, token); + } + return this.codeLenses; + } +} - let parser = this.g_workspace.sourceUnits[document.uri.fsPath]; - if(!parser) { - console.warn("[ERR] parser was not ready while adding codelenses. omitting contract specific lenses."); - return codeLens; - } +class ParserLensProvider { + constructor(g_workspace) { + this.g_workspace = g_workspace; + } + provideCodeLenses(document, token) { + let firstLine = new vscode.Range(0, 0, 0, 0); + let config = settings.extensionConfig().codelens; + return this.g_workspace + .add(document.fileName, { content: document.getText() }) + .then((parser) => { + let codeLens = []; + config.uml.enable && + codeLens.push( + new vscode.CodeLens(firstLine, { + command: "solidity-va.uml.contract.outline", + title: "uml", + arguments: [document, Object.values(parser.contracts)], + }), + ); - config.uml.enable && codeLens.push(new vscode.CodeLens(firstLine, { - command: 'solidity-va.uml.contract.outline', - title: 'uml', - arguments: [document, Object.values(parser.contracts)] - }) - ); + config.drawio.enable && + codeLens.push( + new vscode.CodeLens(firstLine, { + command: "solidity-va.uml.contract.export.drawio.csv", + title: "draw.io", + arguments: [document, Object.values(parser.contracts)], + }), + ); - - config.drawio.enable && codeLens.push(new vscode.CodeLens(firstLine, { - command: 'solidity-va.uml.contract.export.drawio.csv', - title: 'draw.io', - arguments: [document, Object.values(parser.contracts)] - }) - ); - + config.funcSigs.enable && + codeLens.push( + new vscode.CodeLens(firstLine, { + command: "solidity-va.tools.function.signatureForAstItem", + title: "funcSigs", + arguments: [Object.values(parser.contracts)], + }), + ); - let annotateContractTypes = ["contract","library", "abstract"]; + let annotateContractTypes = ["contract", "library", "abstract"]; /** all contract decls */ - for(let contractObj of Object.values(parser.contracts)){ - if(token.isCancellationRequested){ - return []; - } + for (let contractObj of Object.values(parser.contracts)) { + if (token.isCancellationRequested) { + return []; + } - if(annotateContractTypes.indexOf(contractObj._node.kind)>=0){ - codeLens = codeLens.concat(this.onContractDecl(document,contractObj)); + if (annotateContractTypes.indexOf(contractObj._node.kind) >= 0) { + codeLens = codeLens.concat( + this.onContractDecl(document, contractObj), + ); - /** all function decls */ - for(let funcObj of contractObj.functions){ - codeLens = codeLens.concat(this.onFunctionDecl(document, contractObj.name, funcObj)); - } - } else if (contractObj._node.kind == "interface"){ - // add uml to interface - let item = contractObj; - config.uml.enable && codeLens.push(new vscode.CodeLens(elemLocToRange(item._node), { - command: 'solidity-va.uml.contract.outline', - title: 'uml', - arguments: [document, [item]] - }) - ); + /** all function decls */ + for (let funcObj of contractObj.functions) { + codeLens = codeLens.concat( + this.onFunctionDecl(document, contractObj.name, funcObj), + ); } + } else if (contractObj._node.kind == "interface") { + // add uml to interface + let item = contractObj; + config.uml.enable && + codeLens.push( + new vscode.CodeLens(elemLocToRange(item._node), { + command: "solidity-va.uml.contract.outline", + title: "uml", + arguments: [document, [item]], + }), + ); + } } return codeLens; - } + }) + .catch((e) => { + console.warn( + `Error parsing file ${document.fileName}`, + ); + if (settings.extensionConfig().debug.parser.showExceptions) { + console.error(e); + } + return undefined; + }); + } - onContractDecl(document, item) { - let lenses = []; - let range = elemLocToRange(item._node); + onContractDecl(document, item) { + let lenses = []; + let range = elemLocToRange(item._node); - let config = settings.extensionConfig().codelens; + let config = settings.extensionConfig().codelens; - config.unittestStub.enable && lenses.push(new vscode.CodeLens(range, { - command: 'solidity-va.test.createTemplate', - title: 'UnitTest stub', - arguments: [document, item.name] - }) - ); - - config.dependencies.enable && lenses.push(new vscode.CodeLens(range, { - command: 'solidity-va.surya.dependencies', - title: 'dependencies', - arguments: [document, item.name, []] - }) - ); + config.unittestStub.enable && + lenses.push( + new vscode.CodeLens(range, { + command: "solidity-va.test.createTemplate", + title: "UnitTest stub", + arguments: [document, item.name], + }), + ); - config.uml.enable && lenses.push(new vscode.CodeLens(range, { - command: 'solidity-va.uml.contract.outline', - title: 'uml', - arguments: [document, [item]] - }) - ); + config.dependencies.enable && + lenses.push( + new vscode.CodeLens(range, { + command: "solidity-va.surya.dependencies", + title: "dependencies", + arguments: [document, item.name, []], + }), + ); - config.drawio.enable && lenses.push(new vscode.CodeLens(range, { - command: 'solidity-va.uml.contract.export.drawio.csv', - title: 'draw.io', - arguments: [document, [item]] - }) - ); - - - return lenses; - } + config.uml.enable && + lenses.push( + new vscode.CodeLens(range, { + command: "solidity-va.uml.contract.outline", + title: "uml", + arguments: [document, [item]], + }), + ); - onFunctionDecl(document, contractName, item) { - let lenses = []; - let range = elemLocToRange(item._node); + config.funcSigs.enable && + lenses.push( + new vscode.CodeLens(range, { + command: "solidity-va.tools.function.signatureForAstItem", + title: "funcSigs", + arguments: [item], + }), + ); - let config = settings.extensionConfig().codelens; + config.drawio.enable && + lenses.push( + new vscode.CodeLens(range, { + command: "solidity-va.uml.contract.export.drawio.csv", + title: "draw.io", + arguments: [document, [item]], + }), + ); - config.ftrace.enable && lenses.push(new vscode.CodeLens(range, { - command: 'solidity-va.surya.ftrace', - title: 'ftrace', - arguments: [document, contractName, item._node.name, "all"] - }) - ); - //exclude constructor (item._node.name == null) - config.funcSigs.enable && item._node.name && lenses.push(new vscode.CodeLens(range, { - command: 'solidity-va.tools.function.signatureForAstItem', - title: 'funcSig', - arguments: [item] - }) - ); + return lenses; + } - return lenses; - } + onFunctionDecl(document, contractName, item) { + let lenses = []; + let range = elemLocToRange(item._node); + + let config = settings.extensionConfig().codelens; + + config.ftrace.enable && + lenses.push( + new vscode.CodeLens(range, { + command: "solidity-va.surya.ftrace", + title: "ftrace", + arguments: [document, contractName, item._node.name, "all"], + }), + ); + //exclude constructor (item._node.name == null) + config.funcSigs.enable && + item._node.name && + lenses.push( + new vscode.CodeLens(range, { + command: "solidity-va.tools.function.signatureForAstItem", + title: "funcSig", + arguments: [item], + }), + ); + + return lenses; + } } module.exports = { - SolidityCodeLensProvider:SolidityCodeLensProvider + StaticLensProvider, + ParserLensProvider, }; diff --git a/src/features/commands.js b/src/features/commands.js index 5dcfc83..a78dee1 100644 --- a/src/features/commands.js +++ b/src/features/commands.js @@ -1,647 +1,850 @@ -'use strict'; -/** +"use strict"; +/** * @author github.com/tintinweb * @license GPLv3 - * - * + * + * * */ -const vscode = require('vscode'); -const fs = require('fs'); -const child_process = require('child_process'); -const path = require('path'); +const vscode = require("vscode"); +const fs = require("fs"); +const child_process = require("child_process"); +const path = require("path"); -const settings = require('../settings'); +const settings = require("../settings"); -const mod_templates = require('./templates'); -const mod_utils = require('./utils'); - - -const { DrawIoCsvWriter } = require('./writer/drawio'); -const { PlantumlWriter } = require('./writer/plantuml'); - -const surya = require('surya'); +const mod_templates = require("./templates"); +const mod_utils = require("./utils"); +const { DrawIoCsvWriter } = require("./writer/drawio"); +const { PlantumlWriter } = require("./writer/plantuml"); +const surya = require("surya"); const suryaDefaultColorSchemeDark = { - digraph : { - bgcolor: "#2e3e56", - nodeAttribs : { - style:"filled", - fillcolor:"#edad56", - color:"#edad56", - penwidth:"3" - }, - edgeAttribs : { - color:"#fcfcfc", - penwidth:"2", - fontname:"helvetica Neue Ultra Light" - } + digraph: { + bgcolor: "#2e3e56", + nodeAttribs: { + style: "filled", + fillcolor: "#edad56", + color: "#edad56", + penwidth: "3", }, - visibility : { - isFilled: true, - public: "#FF9797", - external: "#ffbdb9", - private: "#edad56", - internal: "#f2c383", + edgeAttribs: { + color: "#fcfcfc", + penwidth: "2", + fontname: "helvetica Neue Ultra Light", }, - nodeType : { - isFilled: false, - shape: "doubleoctagon", - modifier: "#1bc6a6", - payable: "brown", + }, + visibility: { + isFilled: true, + public: "#FF9797", + external: "#ffbdb9", + private: "#edad56", + internal: "#f2c383", + }, + nodeType: { + isFilled: false, + shape: "doubleoctagon", + modifier: "#1bc6a6", + payable: "brown", + }, + call: { + default: "white", + regular: "#1bc6a6", + this: "#80e097", + }, + contract: { + defined: { + bgcolor: "#445773", + color: "#445773", + fontcolor: "#f0f0f0", + style: "rounded", }, - call : { - default: "white", - regular: "#1bc6a6", - this: "#80e097" + undefined: { + bgcolor: "#3b4b63", + color: "#e8726d", + fontcolor: "#f0f0f0", + style: "rounded,dashed", }, - contract : { - defined: { - bgcolor: "#445773", - color: "#445773", - fontcolor:"#f0f0f0", - style: "rounded" - }, - undefined: { - bgcolor: "#3b4b63", - color: "#e8726d", - fontcolor: "#f0f0f0", - style: "rounded,dashed" - } - } - - }; - - -function runCommand(cmd, args, env, cwd, stdin){ - cwd = cwd || vscode.workspace.rootPath; - - return new Promise((resolve, reject) => { - console.log(`running command: ${cmd} ${args.join(" ")}`); - let p = child_process.execFile(cmd, args, { env: env, cwd: cwd }, (err, stdout, stderr) => { - p.stdout.on('data', function(data) { - if(stdin){ - p.stdin.setEncoding('utf-8'); - p.stdin.write(stdin); - p.stdin.end(); - } - }); - if(err===null || err.code === 0){ - console.log("success"); - return resolve(err); - } - err.stderr = stderr; - return reject(err); + }, +}; + +function runCommand(cmd, args, env, cwd, stdin) { + cwd = cwd || vscode.workspace.rootPath; + + return new Promise((resolve, reject) => { + console.log(`running command: ${cmd} ${args.join(" ")}`); + let p = child_process.execFile( + cmd, + args, + { env: env, cwd: cwd }, + (err, stdout, stderr) => { + p.stdout.on("data", function (data) { + if (stdin) { + p.stdin.setEncoding("utf-8"); + p.stdin.write(stdin); + p.stdin.end(); + } }); - }); + if (err === null || err.code === 0) { + console.log("success"); + return resolve(err); + } + err.stderr = stderr; + return reject(err); + }, + ); + }); } -class Commands{ - - constructor(g_workspace) { - this.g_workspace = g_workspace; +class Commands { + constructor(g_workspace) { + this.g_workspace = g_workspace; + } + + _checkIsSolidity(document) { + if (!document || document.languageId != settings.languageId) { + vscode.window.showErrorMessage( + `[Solidity VA] not a solidity source file ${vscode.window.activeTextEditor.document.uri.fsPath}`, + ); + throw new Error("not a solidity file"); } - - _checkIsSolidity(document) { - if(!document || document.languageId!=settings.languageId){ - vscode.window.showErrorMessage(`[Solidity VA] not a solidity source file ${vscode.window.activeTextEditor.document.uri.fsPath}`); - throw new Error("not a solidity file"); - } + } + + async generateUnittestStubForContract(document, contractName) { + this._checkIsSolidity(document); + + let content; + if (settings.extensionConfig().test.defaultUnittestTemplate === "hardhat") { + content = mod_templates.generateHardhatUnittestStubForContract( + document, + this.g_parser, + contractName, + ); + } else { + content = mod_templates.generateUnittestStubForContract( + document, + this.g_parser, + contractName, + ); } - - async generateUnittestStubForContract(document, contractName) { - this._checkIsSolidity(document); - let content; - if(settings.extensionConfig().test.defaultUnittestTemplate==="hardhat"){ - content = mod_templates.generateHardhatUnittestStubForContract(document, this.g_parser, contractName); - } else { - content = mod_templates.generateUnittestStubForContract(document, this.g_parser, contractName); - } - - vscode.workspace.openTextDocument({content: content, language: "javascript"}) - .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)); + vscode.workspace + .openTextDocument({ content: content, language: "javascript" }) + .then((doc) => + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), + ); + } + + async surya(documentOrListItems, command, args) { + //check if input was document or listItem + if (!documentOrListItems) { + throw new Error("not a file or list item"); } - async surya(documentOrListItems, command, args) { - //check if input was document or listItem - if(!documentOrListItems){ - throw new Error("not a file or list item"); - } + let ret; + let files = []; - let ret; - let files = []; + if (documentOrListItems.hasOwnProperty("children")) { + //hack ;) + documentOrListItems = [documentOrListItems]; //allow non array calls + } - if(documentOrListItems.hasOwnProperty("children")){ - //hack ;) - documentOrListItems = [documentOrListItems]; //allow non array calls + if (Array.isArray(documentOrListItems)) { + for (let documentOrListItem of documentOrListItems) { + if (documentOrListItem.hasOwnProperty("children")) { + // is a list item -> item.resource.fsPath + if (!!path.extname(documentOrListItem.resource.fsPath)) { + //file + files = [...files, documentOrListItem.resource.fsPath]; + } else { + //folder + await vscode.workspace + .findFiles( + `${documentOrListItem.path}/**/*.sol`, + settings.DEFAULT_FINDFILES_EXCLUDES, + 500, + ) + .then((uris) => { + files = files.concat( + uris.map(function (uri) { + return uri.fsPath; + }), + ); + }); + } } + } + } else { + //single document mode + this._checkIsSolidity(documentOrListItems); // throws + + if ( + settings.extensionConfig().tools.surya.input.contracts == "workspace" + ) { + await vscode.workspace + .findFiles("**/*.sol", settings.DEFAULT_FINDFILES_EXCLUDES, 500) + .then((uris) => { + files = uris.map(function (uri) { + return uri.fsPath; + }); + }); + } else { + //better only add imported files. need to resolve that somehow + files = [ + documentOrListItems.uri.fsPath, + ...Object.keys(this.g_workspace.sourceUnits), + ].filter((p) => fs.existsSync(p)); //only feed existing files into surya or it might die 🥲 + } + } - if(Array.isArray(documentOrListItems)){ - - for(let documentOrListItem of documentOrListItems){ - - if(documentOrListItem.hasOwnProperty("children")){ - // is a list item -> item.resource.fsPath - if(!!path.extname(documentOrListItem.resource.fsPath)){ - //file - files = [...files, documentOrListItem.resource.fsPath]; - } else { - //folder - await vscode.workspace.findFiles(`${documentOrListItem.path}/**/*.sol`, settings.DEFAULT_FINDFILES_EXCLUDES, 500) - .then(uris => { - files = files.concat(uris.map(function (uri) { - return uri.fsPath; - })); - }); - } - } - - } + switch (command) { + case "describe": + ret = surya.describe(files, {}, true); + vscode.workspace + .openTextDocument({ content: ret, language: "markdown" }) + .then((doc) => + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), + ); + break; + case "graphSimple": + case "graph": + if (command == "graphSimple") { + ret = surya.graphSimple(args || files, { + colorScheme: suryaDefaultColorSchemeDark, + }); } else { - //single document mode - this._checkIsSolidity(documentOrListItems); // throws - - if(settings.extensionConfig().tools.surya.input.contracts=="workspace"){ - await vscode.workspace.findFiles("**/*.sol", settings.DEFAULT_FINDFILES_EXCLUDES, 500) - .then(uris => { - files = uris.map(function (uri) { - return uri.fsPath; - }); - }); - } else { - files = [documentOrListItems.uri.fsPath, ...Object.keys(this.g_workspace.sourceUnits)]; //better only add imported files. need to resolve that somehow - } + ret = surya.graph(args || files, { + colorScheme: suryaDefaultColorSchemeDark, + }); } - - switch(command) { - case "describe": - ret = surya.describe(files, {}, true); - vscode.workspace.openTextDocument({content: ret, language: "markdown"}) - .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)); - break; - case "graphSimple": - case "graph": - if(command=="graphSimple"){ - ret = surya.graphSimple(args || files, {colorScheme: suryaDefaultColorSchemeDark}); - } else { - ret = surya.graph(args || files, {colorScheme: suryaDefaultColorSchemeDark}); - } - //solidity-va.preview.render.markdown - vscode.workspace.openTextDocument({content: ret, language: "dot"}) - .then(doc => { - if(settings.extensionConfig().preview.dot){ - vscode.commands.executeCommand("graphviz-interactive-preview.preview.beside", {document: doc, content:ret, callback:null, title:`Call Graph`}) - .catch(error =>{ - vscode.commands.executeCommand("interactive-graphviz.preview.beside", {document: doc, content:ret, callback:null, title:`Call Graph`}) //TODO: remove this in future version. only for transition to new command - .catch(error =>{ - vscode.commands.executeCommand("graphviz.previewToSide", doc.uri) - .catch(error => { - //command not available. fallback open as text and try graphviz.showPreview - vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) - .then(editor => { - vscode.commands.executeCommand("graphviz.showPreview", editor) // creates new pane - .catch(error => { - //command not available - do nothing - }); - }); - }); + //solidity-va.preview.render.markdown + vscode.workspace + .openTextDocument({ content: ret, language: "dot" }) + .then((doc) => { + if (settings.extensionConfig().preview.dot) { + vscode.commands + .executeCommand("graphviz-interactive-preview.preview.beside", { + document: doc, + content: ret, + callback: null, + title: `Call Graph`, + }) + .catch((error) => { + vscode.commands + .executeCommand("interactive-graphviz.preview.beside", { + document: doc, + content: ret, + callback: null, + title: `Call Graph`, + }) //TODO: remove this in future version. only for transition to new command + .catch((error) => { + vscode.commands + .executeCommand("graphviz.previewToSide", doc.uri) + .catch((error) => { + //command not available. fallback open as text and try graphviz.showPreview + vscode.window + .showTextDocument(doc, vscode.ViewColumn.Beside) + .then((editor) => { + vscode.commands + .executeCommand("graphviz.showPreview", editor) // creates new pane + .catch((error) => { + //command not available - do nothing }); }); - } else { - vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside); - } - + }); }); - /* + }); + } else { + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside); + } + }); + /* vscode.env.openExternal(vscode.Uri.file("/Users/tintin/workspace/vscode/solidity-auditor/images/icon.png")) .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)) */ - break; - case "inheritance": - ret = surya.inheritance(files,{draggable:false}); - vscode.workspace.openTextDocument({content: ret, language: "dot"}) - .then(doc => { - if(settings.extensionConfig().preview.dot){ - vscode.commands.executeCommand("graphviz-interactive-preview.preview.beside", {document: doc, content:ret, callback:null, title:`Inheritance`}) - .catch(error =>{ - vscode.commands.executeCommand("interactive-graphviz.preview.beside", {document: doc, content:ret, callback:null, title:`Inheritance`}) //TODO: remove this in future version. only for transition to new command - .catch(error =>{ - vscode.commands.executeCommand("graphviz.previewToSide", doc.uri) - .catch(error => { - //command not available. fallback open as text and try graphviz.showPreview - vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) - .then(editor => { - vscode.commands.executeCommand("graphviz.showPreview", editor) // creates new pane - .catch(error => { - //command not available - do nothing - }); - }); - }); + break; + case "inheritance": + ret = surya.inheritance(files, { draggable: false }); + vscode.workspace + .openTextDocument({ content: ret, language: "dot" }) + .then((doc) => { + if (settings.extensionConfig().preview.dot) { + vscode.commands + .executeCommand("graphviz-interactive-preview.preview.beside", { + document: doc, + content: ret, + callback: null, + title: `Inheritance`, + }) + .catch((error) => { + vscode.commands + .executeCommand("interactive-graphviz.preview.beside", { + document: doc, + content: ret, + callback: null, + title: `Inheritance`, + }) //TODO: remove this in future version. only for transition to new command + .catch((error) => { + vscode.commands + .executeCommand("graphviz.previewToSide", doc.uri) + .catch((error) => { + //command not available. fallback open as text and try graphviz.showPreview + vscode.window + .showTextDocument(doc, vscode.ViewColumn.Beside) + .then((editor) => { + vscode.commands + .executeCommand("graphviz.showPreview", editor) // creates new pane + .catch((error) => { + //command not available - do nothing }); }); - } else { - vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside); - } - + }); }); - /* + }); + } else { + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside); + } + }); + /* let draggable = surya.inheritance(files,{draggable:true}) console.error(draggable) createWebViewBesides('imgPreview','imgPreview',draggable) */ - break; - case "parse": - ret = surya.parse(documentOrListItems.uri.fsPath); - vscode.workspace.openTextDocument({content: ret, language: "markdown"}) - .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)); - break; - case "dependencies": - ret = surya.dependencies(files, args[0]); - - let outTxt = []; - - if(ret){ - outTxt.push(ret[0]); - - if (ret.length < 2) { - outTxt = ['No Dependencies Found']; - } - else { - ret.shift(); - const reducer = (accumulator, currentValue) => `${accumulator}\n ↖ ${currentValue}`; - outTxt.push(` ↖ ${ret.reduce(reducer)}`); - } - - - vscode.workspace.openTextDocument({content: outTxt.join("\n"), language: "markdown"}) - .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)); - } - break; - case "ftrace": - // contract::func, all, files - if (args[1] === null){ - args[1] = ""; - } else if (args[1] === ""){ - args[1] = ""; - } - try { - ret = surya.ftrace(args[0] + "::" + args[1], args[2] || 'all', files, {}, true); - vscode.workspace.openTextDocument({content: ret, language: "markdown"}) - .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)); - } catch (e) { - console.error(e); - } - - break; - case "mdreport": - ret = surya.mdreport(files, {negModifiers: settings.extensionConfig().tools.surya.option.negModifiers}); - if(!ret) { - return; - } - vscode.workspace.openTextDocument({content: ret, language: "markdown"}) - .then(doc => { - if(settings.extensionConfig().preview.markdown){ - vscode.commands.executeCommand("markdown-preview-enhanced.openPreview", doc.uri) - .catch(error => { - //command does not exist - vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) - .then(editor => { - vscode.commands.executeCommand("markdown.extension.togglePreview") - .catch(error => { - //command does not exist - }); - }); - }); - } else { - vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside); - } - //command not available. fallback open as text - }); - break; - default: - // code block + break; + case "parse": + ret = surya.parse(documentOrListItems.uri.fsPath); + vscode.workspace + .openTextDocument({ content: ret, language: "markdown" }) + .then((doc) => + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), + ); + break; + case "dependencies": + ret = surya.dependencies(files, args[0]); + + let outTxt = []; + + if (ret) { + outTxt.push(ret[0]); + + if (ret.length < 2) { + outTxt = ["No Dependencies Found"]; + } else { + ret.shift(); + const reducer = (accumulator, currentValue) => + `${accumulator}\n ↖ ${currentValue}`; + outTxt.push(` ↖ ${ret.reduce(reducer)}`); + } + + vscode.workspace + .openTextDocument({ + content: outTxt.join("\n"), + language: "markdown", + }) + .then((doc) => + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), + ); + } + break; + case "ftrace": + // contract::func, all, files + if (args[1] === null) { + args[1] = ""; + } else if (args[1] === "") { + args[1] = ""; + } + try { + ret = surya.ftrace( + args[0] + "::" + args[1], + args[2] || "all", + files, + {}, + true, + ); + vscode.workspace + .openTextDocument({ content: ret, language: "markdown" }) + .then((doc) => + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), + ); + } catch (e) { + console.error(e); } - } - - async _findTopLevelContracts(files, scanfiles, workspaceRelativeBaseDirs) { - var that = this; - var dependencies={}; - var contractToFile={}; - if(!scanfiles){ - - workspaceRelativeBaseDirs = Array.isArray(workspaceRelativeBaseDirs) ? workspaceRelativeBaseDirs : [workspaceRelativeBaseDirs]; - - let searchFileString = "{" +workspaceRelativeBaseDirs.map(d => d === undefined ? "**/*.sol" : d + path.sep + "**/*.sol").join(",") + "}"; - - await vscode.workspace.findFiles(searchFileString, settings.DEFAULT_FINDFILES_EXCLUDES, 500) - .then(async (solfiles) => { - await solfiles.forEach( async (solfile) => { - try { - //let content = fs.readFileSync(solfile.fsPath).toString('utf-8'); - //let sourceUnit = that.g_parser.parseSourceUnit(content); - - let sourceUnit = await that.g_workspace.add(solfile.fsPath); - - for(let contractName in sourceUnit.contracts){ - if(sourceUnit.contracts[contractName]._node.kind == "interface") { //ignore interface contracts - continue; - } - dependencies[contractName] = sourceUnit.contracts[contractName].dependencies; - contractToFile[contractName] = solfile; - } - } catch (e) { - } + break; + case "mdreport": + ret = surya.mdreport(files, { + negModifiers: + settings.extensionConfig().tools.surya.option.negModifiers, + }); + if (!ret) { + return; + } + vscode.workspace + .openTextDocument({ content: ret, language: "markdown" }) + .then((doc) => { + if (settings.extensionConfig().preview.markdown) { + vscode.commands + .executeCommand( + "markdown-preview-enhanced.openPreview", + doc.uri, + ) + .catch((error) => { + //command does not exist + vscode.window + .showTextDocument(doc, vscode.ViewColumn.Beside) + .then((editor) => { + vscode.commands + .executeCommand("markdown.extension.togglePreview") + .catch((error) => { + //command does not exist + }); }); }); - } else { - //files not set: take loaded sourceUnits from this.g_workspace - //files set: only take these sourceUnits - await this.g_workspace.getAllContracts().filter(c => c._node.kind != "interface" && c._node.kind != "library").forEach(c => { - dependencies[c.name] = c.dependencies; - }); - } - - var depnames = [].concat.apply([], Object.values(dependencies)); + } else { + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside); + } + //command not available. fallback open as text + }); + break; + default: + // code block + } + } + + async _findTopLevelContracts(files, scanfiles, workspaceRelativeBaseDirs) { + var that = this; + var dependencies = {}; + var contractToFile = {}; + if (!scanfiles) { + workspaceRelativeBaseDirs = Array.isArray(workspaceRelativeBaseDirs) + ? workspaceRelativeBaseDirs + : [workspaceRelativeBaseDirs]; + + let searchFileString = + "{" + + workspaceRelativeBaseDirs + .map((d) => + d === undefined ? "**/*.sol" : d + path.sep + "**/*.sol", + ) + .join(",") + + "}"; + + await vscode.workspace + .findFiles(searchFileString, settings.DEFAULT_FINDFILES_EXCLUDES, 500) + .then(async (solfiles) => { + await solfiles.forEach(async (solfile) => { + try { + //let content = fs.readFileSync(solfile.fsPath).toString('utf-8'); + //let sourceUnit = that.g_parser.parseSourceUnit(content); - let topLevelContracts = Object.keys(dependencies).filter(function (i) { - return depnames.indexOf(i) === -1; - }); + let sourceUnit = await that.g_workspace.add(solfile.fsPath); - let ret = {}; - topLevelContracts.forEach(contractName => { - ret[contractName] = contractToFile[contractName]; + for (let contractName in sourceUnit.contracts) { + if ( + sourceUnit.contracts[contractName]._node.kind == "interface" + ) { + //ignore interface contracts + continue; + } + dependencies[contractName] = + sourceUnit.contracts[contractName].dependencies; + contractToFile[contractName] = solfile; + } + } catch (e) {} + }); + }); + } else { + //files not set: take loaded sourceUnits from this.g_workspace + //files set: only take these sourceUnits + await this.g_workspace + .getAllContracts() + .filter((c) => c._node.kind != "interface" && c._node.kind != "library") + .forEach((c) => { + dependencies[c.name] = c.dependencies; }); - return ret; } - async findTopLevelContracts(files, scanfiles) { - let topLevelContracts = await this._findTopLevelContracts(files, scanfiles); + var depnames = [].concat.apply([], Object.values(dependencies)); - let topLevelContractsText = Object.keys(topLevelContracts).join('\n'); - /* + let topLevelContracts = Object.keys(dependencies).filter(function (i) { + return depnames.indexOf(i) === -1; + }); + + let ret = {}; + topLevelContracts.forEach((contractName) => { + ret[contractName] = contractToFile[contractName]; + }); + return ret; + } + + async findTopLevelContracts(files, scanfiles) { + let topLevelContracts = await this._findTopLevelContracts(files, scanfiles); + + let topLevelContractsText = Object.keys(topLevelContracts).join("\n"); + /* for (var name in topLevelContracts) { topLevelContractsText += name + ' (' + topLevelContracts[name]+')\n'; } */ - let content = ` + let content = ` Top Level Contracts =================== ${topLevelContractsText}`; - vscode.workspace.openTextDocument({content: content, language: "markdown"}) - .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)); - } - - async solidityFlattener(files, callback, showErrors) { - - switch(settings.extensionConfig().flatten.mode){ - case "truffle": - vscode.extensions.getExtension("tintinweb.vscode-solidity-flattener").activate().then( - (active) => { - vscode.commands.executeCommand("vscode-solidity-flattener.flatten", {files: files, callback:callback, showErrors:showErrors}) - .catch(error =>{ - // command not available - vscode.window.showWarningMessage("Error running `tintinweb.vscode-solidity-flattener`. Please make sure the extension is installed.\n" + error); - }); - }, - (err) => { throw new Error(`Solidity Auditor: Failed to activate "tintinweb.vscode-solidity-flattener". Make sure the extension is installed from the marketplace. Details: ${err}`); } - ); - break; - default: - this.flattenInternal(files, callback, showErrors); - break; - } - } - - flattenInternal(files, callback, showErrors){ - files.forEach(async uri => { - let sourceUnit = this.g_workspace.sourceUnits[uri.fsPath];//get sourceUnit object - sourceUnit = sourceUnit || await this.g_workspace.add(uri.fsPath); //retry & force analysis - if(!sourceUnit){ - return; - } - try { - let flat = sourceUnit.flatten(); - if(callback){ - callback(uri.fsPath, undefined, flat); - } else { - vscode.workspace.openTextDocument({content: flat, language: "solidity"}) - .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)); - } - - } catch(e) { - console.warn(`ERROR - flattening file: ${uri}`) - console.error(e); - } - - }); - - } - - async flaterra(documentOrUri, noTryInstall) { - let docUri = documentOrUri; - if(documentOrUri.hasOwnProperty("uri")){ - this._checkIsSolidity(documentOrUri); - docUri = documentOrUri.uri; - } - - - let cmd = "python3"; - let args = ["-m", "flaterra", "--contract", vscode.workspace.asRelativePath(docUri)]; - - - runCommand(cmd, args) - .then( - (success) =>{ - vscode.window.showInformationMessage(`Contract flattened: ${path.basename(docUri.fsPath,".sol")}_flat.sol`); - }, - (err) => { - if(err.code === 'ENOENT'){ - vscode.window.showErrorMessage("'`flaterra` failed with error: unable to execute python3"); - } else if (err.stderr.indexOf(": No module named flaterra")>=0){ - if(!noTryInstall){ - vscode.window.showWarningMessage('Contract Flattener `flaterra` is not installed.\n run `pip3 install flaterra --user` to install? ', 'Install') - .then(selection => { - console.log(selection); - if(selection=="Install"){ - runCommand("pip3", ["install", "flaterra", "--user"], undefined, undefined, "y\n") - .then( - (success) =>{ - vscode.window.showInformationMessage("Successfully installed flaterra."); - this.flaterra(documentOrUri, true); - }, - (error) => { - vscode.window.showErrorMessage("Failed to install flaterra."); - } - ) - .catch(err =>{ - vscode.window.showErrorMessage("Failed to install flaterra. " + err); - }); - } else { - // do not retry - } - }); - } - } else { - vscode.window.showErrorMessage('`flaterra` failed with: ' + err) - .then(selection => { - console.log(selection); - }); - } + vscode.workspace + .openTextDocument({ content: content, language: "markdown" }) + .then((doc) => + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), + ); + } + + async solidityFlattener(files, callback, showErrors) { + switch (settings.extensionConfig().flatten.mode) { + case "truffle": + vscode.extensions + .getExtension("tintinweb.vscode-solidity-flattener") + .activate() + .then( + (active) => { + vscode.commands + .executeCommand("vscode-solidity-flattener.flatten", { + files: files, + callback: callback, + showErrors: showErrors, }) - .catch(err => { - console.log("runcommand threw exception: "+ err); - }); - } - - async flattenCandidates(candidates) { - // takes object key=contractName value=fsPath - let topLevelContracts = candidates || await this._findTopLevelContracts(); - let content = ""; - - this.solidityFlattener(Object.values(topLevelContracts), (filepath, trufflepath, content) => { - let outpath = path.parse(filepath); - - fs.writeFile(path.join(outpath.dir, "flat_" + outpath.base), content, function(err) { - if(err) { - return console.log(err); - } - }); - }); - - - for(let name in topLevelContracts){ - //this.flaterra(new vscode.Uri(topLevelContracts[name])) - let outpath = path.parse(topLevelContracts[name].fsPath); - let outpath_flat = vscode.Uri.file(path.join(outpath.dir, "flat_" + outpath.base)); - content += `${!fs.existsSync(outpath_flat.fsPath)?"[ERR] ":""}${name} => ${outpath_flat} \n`; - } - vscode.workspace.openTextDocument({content: content, language: "markdown"}) - .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)); + .catch((error) => { + // command not available + vscode.window.showWarningMessage( + "Error running `tintinweb.vscode-solidity-flattener`. Please make sure the extension is installed.\n" + + error, + ); + }); + }, + (err) => { + throw new Error( + `Solidity Auditor: Failed to activate "tintinweb.vscode-solidity-flattener". Make sure the extension is installed from the marketplace. Details: ${err}`, + ); + }, + ); + break; + default: + this.flattenInternal(files, callback, showErrors); + break; } - - async listFunctionSignatures(document, asJson) { - let sighash_colls = mod_utils.functionSignatureExtractor(document.getText()); - let sighashes = sighash_colls.sighashes; - - if(sighash_colls.collisions.length){ - vscode.window.showErrorMessage('🔥 FuncSig collisions detected! ' + sighash_colls.collisions.join(",")); - } - - let content; - if(asJson){ - content = JSON.stringify(sighashes); + } + + flattenInternal(files, callback, showErrors) { + files.forEach(async (uri) => { + let sourceUnit = this.g_workspace.sourceUnits[uri.fsPath]; //get sourceUnit object + sourceUnit = sourceUnit || (await this.g_workspace.add(uri.fsPath)); //retry & force analysis + if (!sourceUnit) { + return; + } + try { + let flat = sourceUnit.flatten(); + if (callback) { + callback(uri.fsPath, undefined, flat); } else { - content = "Sighash | Function Signature\n========================\n"; - for(let hash in sighashes){ - content += hash + " => " + sighashes[hash] + "\n"; - } - if(sighash_colls.collisions.length){ - content += "\n\n"; - content += "collisions 🔥🔥🔥 \n========================\n"; - content += sighash_colls.collisions.join("\n"); - } + vscode.workspace + .openTextDocument({ content: flat, language: "solidity" }) + .then((doc) => + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), + ); } - vscode.workspace.openTextDocument({content: content, language: "markdown"}) - .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)); - } - - async listFunctionSignaturesForWorkspace(asJson) { - - let sighashes = {}; - let collisions = []; + } catch (e) { + console.warn(`ERROR - flattening file: ${uri}`); + console.error(e); + } + }); + } - await vscode.workspace.findFiles("**/*.sol", settings.DEFAULT_FINDFILES_EXCLUDES, 500) - .then(uris => { - uris.forEach(uri => { - try { - let sig_colls = mod_utils.functionSignatureExtractor(fs.readFileSync(uri.fsPath).toString('utf-8')); - collisions = collisions.concat(sig_colls.collisions); //we're not yet checking sighash collisions across contracts + async flaterra(documentOrUri, noTryInstall) { + let docUri = documentOrUri; + if (documentOrUri.hasOwnProperty("uri")) { + this._checkIsSolidity(documentOrUri); + docUri = documentOrUri.uri; + } - let currSigs = sig_colls.sighashes; - for(let k in currSigs){ - sighashes[k]=currSigs[k]; - } - } catch (e) {} - }); + let cmd = "python3"; + let args = [ + "-m", + "flaterra", + "--contract", + vscode.workspace.asRelativePath(docUri), + ]; + + runCommand(cmd, args) + .then( + (success) => { + vscode.window.showInformationMessage( + `Contract flattened: ${path.basename( + docUri.fsPath, + ".sol", + )}_flat.sol`, + ); + }, + (err) => { + if (err.code === "ENOENT") { + vscode.window.showErrorMessage( + "'`flaterra` failed with error: unable to execute python3", + ); + } else if (err.stderr.indexOf(": No module named flaterra") >= 0) { + if (!noTryInstall) { + vscode.window + .showWarningMessage( + "Contract Flattener `flaterra` is not installed.\n run `pip3 install flaterra --user` to install? ", + "Install", + ) + .then((selection) => { + if (selection == "Install") { + runCommand( + "pip3", + ["install", "flaterra", "--user"], + undefined, + undefined, + "y\n", + ) + .then( + (success) => { + vscode.window.showInformationMessage( + "Successfully installed flaterra.", + ); + this.flaterra(documentOrUri, true); + }, + (error) => { + vscode.window.showErrorMessage( + "Failed to install flaterra.", + ); + }, + ) + .catch((err) => { + vscode.window.showErrorMessage( + "Failed to install flaterra. " + err, + ); + }); + } else { + // do not retry + } }); - - if(collisions.length){ - vscode.window.showErrorMessage('🔥 FuncSig collisions detected! ' + collisions.join(",")); - } - - let content; - if(asJson){ - content = JSON.stringify(sighashes); - } else { - content = "Sighash | Function Signature\n======================== \n"; - for(let hash in sighashes){ - content += hash + " => " + sighashes[hash] + " \n"; } - if(collisions.length){ - content += "\n\n"; - content += "collisions 🔥🔥🔥 \n========================\n"; - content += collisions.join("\n"); + } else { + vscode.window + .showErrorMessage("`flaterra` failed with: " + err) + .then((selection) => { + console.log(selection); + }); + } + }, + ) + .catch((err) => { + console.log("runcommand threw exception: " + err); + }); + } + + async flattenCandidates(candidates) { + // takes object key=contractName value=fsPath + let topLevelContracts = candidates || (await this._findTopLevelContracts()); + let content = ""; + + this.solidityFlattener( + Object.values(topLevelContracts), + (filepath, trufflepath, content) => { + let outpath = path.parse(filepath); + + fs.writeFile( + path.join(outpath.dir, "flat_" + outpath.base), + content, + function (err) { + if (err) { + return console.log(err); } - } - vscode.workspace.openTextDocument({content: content, language: "markdown"}) - .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)); + }, + ); + }, + ); + + for (let name in topLevelContracts) { + //this.flaterra(new vscode.Uri(topLevelContracts[name])) + let outpath = path.parse(topLevelContracts[name].fsPath); + let outpath_flat = vscode.Uri.file( + path.join(outpath.dir, "flat_" + outpath.base), + ); + content += `${ + !fs.existsSync(outpath_flat.fsPath) ? "[ERR] " : "" + }${name} => ${outpath_flat} \n`; } + vscode.workspace + .openTextDocument({ content: content, language: "markdown" }) + .then((doc) => + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), + ); + } + + async listFunctionSignatures(document, asJson) { + this.g_workspace.add(document.fileName).then(async (sourceUnit) => { + const signatures = await this._signatureForAstItem( + Object.values(sourceUnit.contracts), + ); + await this.revealSignatures(signatures, asJson ? "json" : undefined); + }); + } + + async listFunctionSignaturesForWorkspace(asJson) { + // 1) find all solidity files + // 2) parse + // 3) wait for parser to finish + // 4) get all function signatures + // -- this is kinda resource intensive 🤷‍♂️ + await vscode.workspace + .findFiles("**/*.sol", settings.DEFAULT_FINDFILES_EXCLUDES, 500) + .then((uris) => { + uris.forEach((uri) => { + this.g_workspace.add(uri.fsPath); + }); + }); + await this.g_workspace.withParserReady(undefined, true); + console.log("done"); + const signatures = await this._signatureForAstItem( + this.g_workspace.getAllContracts(), + ); + await this.revealSignatures(signatures, asJson ? "json" : undefined); + } + + async signatureForAstItem(items) { + const signatures = await this._signatureForAstItem(items); + await this.revealSignatures(signatures); + } + + async _signatureForAstItem(items) { + let results = []; + + if (!Array.isArray(items)) { + items = [items]; //arrayify + } + for (let item of items) { + try { + results.push(...mod_utils.functionSignatureForASTItem(item)); + } catch (e) { + console.log(e.message); + } + } + return results; + } - async listFunctionSignatureForAstItem(item, asJson) { + async revealSignatures(signatures, format) { + format = format || "markdown"; + let errs = []; - let sighashes = mod_utils.functionSignatureFromAstNode(item); + const res = {}; - let content; - if(asJson){ - content = JSON.stringify(sighashes); - } else { - content = "Sighash | Function Signature\n======================== \n"; - for(let hash in sighashes){ - content += hash + " => " + sighashes[hash] + " \n"; - } - } - vscode.workspace.openTextDocument({content: content, language: "markdown"}) - .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)); + for (const sig of signatures) { + if (sig.hasOwnProperty("err")) { + errs.push(sig.err); + continue; //skip errors + } + if (!res.hasOwnProperty(sig.sighash)) { + res[sig.sighash] = new Set([sig.signature]); + } else { + res[sig.sighash].add(sig.signature); + } } - async drawioContractsOutlineAsCSV(contractObj) { - - const writer = new DrawIoCsvWriter(); - const content = writer.export(contractObj); + let content; + + switch (format) { + case "json": + content = JSON.stringify( + { + signatures: res, + errors: [...new Set(errs)], + collisions: Object.values(res).filter((v) => v.size > 1), + }, + (_key, value) => (value instanceof Set ? [...value] : value), + ); + break; + + default: + // markdown + + const header = + "| Function Name | Sighash | Function Signature | \n| ------------- | ---------- | ------------------ | \n"; + content = + header + + signatures + .map((r) => `| ${r.name} | ${r.sighash} | ${r.signature} |`) + .join("\n"); + + const collisions = Object.values(res).filter((v) => v.size > 1); + if (collisions.length) { + content += "\n\n"; + content += + "🔥 Collisions \n========================\n"; + content += collisions.map((s) => [...s]).join("\n"); + } - vscode.workspace.openTextDocument({content: content, language: "csv"}) - .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)); + if (errs.length) { + content += "\n\n"; + content += "🐞 Errors \n========================\n"; + content += [...new Set(errs)].join("\n"); + } } - async umlContractsOutline(contractObjects) { - let writer = new PlantumlWriter(); - const content = writer.export(contractObjects); - - vscode.workspace.openTextDocument({content: content, language: "plantuml"}) - .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) - .then(editor => { - vscode.extensions.getExtension("jebbs.plantuml").activate().then( - (active) => { - vscode.commands.executeCommand("plantuml.preview") - .catch(error => { - //command does not exist - }); - }, - (err) => { console.warn(`Solidity Auditor: Failed to activate "jebbs.plantuml". Make sure the extension is installed from the marketplace. Details: ${err}`); } - ); - }) - ); - } + vscode.workspace + .openTextDocument({ content: content, language: format }) + .then((doc) => + vscode.window.showTextDocument(doc, { + viewColumn: vscode.ViewColumn.Beside, + preview: true, + }), + ); + } + + async drawioContractsOutlineAsCSV(contractObj) { + const writer = new DrawIoCsvWriter(); + const content = writer.export(contractObj); + + vscode.workspace + .openTextDocument({ content: content, language: "csv" }) + .then((doc) => + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), + ); + } + + async umlContractsOutline(contractObjects) { + let writer = new PlantumlWriter(); + const content = writer.export(contractObjects); + + vscode.workspace + .openTextDocument({ content: content, language: "plantuml" }) + .then((doc) => + vscode.window + .showTextDocument(doc, vscode.ViewColumn.Beside) + .then((editor) => { + vscode.extensions + .getExtension("jebbs.plantuml") + .activate() + .then( + (active) => { + vscode.commands + .executeCommand("plantuml.preview") + .catch((error) => { + //command does not exist + }); + }, + (err) => { + console.warn( + `Solidity Auditor: Failed to activate "jebbs.plantuml". Make sure the extension is installed from the marketplace. Details: ${err}`, + ); + }, + ); + }), + ); + } } - - module.exports = { - Commands:Commands -}; \ No newline at end of file + Commands: Commands, +}; diff --git a/src/features/deco.js b/src/features/deco.js index d01d272..c80a545 100644 --- a/src/features/deco.js +++ b/src/features/deco.js @@ -1,582 +1,675 @@ -'use strict'; -/** +"use strict"; +/** * @author github.com/tintinweb * @license GPLv3 - * - * + * + * * */ -const vscode = require('vscode'); -const path = require('path'); -const mod_parser = require('solidity-workspace'); -const { getAstValueForExpression } = require('./symbols'); -const settings = require('../settings'); +const vscode = require("vscode"); +const path = require("path"); +const mod_parser = require("solidity-workspace"); +const { getAstValueForExpression } = require("./symbols"); +const settings = require("../settings"); + +async function decorateSourceUnit(document, editor, sourceUnit) { + const config = settings.extensionConfig(); + let decorations = []; + console.log("+ (decorate) in sourceunit: " + sourceUnit.filePath); + + // Decorate external calls + if (config.deco.warn.externalCalls) { + decorations.push( + ...sourceUnit + .getExternalCalls() + .map((c) => CreateDecoStyle.extCall(c._node)), + ); + } + + // Decorate state variables + + if (config.deco.statevars) { + for (let contract of Object.values(sourceUnit.contracts)) { + for (let svar of Object.values(contract.stateVars)) { + decorations.push( + CreateDecoStyle.stateVarDecl(svar, document, contract), + ); + + svar.extra.usedAt.forEach((ident) => { + if (ident.extra.inFunction.declarations[ident.name]) { + // Shadowed state variable + console.log("SHADOWED STATEVAR --> " + ident.name); + decorations.push( + CreateDecoStyle.shadowedStateVar(ident, document, contract, svar), + ); + let declaration = ident.extra.inFunction.declarations[ident.name]; + decorations.push( + CreateDecoStyle.shadowedStateVar( + declaration, + document, + contract, + svar, + ), + ); + } else { + // Not shadowed, decorate normally + decorations.push( + CreateDecoStyle.stateVarIdent(ident, document, contract, svar), + ); + } + }); + } + + //decorate functions + + for (let func of contract.functions) { + handleIdentifiers( + func.identifiers, + document, + contract, + settings, + decorations, + ); + } + + //decorate modifiers + for (let functionName in contract.modifiers) { + handleIdentifiers( + contract.modifiers[functionName].identifiers, + document, + contract, + settings, + decorations, + ); + } + + //decorate events + for (var eventDef of contract.events) { + if (settings.extensionConfig().deco.warn.reserved) { + checkReservedIdentifiers(eventDef.arguments, decorations); + } + } + console.log("✓ decorate scope (new) - identifier "); + } + } + setDecorations(editor, decorations); + console.log("✓ decorate scope done "); +} +function handleIdentifiers( + identifiers, + document, + contract, + settings, + decorations, +) { + let highlightIdentifiers = []; -const decoStyleRedLine = vscode.window.createTextEditorDecorationType({ - isWholeLine: true, - overviewRulerColor: settings.extensionConfig().overviewruler.decorations.enable ? 'blue' : undefined, - overviewRulerLane: settings.extensionConfig().overviewruler.decorations.enable ? vscode.OverviewRulerLane.Right : undefined, - light: { - backgroundColor: `#E8625250` - }, - dark: { - backgroundColor: `#E9190F50` - }, -}); - -// create a decorator type that we use to decorate small numbers -const decoStyleStateVar = vscode.window.createTextEditorDecorationType({ - borderWidth: '1px', - borderStyle: 'dotted', - overviewRulerColor: settings.extensionConfig().overviewruler.decorations.enable ? 'blue' : undefined, - overviewRulerLane: settings.extensionConfig().overviewruler.decorations.enable ? vscode.OverviewRulerLane.Right : undefined, - light: { - borderColor: 'DarkGoldenRod' - }, - dark: { - borderColor: 'GoldenRod' - }, -}); - -const decoStyleStateVarImmutable = vscode.window.createTextEditorDecorationType({ - borderWidth: '1px', - borderStyle: 'dotted', - overviewRulerLane: settings.extensionConfig().overviewruler.decorations.enable ? vscode.OverviewRulerLane.Right : undefined, - light: { - borderColor: 'DarkOrchid' - }, - dark: { - borderColor: 'Orchid' - }, -}); - -const decoStyleLightGreen = vscode.window.createTextEditorDecorationType({ - borderWidth: '1px', - borderStyle: 'dotted', - light: { - borderColor: 'darkgreen' - }, - dark: { - borderColor: 'green' - }, -}); - -const decoStyleLightOrange = vscode.window.createTextEditorDecorationType({ - borderWidth: '1px', - borderStyle: 'solid', - overviewRulerColor: settings.extensionConfig().overviewruler.decorations.enable ? 'red' : undefined, - overviewRulerLane: settings.extensionConfig().overviewruler.decorations.enable ? vscode.OverviewRulerLane.Right : undefined, - light: { - borderColor: 'red' - }, - dark: { - borderColor: 'red' - }, -}); - -const decoStyleLightBlue = vscode.window.createTextEditorDecorationType({ - borderWidth: '1px', - borderStyle: 'dotted', - overviewRulerColor: settings.extensionConfig().overviewruler.decorations.enable ? 'blue' : undefined, - overviewRulerLane: settings.extensionConfig().overviewruler.decorations.enable ? vscode.OverviewRulerLane.Right : undefined, - light: { - borderColor: 'darkblue' - }, - dark: { - borderColor: 'lightblue' - }, -}); - -const decoStyleBlueBoldForeground = vscode.window.createTextEditorDecorationType({ - light: { - fontWeight: 'bold', - }, - dark: { - color: 'Chocolate' - }, -}); - - -var styles = { - decoStyleStateVar: decoStyleStateVar, - decoStyleStateVarImmutable: decoStyleStateVarImmutable, - decoStyleLightGreen: decoStyleLightGreen, - decoStyleLightOrange: decoStyleLightOrange, - decoStyleLightBlue: decoStyleLightBlue, - decoStyleRedLine: decoStyleRedLine, - decoStyleBookmarkGreen: undefined, - decoStyleBookmarkRed: undefined, - decoStyleExternalCall: undefined + identifiers.forEach((ident) => { + if (ident.name === undefined) return; -}; + const is_declared_locally = + !!ident.extra.inFunction.declarations[ident.name]; + const is_state_var = !!contract.stateVars[ident.name]; -async function decorateWords(editor, words, decoStyle, commentMapper) { - if (!editor) { - return; + const is_inherited = !!( + contract.inherited_names[ident.name] && + contract.inherited_names[ident.name] != contract + ); + + if (is_declared_locally && !is_inherited && !is_state_var) { + if (ident.extra.scope === "argument" || ident.extra.scope === "super") { + highlightIdentifiers.push(ident); + } else if (ident.extra.scope === "storageRef") { + decorations.push( + CreateDecoStyle.stateVarIdent( + ident, + document, + contract, + ident.extra.declaration, + ), + ); + } else if (ident.extra.scope === "inheritedName") { + decorations.push( + CreateDecoStyle.shadowedInheritedStateVar(ident, document, contract), + ); + } + } else if ( + (is_declared_locally && is_inherited) || + (is_state_var && is_inherited) + ) { + decorations.push( + CreateDecoStyle.shadowedInheritedStateVar(ident, document, contract), + ); + } else if (is_inherited) { + decorations.push( + CreateDecoStyle.inheritedStateVar(ident, document, contract), + ); } - var smallNumbers = []; - const text = editor.document.getText(); - - words.forEach(function (word) { - //var regEx = new RegExp("\\b" +word+"\\b" ,"g"); - var regEx = new RegExp(word, "g"); - let match; - while (match = regEx.exec(text)) { - if (commentMapper && commentMapper.indexIsInComment(match.index, match.index + match[0].trim().length)) { - continue; - } - var startPos = editor.document.positionAt(match.index); - var endPos = editor.document.positionAt(match.index + match[0].trim().length); - //endPos.line = startPos.line; //hacky force - var decoration = { - range: new vscode.Range(startPos, endPos), - //isWholeLine: true, - - //hoverMessage: 'StateVar **' + match[0] + '**' - }; - smallNumbers.push(decoration); - } + }); + + if (settings.extensionConfig().deco.arguments) { + semanticHighlightFunctionParameters(highlightIdentifiers, decorations); + } + + if (settings.extensionConfig().deco.warn.reserved) { + ["identifiers", "arguments", "returns"].forEach((type) => { + checkReservedIdentifiers(identifiers[type], decorations); }); - console.log("✓ decorateWords " + words); - editor.setDecorations(decoStyle, smallNumbers); + } } -function doDeco(editor, decoArr) { - if (!editor) { - return; +/** func decs */ + +function checkReservedIdentifiers(identifiers, decorations) { + if (!identifiers) { + return; + } + + if (typeof identifiers.forEach !== "function") { + identifiers = Object.values(identifiers); + } + identifiers.forEach(function (ident) { + if (mod_parser.RESERVED_KEYWORDS.indexOf(ident.name) >= 0) { + decorations.push(mod_decorator.CreateDecoStyle.reserved(ident)); } - editor.setDecorations(decoStyleStateVar, decoArr); + }); } -function HSLtoRGB(h, s, l) { - let r, g, b; +async function setDecorations(editor, decorations) { + if (!editor) return; - const rd = (a) => { - return Math.floor(Math.max(Math.min(a * 256, 255), 0)); - }; + const decoMap = {}; - const hueToRGB = (m, n, o) => { - if (o < 0) { - o += 1; - } - if (o > 1) { - o -= 1; - } - if (o < 1 / 6) { - return m + (n - m) * 6 * o; - } - if (o < 1 / 2) { - return n; - } - if (o < 2 / 3) { - return m + (n - m) * (2 / 3 - o) * 6; - } - return m; - }; + for (const styleKey in styles) { + decoMap[styleKey] = []; + } - const q = l < 0.5 ? l * (1 + s) : l + s - l * s; - const p = 2 * l - q; + for (const deco of decorations) { + decoMap[deco.decoStyle].push(deco); + } - r = hueToRGB(p, q, h + 1 / 3); - g = hueToRGB(p, q, h); - b = hueToRGB(p, q, h - 1 / 3); - - return [rd(r), rd(g), rd(b)]; + for (const styleKey in decoMap) { + editor.setDecorations(styles[styleKey], decoMap[styleKey]); + } } -function RGBtoHex(r, g, b) { - return `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`; +async function decorateWords(editor, words, decoStyle, commentMapper) { + if (!editor) { + return; + } + var smallNumbers = []; + const text = editor.document.getText(); + + words.forEach(function (word) { + //var regEx = new RegExp("\\b" +word+"\\b" ,"g"); + var regEx = new RegExp(word, "g"); + let match; + while ((match = regEx.exec(text))) { + if ( + commentMapper && + commentMapper.indexIsInComment( + match.index, + match.index + match[0].trim().length, + ) + ) { + continue; + } + var startPos = editor.document.positionAt(match.index); + var endPos = editor.document.positionAt( + match.index + match[0].trim().length, + ); + //endPos.line = startPos.line; //hacky force + var decoration = { + range: new vscode.Range(startPos, endPos), + //isWholeLine: true, + + //hoverMessage: 'StateVar **' + match[0] + '**' + }; + smallNumbers.push(decoration); + } + }); + console.log("✓ decorateWords " + words); + editor.setDecorations(decoStyle, smallNumbers); } -var gutterIcons = {}; - - function varDecIsArray(node) { - return node && node.typeName && node.typeName.type == "ArrayTypeName"; -} - -function varDecIsUserDefined(node) { - return node && node.typeName && node.typeName.type == "UserDefinedTypeName"; + return node && node.typeName && node.typeName.type == "ArrayTypeName"; } function getVariableDeclarationType(node) { - if(!node){ - return null; - } - - if (typeof node.typeName != "undefined" && node.typeName != null) { - if (varDecIsArray(node)) { - node = node.typeName.baseTypeName; - } else { - node = node.typeName; - } - } + if (!node) { + return null; + } + + if (typeof node.typeName != "undefined" && node.typeName != null) { + node = varDecIsArray(node) ? node.typeName.baseTypeName : node.typeName; + } + + switch (node.type) { + case "ElementaryTypeName": + return node.name; + case "UserDefinedTypeName": + return node.namePath; + case "Mapping": + return `mapping( ${getVariableDeclarationType( + node.keyType, + )} => ${getVariableDeclarationType(node.valueType)} )`; + default: + return null; + } +} - if (node.type == "ElementaryTypeName") { - return node.name; - } else if (node.type == "UserDefinedTypeName") { - return node.namePath; - } else if (node.type == "Mapping") { - node.namePath = "mapping( " + getVariableDeclarationType(node.keyType) + "=>" + getVariableDeclarationType(node.valueType) + " )"; - return node.namePath; - } else { - return null; - } +function semanticHighlightFunctionParameters(arrIdents, decorations) { + if (arrIdents.length <= 0) { + return []; + } + + let funcNode = arrIdents[0].extra.inFunction; + let colorAssign = {}; + + Object.values(funcNode.arguments).forEach((ident, index) => { + if (ident.name === null) return; //skip unnamed arguments (solidity allows function a(bytes,bytes)) + colorAssign[ident.name] = "styleArgument" + ((index + 1) % 15); + let typeName = getVariableDeclarationType(ident) || ""; + + decorations.push({ + range: new vscode.Range( + new vscode.Position(ident.loc.end.line - 1, ident.loc.end.column), + new vscode.Position( + ident.loc.end.line - 1, + ident.loc.end.column + ident.name.length, + ), + ), + hoverMessage: `(*${typeName}*) **Argument** *${funcNode._node.name}*.**${ident.name}**`, + decoStyle: colorAssign[ident.name], + }); + }); + + arrIdents.forEach((ident) => { + let typeName = getVariableDeclarationType(ident.extra.declaration) || ""; + + decorations.push({ + range: new vscode.Range( + new vscode.Position(ident.loc.start.line - 1, ident.loc.start.column), + new vscode.Position( + ident.loc.end.line - 1, + ident.loc.end.column + ident.name.length, + ), + ), + hoverMessage: `(*${typeName}*) **Argument** *${funcNode._node.name}*.**${ident.name}**`, + decoStyle: colorAssign[ident.name], + }); + }); + console.log(`✓ semantic highlight - ${funcNode._node.name}`); } -function semanticHighlightFunctionParameters(arrIdents) { +//Styles - if (arrIdents.length <= 0) { - return []; +class CreateDecoStyle { + static reserved(node) { + let prefix = "**BUILTIN-RESERVED** ❗RESERVED KEYWORD❗"; + let decoStyle = "decoStyleLightOrange"; + let decl_uri = + "[more info..](https://solidity.readthedocs.io/en/latest/miscellaneous.html#reserved-keywords)"; + + return { + range: new vscode.Range( + new vscode.Position(node.loc.start.line - 1, node.loc.start.column), + new vscode.Position( + node.loc.end.line - 1, + node.loc.end.column + node.name.length, + ), + ), + hoverMessage: `${prefix}**${node.name}** (${decl_uri})`, + decoStyle: decoStyle, + }; + } + static extCall(node) { + return { + range: new vscode.Range( + new vscode.Position(node.loc.start.line - 1, node.loc.start.column), + new vscode.Position( + node.loc.start.line - 1, + node.loc.start.column + + mod_parser.parserHelpers.getAstNodeName(node.expression).length, + ), //only highlight first if extcall spans multiple lines + ), + hoverMessage: "❗**EXTCALL**❗", + decoStyle: "decoStyleExternalCall", + }; + } + static stateVarDecl(node, document, contract) { + var prefix = ""; + let knownValue = ""; + var decoStyle = "decoStyleStateVar"; + + if (node.isDeclaredConst) { + prefix = "**CONST** "; + decoStyle = "decoStyleLightGreen"; + knownValue = getAstValueForExpression(node.expression); + knownValue = knownValue ? ` = **${knownValue}** ` : ""; } - let index = 0; - let colorAssign = {}; - - let funcNode = arrIdents[0].extra.inFunction; // just take the first items ref to function - var decorations = []; + if (node.hasOwnProperty("isImmutable") && node.isImmutable) { + prefix = "**IMMUTABLE** "; + decoStyle = "decoStyleStateVarImmutable"; + } - for (let name in funcNode.arguments) { - colorAssign[name] = "styleArgument" + ((index += 1) % 15); - let ident = funcNode.arguments[name]; - if (ident.name === null) { - continue; //skip unnamed arguments (solidity allows function a(bytes,bytes)) - } - let typeName = getVariableDeclarationType(ident); - typeName = typeName ? typeName : ""; - decorations.push( - { - range: new vscode.Range( - new vscode.Position(ident.loc.end.line - 1, ident.loc.end.column), - new vscode.Position(ident.loc.end.line - 1, ident.loc.end.column + ident.name.length) - ), - hoverMessage: "(*" + typeName + "*) " + '**Argument** *' + funcNode._node.name + "*.**" + ident.name + '**', - decoStyle: colorAssign[ident.name] - }); + return { + range: new vscode.Range( + new vscode.Position( + node.identifier.loc.start.line - 1, + node.identifier.loc.start.column, + ), + new vscode.Position( + node.identifier.loc.end.line - 1, + node.identifier.loc.end.column + node.identifier.name.length, + ), + ), + hoverMessage: `${prefix}(*${ + node.typeName.type == "ElementaryTypeName" + ? node.typeName.name + : node.typeName.namePath + }*) StateVar *${contract.name}*.**${node.identifier.name}**`, + decoStyle: decoStyle, + }; + } + static stateVarIdent(node, document, contract, svar) { + var prefix = ""; + let knownValue = ""; + var decoStyle = "decoStyleStateVar"; + + let decl_uri = `([Declaration: #${svar.loc.start.line}](${document.uri}#${svar.loc.start.line}))`; + + if (svar.isDeclaredConst) { + prefix = "**CONST** "; + decoStyle = "decoStyleLightGreen"; + knownValue = getAstValueForExpression(svar.expression); + knownValue = knownValue ? ` = **${knownValue}** ` : ""; } + if (svar.hasOwnProperty("isImmutable") && svar.isImmutable) { + prefix = "**IMMUTABLE** "; + decoStyle = "decoStyleStateVarImmutable"; + } - arrIdents.forEach(function (ident) { - let typeName = getVariableDeclarationType(ident.extra.declaration); - decorations.push( - { - range: new vscode.Range( - new vscode.Position(ident.loc.start.line - 1, ident.loc.start.column), - new vscode.Position(ident.loc.end.line - 1, ident.loc.end.column + ident.name.length) - ), - hoverMessage: "(*" + typeName + "*) " + '**Argument** *' + funcNode._node.name + "*.**" + ident.name + '**', - decoStyle: colorAssign[ident.name] - }); + return { + range: new vscode.Range( + new vscode.Position(node.loc.start.line - 1, node.loc.start.column), + new vscode.Position( + node.loc.end.line - 1, + node.loc.end.column + node.name.length, + ), + ), + hoverMessage: `${prefix}(*${ + svar.typeName.type == "ElementaryTypeName" + ? svar.typeName.name + : svar.typeName.namePath + }*) **StateVar** *${contract.name}*.**${ + svar.name + }**${knownValue} ${decl_uri}`, + decoStyle: decoStyle, + }; + } + static shadowedStateVar(node, document, contract, declaration, prefix) { + let decoStyle = "decoStyleLightOrange"; + prefix = prefix || "❗SHADOWED❗"; + let decl_uri = + "([Declaration: #" + + declaration.loc.start.line + + "](" + + document.uri + + "#" + + declaration.loc.start.line + + "))"; + + return { + range: new vscode.Range( + new vscode.Position(node.loc.start.line - 1, node.loc.start.column), + new vscode.Position( + node.loc.end.line - 1, + node.loc.end.column + node.name.length, + ), + ), + hoverMessage: `${prefix}(*${ + declaration.typeName.type == "ElementaryTypeName" + ? declaration.typeName.name + : declaration.typeName.namePath + }*) **StateVar** *${contract.name}*.**${declaration.name}** ${decl_uri}`, + decoStyle: decoStyle, + }; + } + static shadowedInheritedStateVar(node, document, contract, declaration) { + let decoStyle = "decoStyleLightOrange"; + let prefix = "**INHERITED** ❗SHADOWED❗"; + declaration = declaration || node; + let decl_uri = `([Declaration: #${node.loc.start.line}](${document.uri}#${node.loc.start.line}))`; + let knownType = "undef"; + + let subcontract = contract.inherited_names[node.name]; + if (subcontract) { + let foreignSourceUnit = subcontract._parent; + let uri = vscode.Uri.file(foreignSourceUnit.filePath); + declaration = subcontract.names[node.name]._node || node; + decl_uri = `([Declaration: ${subcontract.name}#${declaration.loc.start.line}](${uri}#${declaration.loc.start.line}))`; + knownType = getVariableDeclarationType(declaration); + } + return { + range: new vscode.Range( + new vscode.Position(node.loc.start.line - 1, node.loc.start.column), + new vscode.Position( + node.loc.end.line - 1, + node.loc.end.column + node.name.length, + ), + ), + hoverMessage: `${prefix}(*${knownType}*) **StateVar** *${subcontract.name}*.**${node.name}** ${decl_uri}`, + decoStyle: decoStyle + }; + } + static inheritedStateVar(node, document, contract, declaration) { + let decoStyle = "decoStyleLightBlue"; + let prefix = "**INHERITED** "; + declaration = declaration || node; + let decl_uri = `([Declaration: #${declaration.loc.start.line}](${document.uri}#${declaration.loc.start.line}))`; + let knownType = getVariableDeclarationType(declaration); + + let subcontract = contract.inherited_names[node.name]; + if (subcontract) { + let foreignSourceUnit = subcontract._parent; + let uri = vscode.Uri.file(foreignSourceUnit.filePath); + declaration = subcontract.names[node.name] || node; + declaration = declaration.hasOwnProperty("_node") + ? declaration._node + : declaration; + decl_uri = `([Declaration: ${subcontract.name}#${declaration.loc.start.line}](${uri}#${declaration.loc.start.line}))`; + knownType = getVariableDeclarationType(declaration); + } - }); - console.log("✓ semantic highlight - " + funcNode._node.name); - return decorations; + return { + range: new vscode.Range( + new vscode.Position(node.loc.start.line - 1, node.loc.start.column), + new vscode.Position( + node.loc.end.line - 1, + node.loc.end.column + node.name.length, + ), + ), + hoverMessage: `${prefix}(*${knownType || "?"}*) **StateVar** *${ + subcontract ? subcontract.name : "Unknown" + }*.**${node.name}** ${decl_uri}`, + decoStyle: decoStyle, + }; + } } -function init(context) { - - styles.decoStyleExternalCall = vscode.window.createTextEditorDecorationType({ - gutterIconPath: context.asAbsolutePath(path.join("images", "warning.svg")), - gutterIconSize: "50%", - }); +var gutterIcons = {}; +var styles = {}; +function init(context) { + styles.decoStyleExternalCall = vscode.window.createTextEditorDecorationType({ + gutterIconPath: context.asAbsolutePath(path.join("images", "warning.svg")), + gutterIconSize: "50%", + }); + + const decoSuffix = + settings.extensionConfig().deco.argumentsMode != "color only" + ? settings.extensionConfig().deco.argumentsSuffix + : undefined; + const shouldHighlightArg = + settings.extensionConfig().deco.argumentsMode != "symbol only"; + + for (let idx = 0; idx < 15; idx++) { + const hue = (((5 + idx) * 19) % 255) / 255; + + const lightBackground = shouldHighlightArg + ? RGBtoHex(...HSLtoRGB(hue, 0.85, 0.75)) + "50" + : undefined; + + const darkBackground = shouldHighlightArg + ? RGBtoHex(...HSLtoRGB((((8 + idx) * 19) % 255) / 255, 0.99, 0.55)) + "30" + : undefined; + + const afterColor = RGBtoHex(...HSLtoRGB(hue, 0.85, 0.75)) + "95"; + + styles[`styleArgument${idx}`] = + vscode.window.createTextEditorDecorationType({ + wholeLine: false, + light: { backgroundColor: lightBackground }, + dark: { backgroundColor: darkBackground }, + after: { + contentText: decoSuffix, + fontStyle: "normal", + color: afterColor, + }, + }); + } - const decoSuffix = settings.extensionConfig().deco.argumentsMode != "color only" ? settings.extensionConfig().deco.argumentsSuffix : undefined; - const shouldHighlightArg = settings.extensionConfig().deco.argumentsMode != "symbol only"; - - [...Array(15).keys()].forEach(function (idx) { - styles["styleArgument" + idx] = vscode.window.createTextEditorDecorationType({ - //cursor: 'crosshair', - // use a themable color. See package.json for the declaration and default values. - wholeLine: false, - light: { - - backgroundColor: shouldHighlightArg ? RGBtoHex(...HSLtoRGB(((5 + idx) * 19) % 255 / 255, 0.85, 0.75)) + "50" : undefined - }, - dark: { - - backgroundColor: shouldHighlightArg ? RGBtoHex(...HSLtoRGB(((8 + idx) * 19) % 255 / 255, 0.99, 0.55)) + "30" : undefined - //color: RGBtoHex(...HSLtoRGB(((6+idx)*19)%255/255, 0.85, 0.75))+"95", - //textDecoration: "underline" + RGBtoHex(...HSLtoRGB(((6+idx)*19)%255/255, 0.85, 0.75))+"95" - }, - after: { - contentText: decoSuffix || undefined, - fontStyle: "normal", - color: RGBtoHex(...HSLtoRGB(((6 + idx) * 19) % 255 / 255, 0.85, 0.75)) + "95" - } - }); - }); + gutterIcons.red = context.asAbsolutePath("images/bookmark-red.svg"); + gutterIcons.green = context.asAbsolutePath("images/bookmark-green.svg"); + gutterIcons.blue = context.asAbsolutePath("images/bookmark-blue.svg"); + gutterIcons.issue = context.asAbsolutePath("images/bookmark-issue.svg"); - gutterIcons.red = context.asAbsolutePath("images/bookmark-red.svg"); - gutterIcons.green = context.asAbsolutePath("images/bookmark-green.svg"); - gutterIcons.blue = context.asAbsolutePath("images/bookmark-blue.svg"); - gutterIcons.issue = context.asAbsolutePath("images/bookmark-issue.svg"); + const createBookmarkDecorationType = (gutterIconPath) => { + return vscode.window.createTextEditorDecorationType({ + gutterIconPath, - styles.decoStyleBookmarkRed = vscode.window.createTextEditorDecorationType({ - gutterIconPath: gutterIcons.red, - light: { + light: { + fontWeight: "bold", + }, - //color: 'GoldenRod', - fontWeight: 'bold', - //backgroundColor: 'DarkSlateGray' - }, - dark: { - - color: 'Chocolate', - //backgroundColor: 'Black', - //fontWeight: 'bold', - //textDecoration: 'underline overline #FF3028', - //borderColor: 'GoldenRod', - //borderStyle: 'solid', - //borderWidth: '0.1px' - }, - /* - after: { - textDecoration: "underline overline #FF3028", - contentText: "<--" - - } - */ + dark: { + color: "Chocolate", + }, }); - styles.decoStyleBookmarkGreen = vscode.window.createTextEditorDecorationType({ - gutterIconPath: gutterIcons.green, - light: { - - //color: 'GoldenRod', - fontWeight: 'bold', - //backgroundColor: 'DarkSlateGray' - }, - dark: { - - color: 'Chocolate', - //backgroundColor: 'Black', - //fontWeight: 'bold', - //textDecoration: 'underline overline #FF3028', - //borderColor: 'GoldenRod', - //borderStyle: 'solid', - //borderWidth: '0.1px' - }, - /* - after: { - textDecoration: "underline overline #FF3028", - contentText: "<--" - - } - */ - }); - styles.decoStyleBookmarkBlue = vscode.window.createTextEditorDecorationType({ - gutterIconPath: gutterIcons.blue, - light: { - - //color: 'GoldenRod', - fontWeight: 'bold', - //backgroundColor: 'DarkSlateGray' - }, - dark: { - - color: 'Chocolate', - //backgroundColor: 'Black', - //fontWeight: 'bold', - //textDecoration: 'underline overline #FF3028', - //borderColor: 'GoldenRod', - //borderStyle: 'solid', - //borderWidth: '0.1px' - }, - /* - after: { - textDecoration: "underline overline #FF3028", - contentText: "<--" - - } - */ + }; + + styles.decoStyleBookmarkRed = createBookmarkDecorationType(gutterIcons.red); + styles.decoStyleBookmarkGreen = createBookmarkDecorationType( + gutterIcons.green, + ); + styles.decoStyleBookmarkBlue = createBookmarkDecorationType(gutterIcons.blue); + styles.decoStyleBookmarkIssue = createBookmarkDecorationType( + gutterIcons.issue, + ); + + const createDecorationType = (options) => { + const { + isWholeLine, + borderColor, + borderStyle, + backgroundColor, + gutterIconPath, + } = options; + + return vscode.window.createTextEditorDecorationType({ + isWholeLine, + borderWidth: "1px", + borderStyle: borderStyle || "dotted", + overviewRulerColor: settings.extensionConfig().overviewruler.decorations + .enable + ? borderColor || "blue" + : undefined, + overviewRulerLane: settings.extensionConfig().overviewruler.decorations + .enable + ? vscode.OverviewRulerLane.Right + : undefined, + light: { + borderColor: borderColor || "DarkGoldenRod", + backgroundColor, + }, + dark: { + borderColor: borderColor || "GoldenRod", + backgroundColor, + }, + gutterIconPath, }); - styles.decoStyleBookmarkIssue = vscode.window.createTextEditorDecorationType({ - gutterIconPath: gutterIcons.issue, - light: { + }; - //color: 'GoldenRod', - fontWeight: 'bold', - //backgroundColor: 'DarkSlateGray' - }, - dark: { - - color: 'Chocolate', - //backgroundColor: 'Black', - //fontWeight: 'bold', - //textDecoration: 'underline overline #FF3028', - //borderColor: 'GoldenRod', - //borderStyle: 'solid', - //borderWidth: '0.1px' - }, - /* - after: { - textDecoration: "underline overline #FF3028", - contentText: "<--" - - } - */ - }); + styles.decoStyleRedLine = createDecorationType({ + isWholeLine: true, + backgroundColor: { light: "#E8625250", dark: "#E9190F50" }, + }); + styles.decoStyleStateVar = createDecorationType({ + borderColor: "DarkGoldenRod", + }); + styles.decoStyleStateVarImmutable = createDecorationType({ + borderColor: "DarkOrchid", + }); + styles.decoStyleLightGreen = createDecorationType({ + borderColor: "darkgreen", + }); + styles.decoStyleLightOrange = createDecorationType({ + borderColor: "red", + borderStyle: "solid", + }); + styles.decoStyleLightBlue = createDecorationType({ borderColor: "darkblue" }); } -class CreateDecoStyle { - static reserved(node) { - let prefix = "**BUILTIN-RESERVED** ❗RESERVED KEYWORD❗"; - let decoStyle = "decoStyleLightOrange"; - let decl_uri = "[more info..](https://solidity.readthedocs.io/en/latest/miscellaneous.html#reserved-keywords)"; - - return { - range: new vscode.Range( - new vscode.Position(node.loc.start.line - 1, node.loc.start.column), - new vscode.Position(node.loc.end.line - 1, node.loc.end.column + node.name.length) - ), - hoverMessage: prefix + "**" + node.name + '**' + " (" + decl_uri + ")", - decoStyle: decoStyle - }; - } - static extCall(node) { - return { - range: new vscode.Range( - new vscode.Position(node.loc.start.line - 1, node.loc.start.column), - new vscode.Position(node.loc.start.line - 1, node.loc.start.column + mod_parser.parserHelpers.getAstNodeName(node.expression).length) //only highlight first if extcall spans multiple lines - ), - hoverMessage: "❗**EXTCALL**❗", - decoStyle: "decoStyleExternalCall" - }; - } - static stateVarDecl(node, document, contract) { - var prefix = ""; - let knownValue = ""; - var decoStyle = "decoStyleStateVar"; - - let decl_uri = "([Declaration: #" + (node.loc.start.line) + "](" + document.uri + "#" + (node.loc.start.line) + "))"; - - if (node.isDeclaredConst) { - prefix = "**CONST** "; - decoStyle = "decoStyleLightGreen"; - knownValue = getAstValueForExpression(node.expression); - knownValue = knownValue ? ` = **${knownValue}** ` : ''; - } +//utils - if (node.hasOwnProperty('isImmutable') && node.isImmutable) { - prefix = "**IMMUTABLE** "; - decoStyle = "decoStyleStateVarImmutable"; - } - - return { - range: new vscode.Range( - new vscode.Position(node.identifier.loc.start.line - 1, node.identifier.loc.start.column), - new vscode.Position(node.identifier.loc.end.line - 1, node.identifier.loc.end.column + node.identifier.name.length) - ), - hoverMessage: prefix + "(*" + (node.typeName.type == "ElementaryTypeName" ? node.typeName.name : node.typeName.namePath) + "*) " + 'StateVar *' + contract.name + "*.**" + node.identifier.name + '**', - decoStyle: decoStyle - }; - } - static stateVarIdent(node, document, contract, svar) { - var prefix = ""; - let knownValue = ""; - var decoStyle = "decoStyleStateVar"; - - let decl_uri = "([Declaration: #" + (svar.loc.start.line) + "](" + document.uri + "#" + (svar.loc.start.line) + "))"; - - if (svar.isDeclaredConst) { - prefix = "**CONST** "; - decoStyle = "decoStyleLightGreen"; - knownValue = getAstValueForExpression(svar.expression); - knownValue = knownValue ? ` = **${knownValue}** ` : ''; - } +function HSLtoRGB(h, s, l) { + let r, g, b; - if (svar.hasOwnProperty('isImmutable') && svar.isImmutable) { - prefix = "**IMMUTABLE** "; - decoStyle = "decoStyleStateVarImmutable"; - } + const rd = (a) => { + return Math.floor(Math.max(Math.min(a * 256, 255), 0)); + }; - return { - range: new vscode.Range( - new vscode.Position(node.loc.start.line - 1, node.loc.start.column), - new vscode.Position(node.loc.end.line - 1, node.loc.end.column + node.name.length) - ), - hoverMessage: prefix + "(*" + (svar.typeName.type == "ElementaryTypeName" ? svar.typeName.name : svar.typeName.namePath) + "*) " + '**StateVar** *' + contract.name + "*.**" + svar.name + '**' + knownValue + " " + decl_uri, - decoStyle: decoStyle - }; + const hueToRGB = (m, n, o) => { + if (o < 0) { + o += 1; } - static shadowedStateVar(node, document, contract, declaration, prefix) { - let decoStyle = "decoStyleLightOrange"; - prefix = prefix || "❗SHADOWED❗"; - let decl_uri = "([Declaration: #" + (declaration.loc.start.line) + "](" + document.uri + "#" + (declaration.loc.start.line) + "))"; - - return { - range: new vscode.Range( - new vscode.Position(node.loc.start.line - 1, node.loc.start.column), - new vscode.Position(node.loc.end.line - 1, node.loc.end.column + node.name.length) - ), - hoverMessage: prefix + "(*" + (declaration.typeName.type == "ElementaryTypeName" ? declaration.typeName.name : declaration.typeName.namePath) + "*) " + '**StateVar** *' + contract.name + "*.**" + declaration.name + '**' + " " + decl_uri, - decoStyle: decoStyle - }; + if (o > 1) { + o -= 1; } - static shadowedInheritedStateVar(node, document, contract, declaration) { - let decoStyle = "decoStyleLightOrange"; - let prefix = "**INHERITED** ❗SHADOWED❗"; - declaration = declaration || node; - let decl_uri = "([Declaration: #" + (node.loc.start.line) + "](" + document.uri + "#" + (node.loc.start.line) + "))"; - let knownType = "undef"; - - let subcontract = contract.inherited_names[node.name]; - if (subcontract) { - let foreignSourceUnit = subcontract._parent; - let uri = vscode.Uri.file(foreignSourceUnit.filePath); - declaration = subcontract.names[node.name]._node || node; - decl_uri = "([Declaration: " + subcontract + "#" + (declaration.loc.start.line) + "](" + uri + "#" + (declaration.loc.start.line) + "))"; - knownType = getVariableDeclarationType(declaration); - } + if (o < 1 / 6) { + return m + (n - m) * 6 * o; + } + if (o < 1 / 2) { + return n; + } + if (o < 2 / 3) { + return m + (n - m) * (2 / 3 - o) * 6; + } + return m; + }; + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; + const p = 2 * l - q; - return { - range: new vscode.Range( - new vscode.Position(node.loc.start.line - 1, node.loc.start.column), - new vscode.Position(node.loc.end.line - 1, node.loc.end.column + node.name.length) - ), - hoverMessage: prefix + "(*" + knownType + "*) " + '**StateVar** *' + subcontract.name + "*.**" + node.name + '**' + " " + decl_uri, - decoStyle: decoStyle - }; - } - static inheritedStateVar(node, document, contract, declaration) { - let decoStyle = "decoStyleLightBlue"; - let prefix = "**INHERITED** "; - declaration = declaration || node; - let decl_uri = "([Declaration: #" + (declaration.loc.start.line) + "](" + document.uri + "#" + (declaration.loc.start.line) + "))"; - let knownType = getVariableDeclarationType(declaration); - - let subcontract = contract.inherited_names[node.name]; - if (subcontract) { - let foreignSourceUnit = subcontract._parent; - let uri = vscode.Uri.file(foreignSourceUnit.filePath); - declaration = subcontract.names[node.name] || node; - declaration = declaration.hasOwnProperty("_node") ? declaration._node : declaration; - decl_uri = "([Declaration: " + subcontract.name + "#" + (declaration.loc.start.line) + "](" + uri + "#" + (declaration.loc.start.line) + "))"; - knownType = getVariableDeclarationType(declaration); - } + r = hueToRGB(p, q, h + 1 / 3); + g = hueToRGB(p, q, h); + b = hueToRGB(p, q, h - 1 / 3); - return { - range: new vscode.Range( - new vscode.Position(node.loc.start.line - 1, node.loc.start.column), - new vscode.Position(node.loc.end.line - 1, node.loc.end.column + node.name.length) - ), - hoverMessage: prefix + "(*" + (knownType || "?") + "*) " + '**StateVar** *' + (subcontract ? subcontract.name : "Unknown") + "*.**" + node.name + '**' + " " + decl_uri, - decoStyle: decoStyle - }; - } + return [rd(r), rd(g), rd(b)]; } +function RGBtoHex(r, g, b) { + return `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`; +} module.exports = { - init: init, - decoStyleStateVar: decoStyleStateVar, - styles: styles, - doDeco: doDeco, - decorateWords: decorateWords, - semanticHighlightFunctionParameters: semanticHighlightFunctionParameters, - CreateDecoStyle: CreateDecoStyle -}; \ No newline at end of file + init: init, + decorateSourceUnit: decorateSourceUnit, +}; diff --git a/src/features/genericDiag.js b/src/features/genericDiag.js index dac1215..d598dcf 100644 --- a/src/features/genericDiag.js +++ b/src/features/genericDiag.js @@ -1,84 +1,92 @@ -'use strict'; -/** +"use strict"; +/** * @author github.com/tintinweb * @license GPLv3 - * - * + * + * * */ /** imports */ -const vscode = require('vscode'); -const fs = require('fs'); -const path = require('path'); -const crypto = require('crypto'); +const vscode = require("vscode"); +const fs = require("fs"); +const path = require("path"); +const crypto = require("crypto"); const fileHashes = {}; const toVscodeSeverity = { - critical: vscode.DiagnosticSeverity.Error, - major: vscode.DiagnosticSeverity.Error, - minor: vscode.DiagnosticSeverity.Warning, - info: vscode.DiagnosticSeverity.Information + critical: vscode.DiagnosticSeverity.Error, + major: vscode.DiagnosticSeverity.Error, + minor: vscode.DiagnosticSeverity.Warning, + info: vscode.DiagnosticSeverity.Information, }; -function fileDidChange(path, input){ - let hash = crypto.createHash('sha1').update(input).digest('base64'); - if(fileHashes[path] && hash===fileHashes[path]){ - return false; - } - fileHashes[path] = hash; - return true; +function fileDidChange(path, input) { + let hash = crypto.createHash("sha1").update(input).digest("base64"); + if (fileHashes[path] && hash === fileHashes[path]) { + return false; + } + fileHashes[path] = hash; + return true; } /** classdec */ class DiliDiagnosticCollection { - constructor(context, base, issueFileGlob) { - this.context = context; - this.collections = {}; - this.issueFileGlob = issueFileGlob ? issueFileGlob : ["**/*-issues.json", "*-issues.json"]; - this.base = base; - this.running = 0; - } - - newCollection(name) { - if(!this.collections.hasOwnProperty(name)){ - this.collections[name] = vscode.languages.createDiagnosticCollection(name); - this.context.subscriptions.push(this.collections[name]); - } - return this.collections[name]; - } - - getCollection(name) { - return this.collections[name]; - } - - clearAll() { - Object.values(this.collections).forEach(function(ob){ - ob.clear(); - },this); + constructor(context, base, issueFileGlob) { + this.context = context; + this.collections = {}; + this.issueFileGlob = issueFileGlob + ? issueFileGlob + : ["**/*-issues.json", "*-issues.json"]; + this.base = base; + this.running = 0; + } + + newCollection(name) { + if (!this.collections.hasOwnProperty(name)) { + this.collections[name] = + vscode.languages.createDiagnosticCollection(name); + this.context.subscriptions.push(this.collections[name]); } + return this.collections[name]; + } + + getCollection(name) { + return this.collections[name]; + } + + clearAll() { + Object.values(this.collections).forEach(function (ob) { + ob.clear(); + }, this); + } + + async updateIssues(cancellationToken) { + return new Promise((resolve, reject) => { + var that = this; + + try { + vscode.workspace + .findFiles( + "**/*-issues.json", + "**/node_modules", + 100, + cancellationToken, + ) + .then((uris) => { + uris.forEach(function (uri) { + let f = uri.fsPath; + let basedir = path.dirname(f); + let collectionName = f; // path.basename(f) + + try { + let content = fs.readFileSync(f); + if (!fileDidChange(f, content)) { + return; + } - async updateIssues(cancellationToken) { - return new Promise((resolve, reject) => { - var that = this; - - try { - vscode.workspace.findFiles("**/*-issues.json",'**/node_modules', 100, cancellationToken) - .then((uris) => { - uris.forEach(function(uri){ - let f = uri.fsPath; - let basedir = path.dirname(f); - let collectionName = f; // path.basename(f) - - - try { - let content = fs.readFileSync(f); - if(!fileDidChange(f, content)){ - return; - } - - //collection.clear() //only reload this collection - var issues = JSON.parse(content); - /* + //collection.clear() //only reload this collection + var issues = JSON.parse(content); + /* {"onInputFile": "contracts/BountiesMetaTxRelayer.sol", "atLineNr": "10", "ruleType": "code_smell", @@ -89,61 +97,65 @@ class DiliDiagnosticCollection { "message": "State Variable Default Visibility - It is best practice to set the visibility of state variables explicitly. The default visibility for \"bountiesContract\" is internal. Other possible visibility values are public and private.", "forRule": "State_Variable_Default_Visibility"} */ - let pathToIssues = new Map(); - let pathToUri = new Map(); - - issues.forEach(function(issue){ - //abspath or relpath? - let targetFileUri = issue.onInputFile.startsWith("/") ? issue.onInputFile : vscode.Uri.file(path.join(basedir,issue.onInputFile)); - - if(!fs.existsSync(targetFileUri.fsPath)){ - // skip nonexistent files - // todo: maybe skip node_modules? - //console.error(targetFileUri.fsPath) - return; - } - - if(!pathToIssues.has(targetFileUri.fsPath)){ - pathToIssues.set(targetFileUri.fsPath,[]); - } - pathToUri.set(targetFileUri.fsPath, targetFileUri); - pathToIssues.get(targetFileUri.fsPath).push({ - code: '', - message: `${issue.linterName}/${issue.severity}/${issue.ruleType} - ${issue.message}`, - range: new vscode.Range(new vscode.Position(issue.atLineNr - 1, 0), new vscode.Position(issue.atLineNr - 1, 255)), - severity: toVscodeSeverity[issue.severity], - source: "", - relatedInformation: [] - - }); - }); - - if(cancellationToken.isCancellationRequested){ - throw cancellationToken; - } - - let collection = that.newCollection(collectionName); - pathToIssues.forEach(function(value, key){ - collection.set(pathToUri.get(key), value); - }); - - } catch (err) { - console.warn(f); - console.warn(err); - } - }); + let pathToIssues = new Map(); + let pathToUri = new Map(); + + issues.forEach(function (issue) { + //abspath or relpath? + let targetFileUri = issue.onInputFile.startsWith("/") + ? issue.onInputFile + : vscode.Uri.file(path.join(basedir, issue.onInputFile)); + + if (!fs.existsSync(targetFileUri.fsPath)) { + // skip nonexistent files + // todo: maybe skip node_modules? + //console.error(targetFileUri.fsPath) + return; + } + + if (!pathToIssues.has(targetFileUri.fsPath)) { + pathToIssues.set(targetFileUri.fsPath, []); + } + pathToUri.set(targetFileUri.fsPath, targetFileUri); + pathToIssues.get(targetFileUri.fsPath).push({ + code: "", + message: `${issue.linterName}/${issue.severity}/${issue.ruleType} - ${issue.message}`, + range: new vscode.Range( + new vscode.Position(issue.atLineNr - 1, 0), + new vscode.Position(issue.atLineNr - 1, 255), + ), + severity: toVscodeSeverity[issue.severity], + source: "", + relatedInformation: [], + }); }); - resolve(); - } catch (err) { - reject(err); - if (typeof err !=="object"){ //CancellationToken - throw err; + + if (cancellationToken.isCancellationRequested) { + throw cancellationToken; } - } - }); - } + + let collection = that.newCollection(collectionName); + pathToIssues.forEach(function (value, key) { + collection.set(pathToUri.get(key), value); + }); + } catch (err) { + console.warn(f); + console.warn(err); + } + }); + }); + resolve(); + } catch (err) { + reject(err); + if (typeof err !== "object") { + //CancellationToken + throw err; + } + } + }); + } } module.exports = { - DiliDiagnosticCollection:DiliDiagnosticCollection -}; \ No newline at end of file + DiliDiagnosticCollection: DiliDiagnosticCollection, +}; diff --git a/src/features/hover.js b/src/features/hover.js index 56f9e4f..6791717 100644 --- a/src/features/hover.js +++ b/src/features/hover.js @@ -1,128 +1,148 @@ -'use strict'; -/** +"use strict"; +/** * @author github.com/tintinweb * @license GPLv3 - * - * + * + * * */ -const vscode = require('vscode'); +const vscode = require("vscode"); -const builtinsArr = require('./hover/builtins.json'); -const asmArr = require('./hover/asm.json'); -const settings = require('../settings.js'); +const builtinsArr = require("./hover/builtins.json"); +const asmArr = require("./hover/asm.json"); +const settings = require("../settings.js"); function createHover(name, snippet, type) { - var text = []; - - if (isSet(snippet.instr_args) || isSet(snippet.instr_returns)){ - text.push("_asm_ :: __" + name + "__ (" + snippet.instr_args.join(", ") + ")" +(isSet(snippet.instr_returns) ? " : "+snippet.instr_returns.join(", ") :"")); - } - - if (text.length>0) { - text.push(""); - } - if (isSet(snippet.instr_gas)){ - text.push("__⟶__ gas (min): " + snippet.instr_gas); - } - if (isSet(snippet.instr_fork)){ - text.push("__⟶__ since: " + snippet.instr_fork); - } - - if (text.length>0) { - text.push(""); - } - if (isSet(snippet.example)){ - text.push(snippet.example); - } - - if (text.length>0) { - text.push(""); - } - if (isSet(snippet.description)){ - var txt_descr = snippet.description instanceof Array? snippet.description.join("\n ") : snippet.description; - text.push("💡 " + txt_descr); - } - - if (text.length>0) { - text.push(""); - } - if (isSet(snippet.security)){ - text.push(""); - var txt_security = snippet.security instanceof Array? snippet.security.join("\n* ❗") : snippet.security; - text.push("* ❗ " + txt_security); - } - - if (text.length>0) { - text.push(""); - } - if (isSet(snippet.reference)){ - text.push("🌎 [more...](" + snippet.reference+")"); - } - - //const commentCommandUri = vscode.Uri.parse(`command:editor.action.addCommentLine`); - //text.push("[Add comment](${commentCommandUri})") - const contents = new vscode.MarkdownString(text.join(" \n")); - contents.isTrusted = true; - return new vscode.Hover(contents); - - /* + var text = []; + + if (isSet(snippet.instr_args) || isSet(snippet.instr_returns)) { + text.push( + "_asm_ :: __" + + name + + "__ (" + + snippet.instr_args.join(", ") + + ")" + + (isSet(snippet.instr_returns) + ? " : " + snippet.instr_returns.join(", ") + : ""), + ); + } + + if (text.length > 0) { + text.push(""); + } + if (isSet(snippet.instr_gas)) { + text.push("__⟶__ gas (min): " + snippet.instr_gas); + } + if (isSet(snippet.instr_fork)) { + text.push("__⟶__ since: " + snippet.instr_fork); + } + + if (text.length > 0) { + text.push(""); + } + if (isSet(snippet.example)) { + text.push(snippet.example); + } + + if (text.length > 0) { + text.push(""); + } + if (isSet(snippet.description)) { + var txt_descr = + snippet.description instanceof Array + ? snippet.description.join("\n ") + : snippet.description; + text.push("💡 " + txt_descr); + } + + if (text.length > 0) { + text.push(""); + } + if (isSet(snippet.security)) { + text.push(""); + var txt_security = + snippet.security instanceof Array + ? snippet.security.join("\n* ❗") + : snippet.security; + text.push("* ❗ " + txt_security); + } + + if (text.length > 0) { + text.push(""); + } + if (isSet(snippet.reference)) { + text.push("🌎 [more...](" + snippet.reference + ")"); + } + + //const commentCommandUri = vscode.Uri.parse(`command:editor.action.addCommentLine`); + //text.push("[Add comment](${commentCommandUri})") + const contents = new vscode.MarkdownString(text.join(" \n")); + contents.isTrusted = true; + return new vscode.Hover(contents); + + /* return new vscode.Hover({ language: type, value: text.join("\n") }); */ - function isSet(val){ - return typeof val != "undefined" && val != ""; - } + function isSet(val) { + return typeof val != "undefined" && val != ""; + } } function provideHoverHandler(document, position, token, type, g_workspace) { - if (settings.extensionConfig().hover === false) { - return; - } + if (settings.extensionConfig().hover === false) { + return; + } - return builtInsHoverHandler(document, position, token, type, g_workspace); + return builtInsHoverHandler(document, position, token, type, g_workspace); } - function builtInsHoverHandler(document, position, token, type, g_workspace) { - - const range = document.getWordRangeAtPosition(position, /(tx\.gasprice|tx\.origin|msg\.data|msg\.sender|msg\.sig|msg\.value|block\.coinbase|block\.difficulty|block\.gaslimit|block\.number|block\.timestamp|abi\.encodePacked|abi\.encodeWithSelector|abi\.encodeWithSignature|abi\.decode|abi\.encode|\.?[0-9_\w>]+)/); - if (!range || range.length<=0) { - return; - } - - const sourceUnit = g_workspace.sourceUnits[document.uri.fsPath]; - if(!sourceUnit || sourceUnit.commentMapper && sourceUnit.commentMapper.isRangeOffsetInComment(document.offsetAt(range.start), document.offsetAt(range.end))){ - return; // is in comment - } - - const word = document.getText(range); - - if(token.isCancellationRequested){ - return token; - } - - for (const snippet in builtinsArr) { - if ( - builtinsArr[snippet].prefix == word || - builtinsArr[snippet].hover == word - ) { - return createHover(snippet, builtinsArr[snippet], type); - } - } - - for (const snippet in asmArr) { - if ( - asmArr[snippet].prefix == word || - asmArr[snippet].hover == word - ) { - return createHover(snippet, asmArr[snippet], type); - } - } + const range = document.getWordRangeAtPosition( + position, + /(tx\.gasprice|tx\.origin|msg\.data|msg\.sender|msg\.sig|msg\.value|block\.coinbase|block\.difficulty|block\.gaslimit|block\.number|block\.timestamp|abi\.encodePacked|abi\.encodeWithSelector|abi\.encodeWithSignature|abi\.decode|abi\.encode|\.?[0-9_\w>]+)/, + ); + if (!range || range.length <= 0) { + return; + } + + const sourceUnit = g_workspace.sourceUnits[document.uri.fsPath]; + if ( + !sourceUnit || + (sourceUnit.commentMapper && + sourceUnit.commentMapper.isRangeOffsetInComment( + document.offsetAt(range.start), + document.offsetAt(range.end), + )) + ) { + return; // is in comment + } + + const word = document.getText(range); + + if (token.isCancellationRequested) { + return token; + } + + for (const snippet in builtinsArr) { + if ( + builtinsArr[snippet].prefix == word || + builtinsArr[snippet].hover == word + ) { + return createHover(snippet, builtinsArr[snippet], type); + } + } + + for (const snippet in asmArr) { + if (asmArr[snippet].prefix == word || asmArr[snippet].hover == word) { + return createHover(snippet, asmArr[snippet], type); + } + } } module.exports = { - provideHoverHandler:provideHoverHandler + provideHoverHandler: provideHoverHandler, }; diff --git a/src/features/hover/asm.json b/src/features/hover/asm.json index 11865be..4b65635 100644 --- a/src/features/hover/asm.json +++ b/src/features/hover/asm.json @@ -1,2166 +1,1840 @@ { - "add": { - "description": "Addition operation.", - "instr_args": [ - "a", - "b" - ], - "instr_category": "arithmetic", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 1, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "add" - }, - "addmod": { - "description": "Modulo addition operation", - "instr_args": [ - "a", - "b", - "mod" - ], - "instr_category": "arithmetic", - "instr_fork": "", - "instr_gas": 8, - "instr_opcode": 8, - "instr_pops": 3, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "addmod" - }, - "address": { - "description": "Get address of currently executing account.", - "instr_args": [], - "instr_category": "envinfo", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 48, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "this.address" - ], - "instr_size": 1, - "prefix": "address" - }, - "and": { - "description": "Bitwise AND operation.", - "instr_args": [ - "a", - "b" - ], - "instr_category": "bitwise-logic", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 22, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "and" - }, - "balance": { - "description": "Get balance of the given account.", - "instr_args": [ - "address" - ], - "instr_category": "envinfo", - "instr_fork": "", - "instr_gas": 20, - "instr_opcode": 49, - "instr_pops": 1, - "instr_pushes": 1, - "instr_returns": [ - "this.balance" - ], - "instr_size": 1, - "prefix": "balance" - }, - "blockhash": { - "description": "Get the hash of one of the 256 most recent complete blocks.", - "instr_args": [ - "num" - ], - "instr_category": "blockinfo", - "instr_fork": "", - "instr_gas": 20, - "instr_opcode": 64, - "instr_pops": 1, - "instr_pushes": 1, - "instr_returns": [ - "block.blockhash" - ], - "instr_size": 1, - "prefix": "blockhash" - }, - "byte": { - "description": "Retrieve single byte from word", - "instr_args": [ - "th", - "value" - ], - "instr_category": "bitwise-logic", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 26, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "byte" - ], - "instr_size": 1, - "prefix": "byte" - }, - "call": { - "description": "Message-call into an account.", - "instr_args": [ - "gas", - "address", - "value", - "inOffset", - "inSize", - "retOffset", - "retSize" - ], - "instr_category": "system", - "instr_fork": "", - "instr_gas": 40, - "instr_opcode": 241, - "instr_pops": 7, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "call" - }, - "callcode": { - "description": "Message-call into this account with alternative account's code.", - "instr_args": [ - "gas", - "address", - "value", - "inOffset", - "inSize", - "retOffset", - "retSize" - ], - "instr_category": "system", - "instr_fork": "", - "instr_gas": 40, - "instr_opcode": 242, - "instr_pops": 7, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "callcode" - }, - "calldatacopy": { - "description": "Copy input data in current environment to memory. This pertains to the input data passed with the message call instruction or transaction.", - "instr_args": [ - "memOffset", - "dataOffset", - "length" - ], - "instr_category": "envinfo", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 55, - "instr_pops": 3, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "calldatacopy" - }, - "calldataload": { - "description": "Get input data of current environment.", - "instr_args": [ - "dataOffset" - ], - "instr_category": "envinfo", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 53, - "instr_pops": 1, - "instr_pushes": 1, - "instr_returns": [ - "msg.data" - ], - "instr_size": 1, - "prefix": "calldataload" - }, - "calldatasize": { - "description": "Get size of input data in current environment.", - "instr_args": [], - "instr_category": "envinfo", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 54, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "msg.data.length" - ], - "instr_size": 1, - "prefix": "calldatasize" - }, - "caller": { - "description": "Get caller address.This is the address of the account that is directly responsible for this execution.", - "instr_args": [], - "instr_category": "envinfo", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 51, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "msg.sender" - ], - "instr_size": 1, - "prefix": "caller" - }, - "callvalue": { - "description": "Get deposited value by the instruction/transaction responsible for this execution.", - "instr_args": [], - "instr_category": "envinfo", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 52, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "msg.value" - ], - "instr_size": 1, - "prefix": "callvalue" - }, - "codecopy": { - "description": "Copy code running in current environment to memory.", - "instr_args": [ - "memOffset", - "codeOffset", - "length" - ], - "instr_category": "envinfo", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 57, - "instr_pops": 3, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "codecopy" - }, - "codesize": { - "description": "Get size of code running in current environment.", - "instr_args": [], - "instr_category": "envinfo", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 56, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "codesize" - ], - "instr_size": 1, - "prefix": "codesize" - }, - "coinbase": { - "description": "Get the block's beneficiary address.", - "instr_args": [], - "instr_category": "blockinfo", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 65, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "block.coinbase" - ], - "instr_size": 1, - "prefix": "coinbase" - }, - "create": { - "description": "Create a new account with associated code.", - "instr_args": [ - "value", - "offset", - "size" - ], - "instr_category": "system", - "instr_fork": "", - "instr_gas": 32000, - "instr_opcode": 240, - "instr_pops": 3, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "create" - }, - "create2": { - "description": "Create a new account with associated code. (Constantinople)", - "instr_args": [ - "endowment", - "offset", - "size", - "salt" - ], - "instr_category": "system", - "instr_fork": "constantinople", - "instr_gas": 32000, - "instr_opcode": 245, - "instr_pops": 4, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "create2" - }, - "delegatecall": { - "description": "Similar to CALLCODE except that it propagates the sender and value from the parent scope to the child scope", - "instr_args": [ - "gas", - "address", - "inOffset", - "inSize", - "retOffset", - "retSize" - ], - "instr_category": "system", - "instr_fork": "", - "instr_gas": 40, - "instr_opcode": 244, - "instr_pops": 6, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "delegatecall" - }, - "difficulty": { - "description": "Get the block's difficulty.", - "instr_args": [], - "instr_category": "blockinfo", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 68, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "block.difficulty" - ], - "instr_size": 1, - "prefix": "difficulty" - }, - "div": { - "description": "Integer division operation.", - "instr_args": [ - "a", - "b" - ], - "instr_category": "arithmetic", - "instr_fork": "", - "instr_gas": 5, - "instr_opcode": 4, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "div" - }, - "dup1": { - "description": "Duplicate 1st stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 128, - "instr_pops": 1, - "instr_pushes": 2, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup1" - }, - "dup10": { - "description": "Duplicate 10th stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 137, - "instr_pops": 10, - "instr_pushes": 11, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup10" - }, - "dup11": { - "description": "Duplicate 11th stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 138, - "instr_pops": 11, - "instr_pushes": 12, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup11" - }, - "dup12": { - "description": "Duplicate 12th stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 139, - "instr_pops": 12, - "instr_pushes": 13, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup12" - }, - "dup13": { - "description": "Duplicate 13th stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 140, - "instr_pops": 13, - "instr_pushes": 14, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup13" - }, - "dup14": { - "description": "Duplicate 14th stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 141, - "instr_pops": 14, - "instr_pushes": 15, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup14" - }, - "dup15": { - "description": "Duplicate 15th stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 142, - "instr_pops": 15, - "instr_pushes": 16, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup15" - }, - "dup16": { - "description": "Duplicate 16th stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 143, - "instr_pops": 16, - "instr_pushes": 17, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup16" - }, - "dup2": { - "description": "Duplicate 2nd stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 129, - "instr_pops": 2, - "instr_pushes": 3, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup2" - }, - "dup3": { - "description": "Duplicate 3rd stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 130, - "instr_pops": 3, - "instr_pushes": 4, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup3" - }, - "dup4": { - "description": "Duplicate 4th stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 131, - "instr_pops": 4, - "instr_pushes": 5, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup4" - }, - "dup5": { - "description": "Duplicate 5th stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 132, - "instr_pops": 5, - "instr_pushes": 6, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup5" - }, - "dup6": { - "description": "Duplicate 6th stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 133, - "instr_pops": 6, - "instr_pushes": 7, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup6" - }, - "dup7": { - "description": "Duplicate 7th stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 134, - "instr_pops": 7, - "instr_pushes": 8, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup7" - }, - "dup8": { - "description": "Duplicate 8th stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 135, - "instr_pops": 8, - "instr_pushes": 9, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup8" - }, - "dup9": { - "description": "Duplicate 9th stack item.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 136, - "instr_pops": 9, - "instr_pushes": 10, - "instr_returns": [], - "instr_size": 1, - "prefix": "dup9" - }, - "eq": { - "description": "Equality comparison", - "instr_args": [ - "a", - "b" - ], - "instr_category": "comparison", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 20, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "flag" - ], - "instr_size": 1, - "prefix": "eq" - }, - "exp": { - "description": "Exponential operation.", - "instr_args": [ - "base", - "exponent" - ], - "instr_category": "arithmetic", - "instr_fork": "", - "instr_gas": 10, - "instr_opcode": 10, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "exp" - }, - "extcodecopy": { - "description": "Copy an account's code to memory.", - "instr_args": [ - "address", - "memOffset", - "codeOffset", - "length" - ], - "instr_category": "envinfo", - "instr_fork": "", - "instr_gas": 20, - "instr_opcode": 60, - "instr_pops": 4, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "extcodecopy" - }, - "extcodehash": { - "description": " - Constantinople", - "instr_args": [ - "address" - ], - "instr_category": "envinfo", - "instr_fork": "constantinople", - "instr_gas": 400, - "instr_opcode": 63, - "instr_pops": 1, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "extcodehash" - }, - "extcodesize": { - "description": "Get size of an account's code.", - "instr_args": [ - "address" - ], - "instr_category": "envinfo", - "instr_fork": "", - "instr_gas": 20, - "instr_opcode": 59, - "instr_pops": 1, - "instr_pushes": 1, - "instr_returns": [ - "extcodesize" - ], - "instr_size": 1, - "prefix": "extcodesize" - }, - "gas": { - "description": "Get the amount of available gas, including the corresponding reduction", - "instr_args": [], - "instr_category": "info", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 90, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "gasleft" - ], - "instr_size": 1, - "prefix": "gas" - }, - "gaslimit": { - "description": "Get the block's gas limit.", - "instr_args": [], - "instr_category": "blockinfo", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 69, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "block.gaslimit" - ], - "instr_size": 1, - "prefix": "gaslimit", - "reference": "https://solidity.readthedocs.io/en/latest/units-and-global-variables.html" - }, - "gasprice": { - "description": "Get price of gas in current environment.", - "instr_args": [], - "instr_category": "envinfo", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 58, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "tx.gasprice" - ], - "instr_size": 1, - "prefix": "gasprice" - }, - "gt": { - "description": "Greater-than comparison", - "instr_args": [ - "a", - "b" - ], - "instr_category": "comparison", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 17, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "flag" - ], - "instr_size": 1, - "prefix": "gt" - }, - "iszero": { - "description": "Simple not operator", - "instr_args": [ - "a" - ], - "instr_category": "comparison", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 21, - "instr_pops": 1, - "instr_pushes": 1, - "instr_returns": [ - "flag" - ], - "instr_size": 1, - "prefix": "iszero" - }, - "jump": { - "description": "Alter the program counter.", - "instr_args": [ - "evm.pc" - ], - "instr_category": "controlflow", - "instr_fork": "", - "instr_gas": 8, - "instr_opcode": 86, - "instr_pops": 1, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "jump" - }, - "jumpdest": { - "description": "Mark a valid destination for jumps.", - "instr_args": [], - "instr_category": "label", - "instr_fork": "", - "instr_gas": 1, - "instr_opcode": 91, - "instr_pops": 0, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "jumpdest" - }, - "jumpi": { - "description": "Conditionally alter the program counter.", - "instr_args": [ - "evm.pc", - "condition" - ], - "instr_category": "controlflow", - "instr_fork": "", - "instr_gas": 10, - "instr_opcode": 87, - "instr_pops": 2, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "jumpi" - }, - "log0": { - "description": "Append log record with no topics.", - "instr_args": [ - "start", - "size" - ], - "instr_category": "event", - "instr_fork": "", - "instr_gas": 375, - "instr_opcode": 160, - "instr_pops": 2, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "log0" - }, - "log1": { - "description": "Append log record with one topic.", - "instr_args": [ - "start", - "size", - "topic1" - ], - "instr_category": "event", - "instr_fork": "", - "instr_gas": 750, - "instr_opcode": 161, - "instr_pops": 3, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "log1" - }, - "log2": { - "description": "Append log record with two topics.", - "instr_args": [ - "start", - "size", - "topic1", - "topic2" - ], - "instr_category": "event", - "instr_fork": "", - "instr_gas": 1125, - "instr_opcode": 162, - "instr_pops": 4, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "log2" - }, - "log3": { - "description": "Append log record with three topics.", - "instr_args": [ - "start", - "size", - "topic1", - "topic2", - "topic3" - ], - "instr_category": "event", - "instr_fork": "", - "instr_gas": 1500, - "instr_opcode": 163, - "instr_pops": 5, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "log3" - }, - "log4": { - "description": "Append log record with four topics.", - "instr_args": [ - "start", - "size", - "topic1", - "topic2", - "topic3", - "topic4" - ], - "instr_category": "event", - "instr_fork": "", - "instr_gas": 1875, - "instr_opcode": 164, - "instr_pops": 6, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "log4" - }, - "lt": { - "description": "Lesser-than comparison", - "instr_args": [ - "a", - "b" - ], - "instr_category": "comparison", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 16, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "flag" - ], - "instr_size": 1, - "prefix": "lt" - }, - "mload": { - "description": "Load word from memory.", - "instr_args": [ - "offset" - ], - "instr_category": "memory", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 81, - "instr_pops": 1, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "mload" - }, - "mod": { - "description": "Modulo", - "instr_args": [ - "a", - "b" - ], - "instr_category": "arithmetic", - "instr_fork": "", - "instr_gas": 5, - "instr_opcode": 6, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "mod" - }, - "msize": { - "description": "Get the size of active memory in bytes.", - "instr_args": [], - "instr_category": "memory", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 89, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "memory.length" - ], - "instr_size": 1, - "prefix": "msize" - }, - "mstore": { - "description": "Save word to memory.", - "instr_args": [ - "offset", - "value" - ], - "instr_category": "memory", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 82, - "instr_pops": 2, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "mstore" - }, - "mstore8": { - "description": "Save byte to memory.", - "instr_args": [ - "offset", - "value" - ], - "instr_category": "memory", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 83, - "instr_pops": 2, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "mstore8" - }, - "mul": { - "description": "Multiplication operation.", - "instr_args": [ - "a", - "b" - ], - "instr_category": "arithmetic", - "instr_fork": "", - "instr_gas": 5, - "instr_opcode": 2, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "mul" - }, - "mulmod": { - "description": "Modulo multiplication operation", - "instr_args": [ - "a", - "b", - "mod" - ], - "instr_category": "arithmetic", - "instr_fork": "", - "instr_gas": 8, - "instr_opcode": 9, - "instr_pops": 3, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "mulmod" - }, - "not": { - "description": "Bitwise NOT operation.", - "instr_args": [ - "a", - "b" - ], - "instr_category": "bitwise-logic", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 25, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "not" - }, - "number": { - "description": "Get the block's number.", - "instr_args": [], - "instr_category": "blockinfo", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 67, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "block.number" - ], - "instr_size": 1, - "prefix": "number" - }, - "or": { - "description": "Bitwise OR operation.", - "instr_args": [ - "a", - "b" - ], - "instr_category": "bitwise-logic", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 23, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "or" - }, - "origin": { - "description": "Get execution origination address.", - "instr_args": [], - "instr_category": "envinfo", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 50, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "tx.origin" - ], - "instr_size": 1, - "prefix": "origin" - }, - "pc": { - "description": "Get the value of the program counter prior to the increment.", - "instr_args": [], - "instr_category": "info", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 88, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "evm.pc" - ], - "instr_size": 1, - "prefix": "pc" - }, - "pop": { - "description": "Remove item from stack.", - "instr_args": [ - "#dummy" - ], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 80, - "instr_pops": 1, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "pop" - }, - "push1": { - "description": "Place 1 byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 96, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 2, - "prefix": "push1" - }, - "push10": { - "description": "Place 10-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 105, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 11, - "prefix": "push10" - }, - "push11": { - "description": "Place 11-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 106, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 12, - "prefix": "push11" - }, - "push12": { - "description": "Place 12-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 107, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 13, - "prefix": "push12" - }, - "push13": { - "description": "Place 13-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 108, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 14, - "prefix": "push13" - }, - "push14": { - "description": "Place 14-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 109, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 15, - "prefix": "push14" - }, - "push15": { - "description": "Place 15-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 110, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 16, - "prefix": "push15" - }, - "push16": { - "description": "Place 16-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 111, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 17, - "prefix": "push16" - }, - "push17": { - "description": "Place 17-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 112, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 18, - "prefix": "push17" - }, - "push18": { - "description": "Place 18-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 113, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 19, - "prefix": "push18" - }, - "push19": { - "description": "Place 19-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 114, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 20, - "prefix": "push19" - }, - "push2": { - "description": "Place 2-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 97, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 3, - "prefix": "push2" - }, - "push20": { - "description": "Place 20-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 115, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 21, - "prefix": "push20" - }, - "push21": { - "description": "Place 21-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 116, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 22, - "prefix": "push21" - }, - "push22": { - "description": "Place 22-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 117, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 23, - "prefix": "push22" - }, - "push23": { - "description": "Place 23-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 118, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 24, - "prefix": "push23" - }, - "push24": { - "description": "Place 24-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 119, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 25, - "prefix": "push24" - }, - "push25": { - "description": "Place 25-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 120, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 26, - "prefix": "push25" - }, - "push26": { - "description": "Place 26-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 121, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 27, - "prefix": "push26" - }, - "push27": { - "description": "Place 27-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 122, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 28, - "prefix": "push27" - }, - "push28": { - "description": "Place 28-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 123, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 29, - "prefix": "push28" - }, - "push29": { - "description": "Place 29-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 124, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 30, - "prefix": "push29" - }, - "push3": { - "description": "Place 3-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 98, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 4, - "prefix": "push3" - }, - "push30": { - "description": "Place 30-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 125, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 31, - "prefix": "push30" - }, - "push31": { - "description": "Place 31-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 126, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 32, - "prefix": "push31" - }, - "push32": { - "description": "Place 32-byte (full word) item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 127, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 33, - "prefix": "push32" - }, - "push4": { - "description": "Place 4-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 99, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 5, - "prefix": "push4" - }, - "push5": { - "description": "Place 5-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 100, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 6, - "prefix": "push5" - }, - "push6": { - "description": "Place 6-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 101, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 7, - "prefix": "push6" - }, - "push7": { - "description": "Place 7-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 102, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 8, - "prefix": "push7" - }, - "push8": { - "description": "Place 8-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 103, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 9, - "prefix": "push8" - }, - "push9": { - "description": "Place 9-byte item on stack.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 104, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "item" - ], - "instr_size": 10, - "prefix": "push9" - }, - "return": { - "description": "Halt execution returning output data.", - "instr_args": [ - "offset", - "size" - ], - "instr_category": "terminate", - "instr_fork": "", - "instr_gas": 0, - "instr_opcode": 243, - "instr_pops": 2, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "return" - }, - "returndatacopy": { - "description": "Copy data from the return data buffer.", - "instr_args": [ - "memOffset", - "dataOffset", - "length" - ], - "instr_category": "envinfo", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 62, - "instr_pops": 3, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "returndatacopy" - }, - "returndatasize": { - "description": "Push the size of the return data buffer onto the stack.", - "instr_args": [], - "instr_category": "envinfo", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 61, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "returndatasize" - ], - "instr_size": 1, - "prefix": "returndatasize" - }, - "revert": { - "description": "throw an error", - "instr_args": [ - "offset", - "size" - ], - "instr_category": "terminate", - "instr_fork": "", - "instr_gas": 0, - "instr_opcode": 253, - "instr_pops": 2, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "revert" - }, - "sar": { - "description": " Shift arithmetic right", - "instr_args": [ - "shift", - "value" - ], - "instr_category": "bitwise-logic", - "instr_fork": "constantinople", - "instr_gas": 3, - "instr_opcode": 29, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "flag" - ], - "instr_size": 1, - "prefix": "sar" - }, - "sdiv": { - "description": "Signed integer", - "instr_args": [ - "a", - "b" - ], - "instr_category": "arithmetic", - "instr_fork": "", - "instr_gas": 5, - "instr_opcode": 5, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "sdiv" - }, - "selfdestruct": { - "description": "Halt execution and register account for later deletion.", - "instr_args": [ - "address" - ], - "instr_category": "terminate", - "instr_fork": "", - "instr_gas": 0, - "instr_opcode": 255, - "instr_pops": 1, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "selfdestruct" - }, - "sgt": { - "description": "Signed greater-than comparison", - "instr_args": [ - "a", - "b" - ], - "instr_category": "comparison", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 19, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "flag" - ], - "instr_size": 1, - "prefix": "sgt" - }, - "sha3": { - "description": "Compute Keccak-256 hash.", - "instr_args": [ - "offset", - "size" - ], - "instr_category": "cryptographic", - "instr_fork": "", - "instr_gas": 30, - "instr_opcode": 32, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "sha3" - ], - "instr_size": 1, - "prefix": "sha3" - }, - "shl": { - "description": " Shift left", - "instr_args": [ - "shift", - "value" - ], - "instr_category": "bitwise-logic", - "instr_fork": "constantinople", - "instr_gas": 3, - "instr_opcode": 27, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "shl" - }, - "shr": { - "description": " Shift Right", - "instr_args": [ - "shift", - "value" - ], - "instr_category": "bitwise-logic", - "instr_fork": "constantinople", - "instr_gas": 3, - "instr_opcode": 28, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "shr" - }, - "signextend": { - "description": "Extend length of two's complement signed integer.", - "instr_args": [ - "bits", - "num" - ], - "instr_category": "arithmetic", - "instr_fork": "", - "instr_gas": 5, - "instr_opcode": 11, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "signextend" - }, - "sload": { - "description": "Load word from storage.", - "instr_args": [ - "loc" - ], - "instr_category": "storage", - "instr_fork": "", - "instr_gas": 50, - "instr_opcode": 84, - "instr_pops": 1, - "instr_pushes": 1, - "instr_returns": [ - "value" - ], - "instr_size": 1, - "prefix": "sload" - }, - "slt": { - "description": "Signed less-than comparison", - "instr_args": [ - "a", - "b" - ], - "instr_category": "comparison", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 18, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "flag" - ], - "instr_size": 1, - "prefix": "slt" - }, - "smod": { - "description": "Signed modulo", - "instr_args": [ - "a", - "b" - ], - "instr_category": "arithmetic", - "instr_fork": "", - "instr_gas": 5, - "instr_opcode": 7, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "smod" - }, - "sstore": { - "description": "Save word to storage.", - "instr_args": [ - "loc", - "value" - ], - "instr_category": "storage", - "instr_fork": "", - "instr_gas": 0, - "instr_opcode": 85, - "instr_pops": 2, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "sstore" - }, - "staticcall": { - "description": "Call another contract (or itself) while disallowing any modifications to the state during the call.", - "instr_args": [ - "gas", - "address", - "inOffset", - "inSize", - "retOffset", - "retSize" - ], - "instr_category": "system", - "instr_fork": "", - "instr_gas": 40, - "instr_opcode": 250, - "instr_pops": 6, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "staticcall" - }, - "stop": { - "description": "Halts execution.", - "instr_args": [], - "instr_category": "terminate", - "instr_fork": "", - "instr_gas": 0, - "instr_opcode": 0, - "instr_pops": 0, - "instr_pushes": 0, - "instr_returns": [], - "instr_size": 1, - "prefix": "stop" - }, - "sub": { - "description": "Subtraction operation.", - "instr_args": [ - "a", - "b" - ], - "instr_category": "arithmetic", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 3, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "sub" - }, - "swap1": { - "description": "Exchange 1st and 2nd stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 144, - "instr_pops": 2, - "instr_pushes": 2, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap1" - }, - "swap10": { - "description": "Exchange 1st and 11th stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 153, - "instr_pops": 11, - "instr_pushes": 11, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap10" - }, - "swap11": { - "description": "Exchange 1st and 12th stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 154, - "instr_pops": 12, - "instr_pushes": 12, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap11" - }, - "swap12": { - "description": "Exchange 1st and 13th stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 155, - "instr_pops": 13, - "instr_pushes": 13, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap12" - }, - "swap13": { - "description": "Exchange 1st and 14th stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 156, - "instr_pops": 14, - "instr_pushes": 14, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap13" - }, - "swap14": { - "description": "Exchange 1st and 15th stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 157, - "instr_pops": 15, - "instr_pushes": 15, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap14" - }, - "swap15": { - "description": "Exchange 1st and 16th stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 158, - "instr_pops": 16, - "instr_pushes": 16, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap15" - }, - "swap16": { - "description": "Exchange 1st and 17th stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 159, - "instr_pops": 17, - "instr_pushes": 17, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap16" - }, - "swap2": { - "description": "Exchange 1st and 3rd stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 145, - "instr_pops": 3, - "instr_pushes": 3, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap2" - }, - "swap3": { - "description": "Exchange 1st and 4th stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 146, - "instr_pops": 4, - "instr_pushes": 3, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap3" - }, - "swap4": { - "description": "Exchange 1st and 5th stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 147, - "instr_pops": 5, - "instr_pushes": 4, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap4" - }, - "swap5": { - "description": "Exchange 1st and 6th stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 148, - "instr_pops": 6, - "instr_pushes": 5, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap5" - }, - "swap6": { - "description": "Exchange 1st and 7th stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 149, - "instr_pops": 7, - "instr_pushes": 6, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap6" - }, - "swap7": { - "description": "Exchange 1st and 8th stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 150, - "instr_pops": 8, - "instr_pushes": 7, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap7" - }, - "swap8": { - "description": "Exchange 1st and 9th stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 151, - "instr_pops": 9, - "instr_pushes": 9, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap8" - }, - "swap9": { - "description": "Exchange 1st and 10th stack items.", - "instr_args": [], - "instr_category": "stack", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 152, - "instr_pops": 10, - "instr_pushes": 10, - "instr_returns": [], - "instr_size": 1, - "prefix": "swap9" - }, - "timestamp": { - "description": "Get the block's timestamp.", - "instr_args": [], - "instr_category": "blockinfo", - "instr_fork": "", - "instr_gas": 2, - "instr_opcode": 66, - "instr_pops": 0, - "instr_pushes": 1, - "instr_returns": [ - "block.timestamp" - ], - "instr_size": 1, - "prefix": "timestamp" - }, - "xor": { - "description": "Bitwise XOR operation.", - "instr_args": [ - "a", - "b" - ], - "instr_category": "bitwise-logic", - "instr_fork": "", - "instr_gas": 3, - "instr_opcode": 24, - "instr_pops": 2, - "instr_pushes": 1, - "instr_returns": [ - "result" - ], - "instr_size": 1, - "prefix": "xor" - } + "add": { + "description": "Addition operation.", + "instr_args": ["a", "b"], + "instr_category": "arithmetic", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 1, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "add" + }, + "addmod": { + "description": "Modulo addition operation", + "instr_args": ["a", "b", "mod"], + "instr_category": "arithmetic", + "instr_fork": "", + "instr_gas": 8, + "instr_opcode": 8, + "instr_pops": 3, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "addmod" + }, + "address": { + "description": "Get address of currently executing account.", + "instr_args": [], + "instr_category": "envinfo", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 48, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["this.address"], + "instr_size": 1, + "prefix": "address" + }, + "and": { + "description": "Bitwise AND operation.", + "instr_args": ["a", "b"], + "instr_category": "bitwise-logic", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 22, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "and" + }, + "balance": { + "description": "Get balance of the given account.", + "instr_args": ["address"], + "instr_category": "envinfo", + "instr_fork": "", + "instr_gas": 20, + "instr_opcode": 49, + "instr_pops": 1, + "instr_pushes": 1, + "instr_returns": ["this.balance"], + "instr_size": 1, + "prefix": "balance" + }, + "blockhash": { + "description": "Get the hash of one of the 256 most recent complete blocks.", + "instr_args": ["num"], + "instr_category": "blockinfo", + "instr_fork": "", + "instr_gas": 20, + "instr_opcode": 64, + "instr_pops": 1, + "instr_pushes": 1, + "instr_returns": ["block.blockhash"], + "instr_size": 1, + "prefix": "blockhash" + }, + "byte": { + "description": "Retrieve single byte from word", + "instr_args": ["th", "value"], + "instr_category": "bitwise-logic", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 26, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["byte"], + "instr_size": 1, + "prefix": "byte" + }, + "call": { + "description": "Message-call into an account.", + "instr_args": [ + "gas", + "address", + "value", + "inOffset", + "inSize", + "retOffset", + "retSize" + ], + "instr_category": "system", + "instr_fork": "", + "instr_gas": 40, + "instr_opcode": 241, + "instr_pops": 7, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "call" + }, + "callcode": { + "description": "Message-call into this account with alternative account's code.", + "instr_args": [ + "gas", + "address", + "value", + "inOffset", + "inSize", + "retOffset", + "retSize" + ], + "instr_category": "system", + "instr_fork": "", + "instr_gas": 40, + "instr_opcode": 242, + "instr_pops": 7, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "callcode" + }, + "calldatacopy": { + "description": "Copy input data in current environment to memory. This pertains to the input data passed with the message call instruction or transaction.", + "instr_args": ["memOffset", "dataOffset", "length"], + "instr_category": "envinfo", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 55, + "instr_pops": 3, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "calldatacopy" + }, + "calldataload": { + "description": "Get input data of current environment.", + "instr_args": ["dataOffset"], + "instr_category": "envinfo", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 53, + "instr_pops": 1, + "instr_pushes": 1, + "instr_returns": ["msg.data"], + "instr_size": 1, + "prefix": "calldataload" + }, + "calldatasize": { + "description": "Get size of input data in current environment.", + "instr_args": [], + "instr_category": "envinfo", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 54, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["msg.data.length"], + "instr_size": 1, + "prefix": "calldatasize" + }, + "caller": { + "description": "Get caller address.This is the address of the account that is directly responsible for this execution.", + "instr_args": [], + "instr_category": "envinfo", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 51, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["msg.sender"], + "instr_size": 1, + "prefix": "caller" + }, + "callvalue": { + "description": "Get deposited value by the instruction/transaction responsible for this execution.", + "instr_args": [], + "instr_category": "envinfo", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 52, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["msg.value"], + "instr_size": 1, + "prefix": "callvalue" + }, + "codecopy": { + "description": "Copy code running in current environment to memory.", + "instr_args": ["memOffset", "codeOffset", "length"], + "instr_category": "envinfo", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 57, + "instr_pops": 3, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "codecopy" + }, + "codesize": { + "description": "Get size of code running in current environment.", + "instr_args": [], + "instr_category": "envinfo", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 56, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["codesize"], + "instr_size": 1, + "prefix": "codesize" + }, + "coinbase": { + "description": "Get the block's beneficiary address.", + "instr_args": [], + "instr_category": "blockinfo", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 65, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["block.coinbase"], + "instr_size": 1, + "prefix": "coinbase" + }, + "create": { + "description": "Create a new account with associated code.", + "instr_args": ["value", "offset", "size"], + "instr_category": "system", + "instr_fork": "", + "instr_gas": 32000, + "instr_opcode": 240, + "instr_pops": 3, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "create" + }, + "create2": { + "description": "Create a new account with associated code. (Constantinople)", + "instr_args": ["endowment", "offset", "size", "salt"], + "instr_category": "system", + "instr_fork": "constantinople", + "instr_gas": 32000, + "instr_opcode": 245, + "instr_pops": 4, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "create2" + }, + "delegatecall": { + "description": "Similar to CALLCODE except that it propagates the sender and value from the parent scope to the child scope", + "instr_args": [ + "gas", + "address", + "inOffset", + "inSize", + "retOffset", + "retSize" + ], + "instr_category": "system", + "instr_fork": "", + "instr_gas": 40, + "instr_opcode": 244, + "instr_pops": 6, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "delegatecall" + }, + "difficulty": { + "description": "Get the block's difficulty.", + "instr_args": [], + "instr_category": "blockinfo", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 68, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["block.difficulty"], + "instr_size": 1, + "prefix": "difficulty" + }, + "div": { + "description": "Integer division operation.", + "instr_args": ["a", "b"], + "instr_category": "arithmetic", + "instr_fork": "", + "instr_gas": 5, + "instr_opcode": 4, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "div" + }, + "dup1": { + "description": "Duplicate 1st stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 128, + "instr_pops": 1, + "instr_pushes": 2, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup1" + }, + "dup10": { + "description": "Duplicate 10th stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 137, + "instr_pops": 10, + "instr_pushes": 11, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup10" + }, + "dup11": { + "description": "Duplicate 11th stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 138, + "instr_pops": 11, + "instr_pushes": 12, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup11" + }, + "dup12": { + "description": "Duplicate 12th stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 139, + "instr_pops": 12, + "instr_pushes": 13, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup12" + }, + "dup13": { + "description": "Duplicate 13th stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 140, + "instr_pops": 13, + "instr_pushes": 14, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup13" + }, + "dup14": { + "description": "Duplicate 14th stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 141, + "instr_pops": 14, + "instr_pushes": 15, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup14" + }, + "dup15": { + "description": "Duplicate 15th stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 142, + "instr_pops": 15, + "instr_pushes": 16, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup15" + }, + "dup16": { + "description": "Duplicate 16th stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 143, + "instr_pops": 16, + "instr_pushes": 17, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup16" + }, + "dup2": { + "description": "Duplicate 2nd stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 129, + "instr_pops": 2, + "instr_pushes": 3, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup2" + }, + "dup3": { + "description": "Duplicate 3rd stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 130, + "instr_pops": 3, + "instr_pushes": 4, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup3" + }, + "dup4": { + "description": "Duplicate 4th stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 131, + "instr_pops": 4, + "instr_pushes": 5, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup4" + }, + "dup5": { + "description": "Duplicate 5th stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 132, + "instr_pops": 5, + "instr_pushes": 6, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup5" + }, + "dup6": { + "description": "Duplicate 6th stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 133, + "instr_pops": 6, + "instr_pushes": 7, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup6" + }, + "dup7": { + "description": "Duplicate 7th stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 134, + "instr_pops": 7, + "instr_pushes": 8, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup7" + }, + "dup8": { + "description": "Duplicate 8th stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 135, + "instr_pops": 8, + "instr_pushes": 9, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup8" + }, + "dup9": { + "description": "Duplicate 9th stack item.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 136, + "instr_pops": 9, + "instr_pushes": 10, + "instr_returns": [], + "instr_size": 1, + "prefix": "dup9" + }, + "eq": { + "description": "Equality comparison", + "instr_args": ["a", "b"], + "instr_category": "comparison", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 20, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["flag"], + "instr_size": 1, + "prefix": "eq" + }, + "exp": { + "description": "Exponential operation.", + "instr_args": ["base", "exponent"], + "instr_category": "arithmetic", + "instr_fork": "", + "instr_gas": 10, + "instr_opcode": 10, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "exp" + }, + "extcodecopy": { + "description": "Copy an account's code to memory.", + "instr_args": ["address", "memOffset", "codeOffset", "length"], + "instr_category": "envinfo", + "instr_fork": "", + "instr_gas": 20, + "instr_opcode": 60, + "instr_pops": 4, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "extcodecopy" + }, + "extcodehash": { + "description": " - Constantinople", + "instr_args": ["address"], + "instr_category": "envinfo", + "instr_fork": "constantinople", + "instr_gas": 400, + "instr_opcode": 63, + "instr_pops": 1, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "extcodehash" + }, + "extcodesize": { + "description": "Get size of an account's code.", + "instr_args": ["address"], + "instr_category": "envinfo", + "instr_fork": "", + "instr_gas": 20, + "instr_opcode": 59, + "instr_pops": 1, + "instr_pushes": 1, + "instr_returns": ["extcodesize"], + "instr_size": 1, + "prefix": "extcodesize" + }, + "gas": { + "description": "Get the amount of available gas, including the corresponding reduction", + "instr_args": [], + "instr_category": "info", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 90, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["gasleft"], + "instr_size": 1, + "prefix": "gas" + }, + "gaslimit": { + "description": "Get the block's gas limit.", + "instr_args": [], + "instr_category": "blockinfo", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 69, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["block.gaslimit"], + "instr_size": 1, + "prefix": "gaslimit", + "reference": "https://solidity.readthedocs.io/en/latest/units-and-global-variables.html" + }, + "gasprice": { + "description": "Get price of gas in current environment.", + "instr_args": [], + "instr_category": "envinfo", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 58, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["tx.gasprice"], + "instr_size": 1, + "prefix": "gasprice" + }, + "gt": { + "description": "Greater-than comparison", + "instr_args": ["a", "b"], + "instr_category": "comparison", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 17, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["flag"], + "instr_size": 1, + "prefix": "gt" + }, + "iszero": { + "description": "Simple not operator", + "instr_args": ["a"], + "instr_category": "comparison", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 21, + "instr_pops": 1, + "instr_pushes": 1, + "instr_returns": ["flag"], + "instr_size": 1, + "prefix": "iszero" + }, + "jump": { + "description": "Alter the program counter.", + "instr_args": ["evm.pc"], + "instr_category": "controlflow", + "instr_fork": "", + "instr_gas": 8, + "instr_opcode": 86, + "instr_pops": 1, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "jump" + }, + "jumpdest": { + "description": "Mark a valid destination for jumps.", + "instr_args": [], + "instr_category": "label", + "instr_fork": "", + "instr_gas": 1, + "instr_opcode": 91, + "instr_pops": 0, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "jumpdest" + }, + "jumpi": { + "description": "Conditionally alter the program counter.", + "instr_args": ["evm.pc", "condition"], + "instr_category": "controlflow", + "instr_fork": "", + "instr_gas": 10, + "instr_opcode": 87, + "instr_pops": 2, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "jumpi" + }, + "log0": { + "description": "Append log record with no topics.", + "instr_args": ["start", "size"], + "instr_category": "event", + "instr_fork": "", + "instr_gas": 375, + "instr_opcode": 160, + "instr_pops": 2, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "log0" + }, + "log1": { + "description": "Append log record with one topic.", + "instr_args": ["start", "size", "topic1"], + "instr_category": "event", + "instr_fork": "", + "instr_gas": 750, + "instr_opcode": 161, + "instr_pops": 3, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "log1" + }, + "log2": { + "description": "Append log record with two topics.", + "instr_args": ["start", "size", "topic1", "topic2"], + "instr_category": "event", + "instr_fork": "", + "instr_gas": 1125, + "instr_opcode": 162, + "instr_pops": 4, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "log2" + }, + "log3": { + "description": "Append log record with three topics.", + "instr_args": ["start", "size", "topic1", "topic2", "topic3"], + "instr_category": "event", + "instr_fork": "", + "instr_gas": 1500, + "instr_opcode": 163, + "instr_pops": 5, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "log3" + }, + "log4": { + "description": "Append log record with four topics.", + "instr_args": ["start", "size", "topic1", "topic2", "topic3", "topic4"], + "instr_category": "event", + "instr_fork": "", + "instr_gas": 1875, + "instr_opcode": 164, + "instr_pops": 6, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "log4" + }, + "lt": { + "description": "Lesser-than comparison", + "instr_args": ["a", "b"], + "instr_category": "comparison", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 16, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["flag"], + "instr_size": 1, + "prefix": "lt" + }, + "mload": { + "description": "Load word from memory.", + "instr_args": ["offset"], + "instr_category": "memory", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 81, + "instr_pops": 1, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "mload" + }, + "mod": { + "description": "Modulo", + "instr_args": ["a", "b"], + "instr_category": "arithmetic", + "instr_fork": "", + "instr_gas": 5, + "instr_opcode": 6, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "mod" + }, + "msize": { + "description": "Get the size of active memory in bytes.", + "instr_args": [], + "instr_category": "memory", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 89, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["memory.length"], + "instr_size": 1, + "prefix": "msize" + }, + "mstore": { + "description": "Save word to memory.", + "instr_args": ["offset", "value"], + "instr_category": "memory", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 82, + "instr_pops": 2, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "mstore" + }, + "mstore8": { + "description": "Save byte to memory.", + "instr_args": ["offset", "value"], + "instr_category": "memory", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 83, + "instr_pops": 2, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "mstore8" + }, + "mul": { + "description": "Multiplication operation.", + "instr_args": ["a", "b"], + "instr_category": "arithmetic", + "instr_fork": "", + "instr_gas": 5, + "instr_opcode": 2, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "mul" + }, + "mulmod": { + "description": "Modulo multiplication operation", + "instr_args": ["a", "b", "mod"], + "instr_category": "arithmetic", + "instr_fork": "", + "instr_gas": 8, + "instr_opcode": 9, + "instr_pops": 3, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "mulmod" + }, + "not": { + "description": "Bitwise NOT operation.", + "instr_args": ["a", "b"], + "instr_category": "bitwise-logic", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 25, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "not" + }, + "number": { + "description": "Get the block's number.", + "instr_args": [], + "instr_category": "blockinfo", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 67, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["block.number"], + "instr_size": 1, + "prefix": "number" + }, + "or": { + "description": "Bitwise OR operation.", + "instr_args": ["a", "b"], + "instr_category": "bitwise-logic", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 23, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "or" + }, + "origin": { + "description": "Get execution origination address.", + "instr_args": [], + "instr_category": "envinfo", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 50, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["tx.origin"], + "instr_size": 1, + "prefix": "origin" + }, + "pc": { + "description": "Get the value of the program counter prior to the increment.", + "instr_args": [], + "instr_category": "info", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 88, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["evm.pc"], + "instr_size": 1, + "prefix": "pc" + }, + "pop": { + "description": "Remove item from stack.", + "instr_args": ["#dummy"], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 80, + "instr_pops": 1, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "pop" + }, + "push1": { + "description": "Place 1 byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 96, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 2, + "prefix": "push1" + }, + "push10": { + "description": "Place 10-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 105, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 11, + "prefix": "push10" + }, + "push11": { + "description": "Place 11-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 106, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 12, + "prefix": "push11" + }, + "push12": { + "description": "Place 12-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 107, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 13, + "prefix": "push12" + }, + "push13": { + "description": "Place 13-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 108, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 14, + "prefix": "push13" + }, + "push14": { + "description": "Place 14-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 109, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 15, + "prefix": "push14" + }, + "push15": { + "description": "Place 15-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 110, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 16, + "prefix": "push15" + }, + "push16": { + "description": "Place 16-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 111, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 17, + "prefix": "push16" + }, + "push17": { + "description": "Place 17-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 112, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 18, + "prefix": "push17" + }, + "push18": { + "description": "Place 18-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 113, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 19, + "prefix": "push18" + }, + "push19": { + "description": "Place 19-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 114, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 20, + "prefix": "push19" + }, + "push2": { + "description": "Place 2-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 97, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 3, + "prefix": "push2" + }, + "push20": { + "description": "Place 20-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 115, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 21, + "prefix": "push20" + }, + "push21": { + "description": "Place 21-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 116, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 22, + "prefix": "push21" + }, + "push22": { + "description": "Place 22-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 117, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 23, + "prefix": "push22" + }, + "push23": { + "description": "Place 23-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 118, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 24, + "prefix": "push23" + }, + "push24": { + "description": "Place 24-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 119, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 25, + "prefix": "push24" + }, + "push25": { + "description": "Place 25-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 120, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 26, + "prefix": "push25" + }, + "push26": { + "description": "Place 26-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 121, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 27, + "prefix": "push26" + }, + "push27": { + "description": "Place 27-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 122, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 28, + "prefix": "push27" + }, + "push28": { + "description": "Place 28-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 123, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 29, + "prefix": "push28" + }, + "push29": { + "description": "Place 29-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 124, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 30, + "prefix": "push29" + }, + "push3": { + "description": "Place 3-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 98, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 4, + "prefix": "push3" + }, + "push30": { + "description": "Place 30-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 125, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 31, + "prefix": "push30" + }, + "push31": { + "description": "Place 31-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 126, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 32, + "prefix": "push31" + }, + "push32": { + "description": "Place 32-byte (full word) item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 127, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 33, + "prefix": "push32" + }, + "push4": { + "description": "Place 4-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 99, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 5, + "prefix": "push4" + }, + "push5": { + "description": "Place 5-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 100, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 6, + "prefix": "push5" + }, + "push6": { + "description": "Place 6-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 101, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 7, + "prefix": "push6" + }, + "push7": { + "description": "Place 7-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 102, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 8, + "prefix": "push7" + }, + "push8": { + "description": "Place 8-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 103, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 9, + "prefix": "push8" + }, + "push9": { + "description": "Place 9-byte item on stack.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 104, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["item"], + "instr_size": 10, + "prefix": "push9" + }, + "return": { + "description": "Halt execution returning output data.", + "instr_args": ["offset", "size"], + "instr_category": "terminate", + "instr_fork": "", + "instr_gas": 0, + "instr_opcode": 243, + "instr_pops": 2, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "return" + }, + "returndatacopy": { + "description": "Copy data from the return data buffer.", + "instr_args": ["memOffset", "dataOffset", "length"], + "instr_category": "envinfo", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 62, + "instr_pops": 3, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "returndatacopy" + }, + "returndatasize": { + "description": "Push the size of the return data buffer onto the stack.", + "instr_args": [], + "instr_category": "envinfo", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 61, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["returndatasize"], + "instr_size": 1, + "prefix": "returndatasize" + }, + "revert": { + "description": "throw an error", + "instr_args": ["offset", "size"], + "instr_category": "terminate", + "instr_fork": "", + "instr_gas": 0, + "instr_opcode": 253, + "instr_pops": 2, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "revert" + }, + "sar": { + "description": " Shift arithmetic right", + "instr_args": ["shift", "value"], + "instr_category": "bitwise-logic", + "instr_fork": "constantinople", + "instr_gas": 3, + "instr_opcode": 29, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["flag"], + "instr_size": 1, + "prefix": "sar" + }, + "sdiv": { + "description": "Signed integer", + "instr_args": ["a", "b"], + "instr_category": "arithmetic", + "instr_fork": "", + "instr_gas": 5, + "instr_opcode": 5, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "sdiv" + }, + "selfdestruct": { + "description": "Halt execution and register account for later deletion.", + "instr_args": ["address"], + "instr_category": "terminate", + "instr_fork": "", + "instr_gas": 0, + "instr_opcode": 255, + "instr_pops": 1, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "selfdestruct" + }, + "sgt": { + "description": "Signed greater-than comparison", + "instr_args": ["a", "b"], + "instr_category": "comparison", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 19, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["flag"], + "instr_size": 1, + "prefix": "sgt" + }, + "sha3": { + "description": "Compute Keccak-256 hash.", + "instr_args": ["offset", "size"], + "instr_category": "cryptographic", + "instr_fork": "", + "instr_gas": 30, + "instr_opcode": 32, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["sha3"], + "instr_size": 1, + "prefix": "sha3" + }, + "shl": { + "description": " Shift left", + "instr_args": ["shift", "value"], + "instr_category": "bitwise-logic", + "instr_fork": "constantinople", + "instr_gas": 3, + "instr_opcode": 27, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "shl" + }, + "shr": { + "description": " Shift Right", + "instr_args": ["shift", "value"], + "instr_category": "bitwise-logic", + "instr_fork": "constantinople", + "instr_gas": 3, + "instr_opcode": 28, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "shr" + }, + "signextend": { + "description": "Extend length of two's complement signed integer.", + "instr_args": ["bits", "num"], + "instr_category": "arithmetic", + "instr_fork": "", + "instr_gas": 5, + "instr_opcode": 11, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "signextend" + }, + "sload": { + "description": "Load word from storage.", + "instr_args": ["loc"], + "instr_category": "storage", + "instr_fork": "", + "instr_gas": 50, + "instr_opcode": 84, + "instr_pops": 1, + "instr_pushes": 1, + "instr_returns": ["value"], + "instr_size": 1, + "prefix": "sload" + }, + "slt": { + "description": "Signed less-than comparison", + "instr_args": ["a", "b"], + "instr_category": "comparison", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 18, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["flag"], + "instr_size": 1, + "prefix": "slt" + }, + "smod": { + "description": "Signed modulo", + "instr_args": ["a", "b"], + "instr_category": "arithmetic", + "instr_fork": "", + "instr_gas": 5, + "instr_opcode": 7, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "smod" + }, + "sstore": { + "description": "Save word to storage.", + "instr_args": ["loc", "value"], + "instr_category": "storage", + "instr_fork": "", + "instr_gas": 0, + "instr_opcode": 85, + "instr_pops": 2, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "sstore" + }, + "staticcall": { + "description": "Call another contract (or itself) while disallowing any modifications to the state during the call.", + "instr_args": [ + "gas", + "address", + "inOffset", + "inSize", + "retOffset", + "retSize" + ], + "instr_category": "system", + "instr_fork": "", + "instr_gas": 40, + "instr_opcode": 250, + "instr_pops": 6, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "staticcall" + }, + "stop": { + "description": "Halts execution.", + "instr_args": [], + "instr_category": "terminate", + "instr_fork": "", + "instr_gas": 0, + "instr_opcode": 0, + "instr_pops": 0, + "instr_pushes": 0, + "instr_returns": [], + "instr_size": 1, + "prefix": "stop" + }, + "sub": { + "description": "Subtraction operation.", + "instr_args": ["a", "b"], + "instr_category": "arithmetic", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 3, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "sub" + }, + "swap1": { + "description": "Exchange 1st and 2nd stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 144, + "instr_pops": 2, + "instr_pushes": 2, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap1" + }, + "swap10": { + "description": "Exchange 1st and 11th stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 153, + "instr_pops": 11, + "instr_pushes": 11, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap10" + }, + "swap11": { + "description": "Exchange 1st and 12th stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 154, + "instr_pops": 12, + "instr_pushes": 12, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap11" + }, + "swap12": { + "description": "Exchange 1st and 13th stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 155, + "instr_pops": 13, + "instr_pushes": 13, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap12" + }, + "swap13": { + "description": "Exchange 1st and 14th stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 156, + "instr_pops": 14, + "instr_pushes": 14, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap13" + }, + "swap14": { + "description": "Exchange 1st and 15th stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 157, + "instr_pops": 15, + "instr_pushes": 15, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap14" + }, + "swap15": { + "description": "Exchange 1st and 16th stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 158, + "instr_pops": 16, + "instr_pushes": 16, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap15" + }, + "swap16": { + "description": "Exchange 1st and 17th stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 159, + "instr_pops": 17, + "instr_pushes": 17, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap16" + }, + "swap2": { + "description": "Exchange 1st and 3rd stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 145, + "instr_pops": 3, + "instr_pushes": 3, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap2" + }, + "swap3": { + "description": "Exchange 1st and 4th stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 146, + "instr_pops": 4, + "instr_pushes": 3, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap3" + }, + "swap4": { + "description": "Exchange 1st and 5th stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 147, + "instr_pops": 5, + "instr_pushes": 4, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap4" + }, + "swap5": { + "description": "Exchange 1st and 6th stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 148, + "instr_pops": 6, + "instr_pushes": 5, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap5" + }, + "swap6": { + "description": "Exchange 1st and 7th stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 149, + "instr_pops": 7, + "instr_pushes": 6, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap6" + }, + "swap7": { + "description": "Exchange 1st and 8th stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 150, + "instr_pops": 8, + "instr_pushes": 7, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap7" + }, + "swap8": { + "description": "Exchange 1st and 9th stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 151, + "instr_pops": 9, + "instr_pushes": 9, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap8" + }, + "swap9": { + "description": "Exchange 1st and 10th stack items.", + "instr_args": [], + "instr_category": "stack", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 152, + "instr_pops": 10, + "instr_pushes": 10, + "instr_returns": [], + "instr_size": 1, + "prefix": "swap9" + }, + "timestamp": { + "description": "Get the block's timestamp.", + "instr_args": [], + "instr_category": "blockinfo", + "instr_fork": "", + "instr_gas": 2, + "instr_opcode": 66, + "instr_pops": 0, + "instr_pushes": 1, + "instr_returns": ["block.timestamp"], + "instr_size": 1, + "prefix": "timestamp" + }, + "xor": { + "description": "Bitwise XOR operation.", + "instr_args": ["a", "b"], + "instr_category": "bitwise-logic", + "instr_fork": "", + "instr_gas": 3, + "instr_opcode": 24, + "instr_pops": 2, + "instr_pushes": 1, + "instr_returns": ["result"], + "instr_size": 1, + "prefix": "xor" + } } diff --git a/src/features/hover/builtins.json b/src/features/hover/builtins.json index 5b2e6c6..d669c6a 100644 --- a/src/features/hover/builtins.json +++ b/src/features/hover/builtins.json @@ -1,380 +1,429 @@ { - "wei": { - "prefix": "wei", - "description": "1 wei == 10e-XX eth", - "security":"" - }, - "finney": { - "prefix": "finney", - "description": "1 finney == 10e-XX eth", - "security":"" - }, - "szabo": { - "prefix": "szabo", - "description": "1 szabo == 10e-XX eth", - "security":"" - }, - "ether": { - "prefix": "ether", - "description": "1 ether == 10e-XX eth", - "security":"" - }, - "seconds": { - "prefix": "seconds", - "description": "1 seconds == 10e-XX eth", - "security":"" - }, - "minutes": { - "prefix": "minutes", - "description": "1 minutes == 60 seconds", - "security":"Note - for calendar calculations: does not account for leap seconds!" - }, - "hours": { - "prefix": "hours", - "description": "1 hours == 60 minutes", - "security":"Note - for calendar calculations: does not account for leap seconds!" - }, - "days": { - "prefix": "days", - "description": "1 days == 24 hours", - "security":"Note - for calendar calculations: does not account for leap year or leap seconds!" - }, - "weeks": { - "prefix": "weeks", - "description": "1 weeks == 7 days", - "security":"Note - for calendar calculations: does not account for leap year or leap seconds!" - }, - "years": { - "prefix": "years", - "description": "1 years == 365 days", - "security":"**deprecated - do not use** Note - for calendar calculations: does not account for leap year or leap seconds!" - }, - "blockhash": { - "prefix": "blockhash", - "description": "blockhash(uint blockNumber) returns (bytes32): hash of the given block - only works for 256 most recent, excluding current, blocks", - "security":["Do not rely on block.timestamp, now and blockhash as a source of randomness, unless you know what you are doing.","Both the timestamp and the block hash can be influenced by miners to some degree. Bad actors in the mining community can for example run a casino payout function on a chosen hash and just retry a different hash if they did not receive any money.","The current block timestamp must be strictly larger than the timestamp of the last block, but the only guarantee is that it will be somewhere between the timestamps of two consecutive blocks in the canonical chain.","The block hashes are not available for all blocks for scalability reasons. You can only access the hashes of the most recent 256 blocks, all other values will be zero.","The function blockhash was previously known as block.blockhash, which was deprecated in version 0.4.22 and removed in version 0.5.0."] - }, - "_blockhash": { - "prefix": "block.blockhash", - "description": "blockhash(uint blockNumber) returns (bytes32): hash of the given block - only works for 256 most recent, excluding current, blocks", - "security":["Do not rely on block.timestamp, now and blockhash as a source of randomness, unless you know what you are doing.","Both the timestamp and the block hash can be influenced by miners to some degree. Bad actors in the mining community can for example run a casino payout function on a chosen hash and just retry a different hash if they did not receive any money.","The current block timestamp must be strictly larger than the timestamp of the last block, but the only guarantee is that it will be somewhere between the timestamps of two consecutive blocks in the canonical chain.","The block hashes are not available for all blocks for scalability reasons. You can only access the hashes of the most recent 256 blocks, all other values will be zero.","The function blockhash was previously known as block.blockhash, which was deprecated in version 0.4.22 and removed in version 0.5.0."] - }, - "_coinbase": { - "prefix": "block.coinbase", - "description": "block.coinbase (address payable): current block miner’s address", - "security":"" - }, - "_difficulty": { - "prefix": "block.difficulty", - "description": "block.difficulty (uint): current block difficulty", - "security":"" - }, - "_gaslimit": { - "prefix": "block.gaslimit", - "description": "block.gaslimit (uint): current block gaslimit", - "security":"" - }, - "_number": { - "prefix": "block.number", - "description": "block.number (uint): current block number", - "security":"Can be manipulated by miner" - }, - "_timestamp": { - "prefix": "block.timestamp", - "description": "block.timestamp (uint): current block timestamp as seconds since unix epoch", - "security":["Do not rely on block.timestamp, now and blockhash as a source of randomness, unless you know what you are doing.","Both the timestamp and the block hash can be influenced by miners to some degree. Bad actors in the mining community can for example run a casino payout function on a chosen hash and just retry a different hash if they did not receive any money.","The current block timestamp must be strictly larger than the timestamp of the last block, but the only guarantee is that it will be somewhere between the timestamps of two consecutive blocks in the canonical chain."] - }, - "gasleft": { - "prefix": "gasleft", - "description": "gasleft() returns (uint256): remaining gas", - "security":"The function gasleft was previously known as msg.gas, which was deprecated in version 0.4.21 and removed in version 0.5.0." - }, - "msg": { - "prefix": "msg", - "description": "msg", - "security":"The values of all members of msg, including msg.sender and msg.value can change for every external function call. This includes calls to library functions." - }, - "_data": { - "prefix": "msg.data", - "description": "msg.data (bytes calldata): complete calldata", - "security":"" - }, - "_sender": { - "prefix": "msg.sender", - "description": "msg.sender (address payable): sender of the message (current call)", - "security":"The values of all members of msg, including msg.sender and msg.value can change for every external function call. This includes calls to library functions." - }, - "_sig": { - "prefix": "msg.sig", - "description": "msg.sig (bytes4): first four bytes of the calldata (i.e. function identifier)", - "security":"" - }, - "_value": { - "prefix": "msg.value", - "description": "msg.value (uint): number of wei sent with the message", - "security":"The values of all members of msg, including msg.sender and msg.value can change for every external function call. This includes calls to library functions." - }, - "now": { - "prefix": "now", - "description": "now (uint): current block timestamp (alias for block.timestamp)", - "security":["Do not rely on block.timestamp, now and blockhash as a source of randomness, unless you know what you are doing.","Both the timestamp and the block hash can be influenced by miners to some degree. Bad actors in the mining community can for example run a casino payout function on a chosen hash and just retry a different hash if they did not receive any money.","The current block timestamp must be strictly larger than the timestamp of the last block, but the only guarantee is that it will be somewhere between the timestamps of two consecutive blocks in the canonical chain."] - }, - "_gasprice": { - "prefix": "tx.gasprice", - "description": "tx.gasprice (uint): gas price of the transaction", - "security":"" - }, - "_origin": { - "prefix": "tx.origin", - "description": "tx.origin (address payable): sender of the transaction (full call chain)", - "security":"Do not use for authentication" - }, - "abi": { - "prefix": "abi", - "description": "These encoding functions can be used to craft data for external function calls without actually calling an external function. Furthermore, keccak256(abi.encodePacked(a, b)) is a way to compute the hash of structured data (although be aware that it is possible to craft a “hash collision” using different function parameter types).", - "security":"error prone" - }, - "_decode": { - "prefix": "abi.decode", - "description": "abi.decode(bytes memory encodedData, (...)) returns (...): ABI-decodes the given data, while the types are given in parentheses as second argument. Example: (uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes))", - "security":"" - }, - "_encode": { - "prefix": "abi.encode", - "description": "abi.encode(...) returns (bytes memory): ABI-encodes the given arguments", - "security":"" - }, - "encodePacked": { - "prefix": "abi.encodePacked", - "description": "abi.encodePacked(...) returns (bytes memory): Performs packed encoding of the given arguments. Note that packed encoding can be ambiguous!", - "security":"" - }, - "_encodeWithSelector": { - "prefix": "abi.encodeWithSelector", - "description": "abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory): ABI-encodes the given arguments starting from the second and prepends the given four-byte selector", - "security":"" - }, - "encodeWithSignature": { - "prefix": "abi.encodeWithSignature", - "description": "abi.encodeWithSignature(string memory signature, ...) returns (bytes memory): Equivalent to abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)`", - "security":"" - }, - "assert": { - "prefix": "assert", - "description": "assert(bool condition):\ncauses an invalid opcode and thus state change reversion if the condition is not met - to be used for internal errors.", - "security":"" - }, - "require": { - "prefix": "require", - "description": ["require(bool condition):\n\treverts if the condition is not met - to be used for errors in inputs or external components.","require(bool condition, string memory message):\n\treverts if the condition is not met - to be used for errors in inputs or external components. Also provides an error message."], - "security":"" - }, - "revert": { - "prefix": "revert", - "description": ["revert():\n\tabort execution and revert state changes","revert(string memory reason):\n\tabort execution and revert state changes, providing an explanatory string"], - "security":"" - }, - "addmod": { - "prefix": "addmod", - "description": "addmod(uint x, uint y, uint k) returns (uint):\n\tcompute (x + y) % k where the addition is performed with arbitrary precision and does not wrap around at 2**256. Assert that k != 0 starting from version 0.5.0.", - "security":"" - }, - "mulmod": { - "prefix": "mulmod", - "description": "mulmod(uint x, uint y, uint k) returns (uint):\n\tcompute (x * y) % k where the multiplication is performed with arbitrary precision and does not wrap around at 2**256. Assert that k != 0 starting from version 0.5.0.", - "security":"" - }, - "keccak256": { - "prefix": "keccak256", - "description": "keccak256(bytes memory) returns (bytes32):\n\tcompute the Keccak-256 hash of the input", - "security":"" - }, - "sha256": { - "prefix": "sha256", - "description": "sha256(bytes memory) returns (bytes32):\n\tcompute the SHA-256 hash of the input", - "security":"It might be that you run into Out-of-Gas for sha256, ripemd160 or ecrecover on a private blockchain. The reason for this is that those are implemented as so-called precompiled contracts and these contracts only really exist after they received the first message (although their contract code is hardcoded). Messages to non-existing contracts are more expensive and thus the execution runs into an Out-of-Gas error. A workaround for this problem is to first send e.g. 1 Wei to each of the contracts before you use them in your actual contracts. This is not an issue on the official or test net." - }, - "ripemd160": { - "prefix": "ripemd160", - "description": "ripemd160(bytes memory) returns (bytes20):\n\tcompute RIPEMD-160 hash of the input", - "security":"It might be that you run into Out-of-Gas for sha256, ripemd160 or ecrecover on a private blockchain. The reason for this is that those are implemented as so-called precompiled contracts and these contracts only really exist after they received the first message (although their contract code is hardcoded). Messages to non-existing contracts are more expensive and thus the execution runs into an Out-of-Gas error. A workaround for this problem is to first send e.g. 1 Wei to each of the contracts before you use them in your actual contracts. This is not an issue on the official or test net." - }, - "ecrecover": { - "prefix": "ecrecover", - "description": "ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address):\n\trecover the address associated with the public key from elliptic curve signature or return zero on error (example usage)", - "security":["Function ecrecover returns an address, and not an address payable. See address payable for conversion, in case you need to transfer funds to the recovered address.","It might be that you run into Out-of-Gas for sha256, ripemd160 or ecrecover on a private blockchain. The reason for this is that those are implemented as so-called precompiled contracts and these contracts only really exist after they received the first message (although their contract code is hardcoded). Messages to non-existing contracts are more expensive and thus the execution runs into an Out-of-Gas error. A workaround for this problem is to first send e.g. 1 Wei to each of the contracts before you use them in your actual contracts. This is not an issue on the official or test net.", "check function signature (v:=uint8)", "check if replay protection is needed (nonce, chainid)"] - }, - "sha3": { - "prefix": "sha3", - "description": "sha3() --> keccak256(bytes memory) returns (bytes32):\n\tcompute the Keccak-256 hash of the input", - "security":"There used to be an alias for keccak256 called sha3, which was removed in version 0.5.0." - }, - "_balance": { - "prefix": ".balance", - "description": "
.balance (uint256):\n\tbalance of the Address in Wei", - "security":"Prior to version 0.5.0, Solidity allowed address members to be accessed by a contract instance, for example this.balance. This is now forbidden and an explicit conversion to address must be done: address(this).balance." - }, - "_transfer": { - "prefix": ".transfer", - "description": "
.transfer(uint256 amount):\n\tsend given amount of Wei to Address, reverts on failure, forwards 2300 gas stipend, not adjustable", - "security":"" - }, - "_send": { - "prefix": ".send", - "description": "
.send(uint256 amount) returns (bool):\n\tsend given amount of Wei to Address, returns false on failure, forwards 2300 gas stipend, not adjustable", - "security":"There are some dangers in using send: The transfer fails if the call stack depth is at 1024 (this can always be forced by the caller) and it also fails if the recipient runs out of gas. So in order to make safe Ether transfers, always check the return value of send, use transfer or even better: Use a pattern where the recipient withdraws the money." - }, - "_call": { - "prefix": ".call", - "description": "
.call(bytes memory) returns (bool, bytes memory):\n\tissue low-level CALL with the given payload, returns success condition and return data, forwards all available gas, adjustable", - "security":["You should avoid using .call() whenever possible when executing another contract function as it bypasses type checking, function existence check, and argument packing.","Prior to version 0.5.0, .call, .delegatecall and .staticcall only returned the success condition and not the return data."] - }, - "_delegatecall": { - "prefix": ".delegatecall", - "description": "
.delegatecall(bytes memory) returns (bool, bytes memory):\n\tissue low-level DELEGATECALL with the given payload, returns success condition and return data, forwards all available gas, adjustable", - "security":["If state variables are accessed via a low-level delegatecall, the storage layout of the two contracts must align in order for the called contract to correctly access the storage variables of the calling contract by name. This is of course not the case if storage pointers are passed as function arguments as in the case for the high-level libraries.","Prior to version 0.5.0, .call, .delegatecall and .staticcall only returned the success condition and not the return data."] - }, - "_staticcall": { - "prefix": ".staticcall", - "description": ["
.staticcall(bytes memory) returns (bool, bytes memory):\n\tissue low-level STATICCALL with the given payload, returns success condition and return data, forwards all available gas, adjustable","Prior to version 0.5.0, .call, .delegatecall and .staticcall only returned the success condition and not the return data."], - "security":"" - }, - "_callcode": { - "prefix": ".callcode", - "description": "
.delegatecall(bytes memory) returns (bool, bytes memory):\n\tissue low-level DELEGATECALL with the given payload, returns success condition and return data, forwards all available gas, adjustable", - "security":"Prior to version 0.5.0, there was a member called callcode with similar but slightly different semantics than delegatecall." - }, - "selfdestruct": { - "prefix": "selfdestruct", - "description": "selfdestruct(address payable recipient):\n\tdestroy the current contract, sending its funds to the given Address", - "security":"" - }, - "suicide": { - "prefix": "suicide", - "description": "selfdestruct(address payable recipient):\n\tdestroy the current contract, sending its funds to the given Address", - "security":"Prior to version 0.5.0, there was a function called suicide with the same semantics as selfdestruct." - }, - "this": { - "prefix": "this", - "description": "this (current contract’s type):\n\tthe current contract, explicitly convertible to Address", - "security":"" - }, - "_creationCode": { - "prefix": ".creationCode", - "description": "type(C).creationCode:\n\tMemory byte array that contains the creation bytecode of the contract. This can be used in inline assembly to build custom creation routines, especially by using the create2 opcode. This property can not be accessed in the contract itself or any derived contract. It causes the bytecode to be included in the bytecode of the call site and thus circular references like that are not possible.", - "security":"" - }, - "_runtimeCode": { - "prefix": ".runtimeCode", - "description": "type(C).runtimeCode:\n\tMemory byte array that contains the runtime bytecode of the contract. This is the code that is usually deployed by the constructor of C. If C has a constructor that uses inline assembly, this might be different from the actually deployed bytecode. Also note that libraries modify their runtime bytecode at time of deployment to guard against regular calls. The same restrictions as with .creationCode also apply for this property.", - "security":"" - }, - "memory": { - "prefix": "memory", - "description": "", - "security":["Array/Structs: check for uninit pointer.", - "Array/Structs: check that variable is not used before declaration"] - }, - "storage": { - "prefix": "storage", - "description": "", - "security":["Array/Structs: check for uninit pointer.", - "Array/Structs: check that variable is not used before declaration"] - }, - "calldata": { - "prefix": "calldata", - "description": "special data location that contains the function arguments, only available for external function call parameters", - "security":[] - }, - "ERC20": { - "prefix": "ERC20", - "description": "", - "security":"check if contract was modified" - }, - "while": { - "prefix": "while", - "description": "", - "security":"LOOP - check for OOG conditions (locking ether, DoS, ...)" - }, - "do": { - "prefix": "do", - "description": "", - "security":"LOOP - check for OOG conditions (locking ether, DoS, ...)" - }, - "for": { - "prefix": "for", - "description": "", - "security":"LOOP - check for OOG conditions (locking ether, DoS, ...)" - }, - "pragma": { - "prefix": "pragma", - "description": "", - "security":"avoid using experimental features! avoid specifying version ^" - }, - "is": { - "prefix": "is", - "description": "", - "security":"check inheritance order" - }, - ">>": { - "prefix": ">>", - "description": "", - "security":"The results produced by shift right of negative values of signed integer types is different from those produced by other programming languages. In Solidity, shift right maps to division so the shifted negative values are going to be rounded towards zero (truncated). In other programming languages the shift right of negative values works like division with rounding down (towards negative infinity)." - }, - "byte": { - "prefix": "byte", - "description": "byte is an alias for bytes1", - "security":"" - }, - "bytes": { - "prefix": "bytes", - "description": "Dynamically-sized byte array, see Arrays. Not a value-type!", - "security":"As a rule of thumb, use bytes for arbitrary-length raw byte data and string for arbitrary-length string (UTF-8) data. If you can limit the length to a certain number of bytes, always use one of bytes1 to bytes32 because they are much cheaper." - }, - "string": { - "prefix": "string", - "description": "Dynamically-sized UTF-8-encoded string, see Arrays. Not a value-type!", - "security":"As a rule of thumb, use bytes for arbitrary-length raw byte data and string for arbitrary-length string (UTF-8) data. If you can limit the length to a certain number of bytes, always use one of bytes1 to bytes32 because they are much cheaper." - }, - "_length":{ - "prefix":".length", - "description":".length yields the fixed length of the byte array (read-only)." - }, - "public":{ - "prefix":"public", - "description":"Public functions are part of the contract interface and can be either called internally or via messages. For public state variables, an automatic getter function (see below) is generated.", - "security":"make sure to authenticate calls to this method as anyone can access it" - }, - "external":{ - "prefix":"external", - "description":"External functions are part of the contract interface, which means they can be called from other contracts and via transactions. An external function f cannot be called internally (i.e. f() does not work, but this.f() works). External functions are sometimes more efficient when they receive large arrays of data.", - "security": "make sure to authenticate calls to this method as anyone can access it" - }, - "internal":{ - "prefix":"internal", - "description":"Those functions and state variables can only be accessed internally (i.e. from within the current contract or contracts deriving from it), without using this." - }, - "private":{ - "prefix":"private", - "description":"Private functions and state variables are only visible for the contract they are defined in and not in derived contracts.", - "security":"Everything that is inside a contract is visible to all external observers. Making something private only prevents other contracts from accessing and modifying the information, but it will still be visible to the whole world outside of the blockchain." - }, - "pure":{ - "prefix":"pure", - "description":"Functions can be declared pure in which case they promise not to read from or modify the state.", - "security": ["It is not possible to prevent functions from reading the state at the level of the EVM, it is only possible to prevent them from writing to the state (i.e. only view can be enforced at the EVM level, pure can not).", - "Before version 0.4.17 the compiler didn’t enforce that pure is not reading the state."] - }, - "view":{ - "prefix":"view", - "description":"function call CANNOT write state. It is however allowed to read state.", - "security":["Functions can be declared view in which case they promise not to modify the state.", - "constant on functions is an alias to view, but this is deprecated and will be dropped in version 0.5.0.","Getter methods are marked view.", - "The compiler does not enforce yet that a view method is not modifying state. It raises a warning though."] - }, - "extcodehash": { - "prefix": "extcodehash", - "description": "", - "security":"Note that EXTCODEHASH will be zero during constructor calls. Therefore it is not fit to use it to check if an address is a contract or not as this can be subverted by calling your contract in a constructor." - } -} \ No newline at end of file + "wei": { + "prefix": "wei", + "description": "1 wei == 10e-XX eth", + "security": "" + }, + "finney": { + "prefix": "finney", + "description": "1 finney == 10e-XX eth", + "security": "" + }, + "szabo": { + "prefix": "szabo", + "description": "1 szabo == 10e-XX eth", + "security": "" + }, + "ether": { + "prefix": "ether", + "description": "1 ether == 10e-XX eth", + "security": "" + }, + "seconds": { + "prefix": "seconds", + "description": "1 seconds == 10e-XX eth", + "security": "" + }, + "minutes": { + "prefix": "minutes", + "description": "1 minutes == 60 seconds", + "security": "Note - for calendar calculations: does not account for leap seconds!" + }, + "hours": { + "prefix": "hours", + "description": "1 hours == 60 minutes", + "security": "Note - for calendar calculations: does not account for leap seconds!" + }, + "days": { + "prefix": "days", + "description": "1 days == 24 hours", + "security": "Note - for calendar calculations: does not account for leap year or leap seconds!" + }, + "weeks": { + "prefix": "weeks", + "description": "1 weeks == 7 days", + "security": "Note - for calendar calculations: does not account for leap year or leap seconds!" + }, + "years": { + "prefix": "years", + "description": "1 years == 365 days", + "security": "**deprecated - do not use** Note - for calendar calculations: does not account for leap year or leap seconds!" + }, + "blockhash": { + "prefix": "blockhash", + "description": "blockhash(uint blockNumber) returns (bytes32): hash of the given block - only works for 256 most recent, excluding current, blocks", + "security": [ + "Do not rely on block.timestamp, now and blockhash as a source of randomness, unless you know what you are doing.", + "Both the timestamp and the block hash can be influenced by miners to some degree. Bad actors in the mining community can for example run a casino payout function on a chosen hash and just retry a different hash if they did not receive any money.", + "The current block timestamp must be strictly larger than the timestamp of the last block, but the only guarantee is that it will be somewhere between the timestamps of two consecutive blocks in the canonical chain.", + "The block hashes are not available for all blocks for scalability reasons. You can only access the hashes of the most recent 256 blocks, all other values will be zero.", + "The function blockhash was previously known as block.blockhash, which was deprecated in version 0.4.22 and removed in version 0.5.0." + ] + }, + "_blockhash": { + "prefix": "block.blockhash", + "description": "blockhash(uint blockNumber) returns (bytes32): hash of the given block - only works for 256 most recent, excluding current, blocks", + "security": [ + "Do not rely on block.timestamp, now and blockhash as a source of randomness, unless you know what you are doing.", + "Both the timestamp and the block hash can be influenced by miners to some degree. Bad actors in the mining community can for example run a casino payout function on a chosen hash and just retry a different hash if they did not receive any money.", + "The current block timestamp must be strictly larger than the timestamp of the last block, but the only guarantee is that it will be somewhere between the timestamps of two consecutive blocks in the canonical chain.", + "The block hashes are not available for all blocks for scalability reasons. You can only access the hashes of the most recent 256 blocks, all other values will be zero.", + "The function blockhash was previously known as block.blockhash, which was deprecated in version 0.4.22 and removed in version 0.5.0." + ] + }, + "_coinbase": { + "prefix": "block.coinbase", + "description": "block.coinbase (address payable): current block miner’s address", + "security": "" + }, + "_difficulty": { + "prefix": "block.difficulty", + "description": "block.difficulty (uint): current block difficulty", + "security": "" + }, + "_gaslimit": { + "prefix": "block.gaslimit", + "description": "block.gaslimit (uint): current block gaslimit", + "security": "" + }, + "_number": { + "prefix": "block.number", + "description": "block.number (uint): current block number", + "security": "Can be manipulated by miner" + }, + "_timestamp": { + "prefix": "block.timestamp", + "description": "block.timestamp (uint): current block timestamp as seconds since unix epoch", + "security": [ + "Do not rely on block.timestamp, now and blockhash as a source of randomness, unless you know what you are doing.", + "Both the timestamp and the block hash can be influenced by miners to some degree. Bad actors in the mining community can for example run a casino payout function on a chosen hash and just retry a different hash if they did not receive any money.", + "The current block timestamp must be strictly larger than the timestamp of the last block, but the only guarantee is that it will be somewhere between the timestamps of two consecutive blocks in the canonical chain." + ] + }, + "gasleft": { + "prefix": "gasleft", + "description": "gasleft() returns (uint256): remaining gas", + "security": "The function gasleft was previously known as msg.gas, which was deprecated in version 0.4.21 and removed in version 0.5.0." + }, + "msg": { + "prefix": "msg", + "description": "msg", + "security": "The values of all members of msg, including msg.sender and msg.value can change for every external function call. This includes calls to library functions." + }, + "_data": { + "prefix": "msg.data", + "description": "msg.data (bytes calldata): complete calldata", + "security": "" + }, + "_sender": { + "prefix": "msg.sender", + "description": "msg.sender (address payable): sender of the message (current call)", + "security": "The values of all members of msg, including msg.sender and msg.value can change for every external function call. This includes calls to library functions." + }, + "_sig": { + "prefix": "msg.sig", + "description": "msg.sig (bytes4): first four bytes of the calldata (i.e. function identifier)", + "security": "" + }, + "_value": { + "prefix": "msg.value", + "description": "msg.value (uint): number of wei sent with the message", + "security": "The values of all members of msg, including msg.sender and msg.value can change for every external function call. This includes calls to library functions." + }, + "now": { + "prefix": "now", + "description": "now (uint): current block timestamp (alias for block.timestamp)", + "security": [ + "Do not rely on block.timestamp, now and blockhash as a source of randomness, unless you know what you are doing.", + "Both the timestamp and the block hash can be influenced by miners to some degree. Bad actors in the mining community can for example run a casino payout function on a chosen hash and just retry a different hash if they did not receive any money.", + "The current block timestamp must be strictly larger than the timestamp of the last block, but the only guarantee is that it will be somewhere between the timestamps of two consecutive blocks in the canonical chain." + ] + }, + "_gasprice": { + "prefix": "tx.gasprice", + "description": "tx.gasprice (uint): gas price of the transaction", + "security": "" + }, + "_origin": { + "prefix": "tx.origin", + "description": "tx.origin (address payable): sender of the transaction (full call chain)", + "security": "Do not use for authentication" + }, + "abi": { + "prefix": "abi", + "description": "These encoding functions can be used to craft data for external function calls without actually calling an external function. Furthermore, keccak256(abi.encodePacked(a, b)) is a way to compute the hash of structured data (although be aware that it is possible to craft a “hash collision” using different function parameter types).", + "security": "error prone" + }, + "_decode": { + "prefix": "abi.decode", + "description": "abi.decode(bytes memory encodedData, (...)) returns (...): ABI-decodes the given data, while the types are given in parentheses as second argument. Example: (uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes))", + "security": "" + }, + "_encode": { + "prefix": "abi.encode", + "description": "abi.encode(...) returns (bytes memory): ABI-encodes the given arguments", + "security": "" + }, + "encodePacked": { + "prefix": "abi.encodePacked", + "description": "abi.encodePacked(...) returns (bytes memory): Performs packed encoding of the given arguments. Note that packed encoding can be ambiguous!", + "security": "" + }, + "_encodeWithSelector": { + "prefix": "abi.encodeWithSelector", + "description": "abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory): ABI-encodes the given arguments starting from the second and prepends the given four-byte selector", + "security": "" + }, + "encodeWithSignature": { + "prefix": "abi.encodeWithSignature", + "description": "abi.encodeWithSignature(string memory signature, ...) returns (bytes memory): Equivalent to abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)`", + "security": "" + }, + "assert": { + "prefix": "assert", + "description": "assert(bool condition):\ncauses an invalid opcode and thus state change reversion if the condition is not met - to be used for internal errors.", + "security": "" + }, + "require": { + "prefix": "require", + "description": [ + "require(bool condition):\n\treverts if the condition is not met - to be used for errors in inputs or external components.", + "require(bool condition, string memory message):\n\treverts if the condition is not met - to be used for errors in inputs or external components. Also provides an error message." + ], + "security": "" + }, + "revert": { + "prefix": "revert", + "description": [ + "revert():\n\tabort execution and revert state changes", + "revert(string memory reason):\n\tabort execution and revert state changes, providing an explanatory string" + ], + "security": "" + }, + "addmod": { + "prefix": "addmod", + "description": "addmod(uint x, uint y, uint k) returns (uint):\n\tcompute (x + y) % k where the addition is performed with arbitrary precision and does not wrap around at 2**256. Assert that k != 0 starting from version 0.5.0.", + "security": "" + }, + "mulmod": { + "prefix": "mulmod", + "description": "mulmod(uint x, uint y, uint k) returns (uint):\n\tcompute (x * y) % k where the multiplication is performed with arbitrary precision and does not wrap around at 2**256. Assert that k != 0 starting from version 0.5.0.", + "security": "" + }, + "keccak256": { + "prefix": "keccak256", + "description": "keccak256(bytes memory) returns (bytes32):\n\tcompute the Keccak-256 hash of the input", + "security": "" + }, + "sha256": { + "prefix": "sha256", + "description": "sha256(bytes memory) returns (bytes32):\n\tcompute the SHA-256 hash of the input", + "security": "It might be that you run into Out-of-Gas for sha256, ripemd160 or ecrecover on a private blockchain. The reason for this is that those are implemented as so-called precompiled contracts and these contracts only really exist after they received the first message (although their contract code is hardcoded). Messages to non-existing contracts are more expensive and thus the execution runs into an Out-of-Gas error. A workaround for this problem is to first send e.g. 1 Wei to each of the contracts before you use them in your actual contracts. This is not an issue on the official or test net." + }, + "ripemd160": { + "prefix": "ripemd160", + "description": "ripemd160(bytes memory) returns (bytes20):\n\tcompute RIPEMD-160 hash of the input", + "security": "It might be that you run into Out-of-Gas for sha256, ripemd160 or ecrecover on a private blockchain. The reason for this is that those are implemented as so-called precompiled contracts and these contracts only really exist after they received the first message (although their contract code is hardcoded). Messages to non-existing contracts are more expensive and thus the execution runs into an Out-of-Gas error. A workaround for this problem is to first send e.g. 1 Wei to each of the contracts before you use them in your actual contracts. This is not an issue on the official or test net." + }, + "ecrecover": { + "prefix": "ecrecover", + "description": "ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address):\n\trecover the address associated with the public key from elliptic curve signature or return zero on error (example usage)", + "security": [ + "Function ecrecover returns an address, and not an address payable. See address payable for conversion, in case you need to transfer funds to the recovered address.", + "It might be that you run into Out-of-Gas for sha256, ripemd160 or ecrecover on a private blockchain. The reason for this is that those are implemented as so-called precompiled contracts and these contracts only really exist after they received the first message (although their contract code is hardcoded). Messages to non-existing contracts are more expensive and thus the execution runs into an Out-of-Gas error. A workaround for this problem is to first send e.g. 1 Wei to each of the contracts before you use them in your actual contracts. This is not an issue on the official or test net.", + "check function signature (v:=uint8)", + "check if replay protection is needed (nonce, chainid)" + ] + }, + "sha3": { + "prefix": "sha3", + "description": "sha3() --> keccak256(bytes memory) returns (bytes32):\n\tcompute the Keccak-256 hash of the input", + "security": "There used to be an alias for keccak256 called sha3, which was removed in version 0.5.0." + }, + "_balance": { + "prefix": ".balance", + "description": "
.balance (uint256):\n\tbalance of the Address in Wei", + "security": "Prior to version 0.5.0, Solidity allowed address members to be accessed by a contract instance, for example this.balance. This is now forbidden and an explicit conversion to address must be done: address(this).balance." + }, + "_transfer": { + "prefix": ".transfer", + "description": "
.transfer(uint256 amount):\n\tsend given amount of Wei to Address, reverts on failure, forwards 2300 gas stipend, not adjustable", + "security": "" + }, + "_send": { + "prefix": ".send", + "description": "
.send(uint256 amount) returns (bool):\n\tsend given amount of Wei to Address, returns false on failure, forwards 2300 gas stipend, not adjustable", + "security": "There are some dangers in using send: The transfer fails if the call stack depth is at 1024 (this can always be forced by the caller) and it also fails if the recipient runs out of gas. So in order to make safe Ether transfers, always check the return value of send, use transfer or even better: Use a pattern where the recipient withdraws the money." + }, + "_call": { + "prefix": ".call", + "description": "
.call(bytes memory) returns (bool, bytes memory):\n\tissue low-level CALL with the given payload, returns success condition and return data, forwards all available gas, adjustable", + "security": [ + "You should avoid using .call() whenever possible when executing another contract function as it bypasses type checking, function existence check, and argument packing.", + "Prior to version 0.5.0, .call, .delegatecall and .staticcall only returned the success condition and not the return data." + ] + }, + "_delegatecall": { + "prefix": ".delegatecall", + "description": "
.delegatecall(bytes memory) returns (bool, bytes memory):\n\tissue low-level DELEGATECALL with the given payload, returns success condition and return data, forwards all available gas, adjustable", + "security": [ + "If state variables are accessed via a low-level delegatecall, the storage layout of the two contracts must align in order for the called contract to correctly access the storage variables of the calling contract by name. This is of course not the case if storage pointers are passed as function arguments as in the case for the high-level libraries.", + "Prior to version 0.5.0, .call, .delegatecall and .staticcall only returned the success condition and not the return data." + ] + }, + "_staticcall": { + "prefix": ".staticcall", + "description": [ + "
.staticcall(bytes memory) returns (bool, bytes memory):\n\tissue low-level STATICCALL with the given payload, returns success condition and return data, forwards all available gas, adjustable", + "Prior to version 0.5.0, .call, .delegatecall and .staticcall only returned the success condition and not the return data." + ], + "security": "" + }, + "_callcode": { + "prefix": ".callcode", + "description": "
.delegatecall(bytes memory) returns (bool, bytes memory):\n\tissue low-level DELEGATECALL with the given payload, returns success condition and return data, forwards all available gas, adjustable", + "security": "Prior to version 0.5.0, there was a member called callcode with similar but slightly different semantics than delegatecall." + }, + "selfdestruct": { + "prefix": "selfdestruct", + "description": "selfdestruct(address payable recipient):\n\tdestroy the current contract, sending its funds to the given Address", + "security": "" + }, + "suicide": { + "prefix": "suicide", + "description": "selfdestruct(address payable recipient):\n\tdestroy the current contract, sending its funds to the given Address", + "security": "Prior to version 0.5.0, there was a function called suicide with the same semantics as selfdestruct." + }, + "this": { + "prefix": "this", + "description": "this (current contract’s type):\n\tthe current contract, explicitly convertible to Address", + "security": "" + }, + "_creationCode": { + "prefix": ".creationCode", + "description": "type(C).creationCode:\n\tMemory byte array that contains the creation bytecode of the contract. This can be used in inline assembly to build custom creation routines, especially by using the create2 opcode. This property can not be accessed in the contract itself or any derived contract. It causes the bytecode to be included in the bytecode of the call site and thus circular references like that are not possible.", + "security": "" + }, + "_runtimeCode": { + "prefix": ".runtimeCode", + "description": "type(C).runtimeCode:\n\tMemory byte array that contains the runtime bytecode of the contract. This is the code that is usually deployed by the constructor of C. If C has a constructor that uses inline assembly, this might be different from the actually deployed bytecode. Also note that libraries modify their runtime bytecode at time of deployment to guard against regular calls. The same restrictions as with .creationCode also apply for this property.", + "security": "" + }, + "memory": { + "prefix": "memory", + "description": "", + "security": [ + "Array/Structs: check for uninit pointer.", + "Array/Structs: check that variable is not used before declaration" + ] + }, + "storage": { + "prefix": "storage", + "description": "", + "security": [ + "Array/Structs: check for uninit pointer.", + "Array/Structs: check that variable is not used before declaration" + ] + }, + "calldata": { + "prefix": "calldata", + "description": "special data location that contains the function arguments, only available for external function call parameters", + "security": [] + }, + "ERC20": { + "prefix": "ERC20", + "description": "", + "security": "check if contract was modified" + }, + "while": { + "prefix": "while", + "description": "", + "security": "LOOP - check for OOG conditions (locking ether, DoS, ...)" + }, + "do": { + "prefix": "do", + "description": "", + "security": "LOOP - check for OOG conditions (locking ether, DoS, ...)" + }, + "for": { + "prefix": "for", + "description": "", + "security": "LOOP - check for OOG conditions (locking ether, DoS, ...)" + }, + "pragma": { + "prefix": "pragma", + "description": "", + "security": "avoid using experimental features! avoid specifying version ^" + }, + "is": { + "prefix": "is", + "description": "", + "security": "check inheritance order" + }, + ">>": { + "prefix": ">>", + "description": "", + "security": "The results produced by shift right of negative values of signed integer types is different from those produced by other programming languages. In Solidity, shift right maps to division so the shifted negative values are going to be rounded towards zero (truncated). In other programming languages the shift right of negative values works like division with rounding down (towards negative infinity)." + }, + "byte": { + "prefix": "byte", + "description": "byte is an alias for bytes1", + "security": "" + }, + "bytes": { + "prefix": "bytes", + "description": "Dynamically-sized byte array, see Arrays. Not a value-type!", + "security": "As a rule of thumb, use bytes for arbitrary-length raw byte data and string for arbitrary-length string (UTF-8) data. If you can limit the length to a certain number of bytes, always use one of bytes1 to bytes32 because they are much cheaper." + }, + "string": { + "prefix": "string", + "description": "Dynamically-sized UTF-8-encoded string, see Arrays. Not a value-type!", + "security": "As a rule of thumb, use bytes for arbitrary-length raw byte data and string for arbitrary-length string (UTF-8) data. If you can limit the length to a certain number of bytes, always use one of bytes1 to bytes32 because they are much cheaper." + }, + "_length": { + "prefix": ".length", + "description": ".length yields the fixed length of the byte array (read-only)." + }, + "public": { + "prefix": "public", + "description": "Public functions are part of the contract interface and can be either called internally or via messages. For public state variables, an automatic getter function (see below) is generated.", + "security": "make sure to authenticate calls to this method as anyone can access it" + }, + "external": { + "prefix": "external", + "description": "External functions are part of the contract interface, which means they can be called from other contracts and via transactions. An external function f cannot be called internally (i.e. f() does not work, but this.f() works). External functions are sometimes more efficient when they receive large arrays of data.", + "security": "make sure to authenticate calls to this method as anyone can access it" + }, + "internal": { + "prefix": "internal", + "description": "Those functions and state variables can only be accessed internally (i.e. from within the current contract or contracts deriving from it), without using this." + }, + "private": { + "prefix": "private", + "description": "Private functions and state variables are only visible for the contract they are defined in and not in derived contracts.", + "security": "Everything that is inside a contract is visible to all external observers. Making something private only prevents other contracts from accessing and modifying the information, but it will still be visible to the whole world outside of the blockchain." + }, + "pure": { + "prefix": "pure", + "description": "Functions can be declared pure in which case they promise not to read from or modify the state.", + "security": [ + "It is not possible to prevent functions from reading the state at the level of the EVM, it is only possible to prevent them from writing to the state (i.e. only view can be enforced at the EVM level, pure can not).", + "Before version 0.4.17 the compiler didn’t enforce that pure is not reading the state." + ] + }, + "view": { + "prefix": "view", + "description": "function call CANNOT write state. It is however allowed to read state.", + "security": [ + "Functions can be declared view in which case they promise not to modify the state.", + "constant on functions is an alias to view, but this is deprecated and will be dropped in version 0.5.0.", + "Getter methods are marked view.", + "The compiler does not enforce yet that a view method is not modifying state. It raises a warning though." + ] + }, + "extcodehash": { + "prefix": "extcodehash", + "description": "", + "security": "Note that EXTCODEHASH will be zero during constructor calls. Therefore it is not fit to use it to check if an address is a contract or not as this can be subverted by calling your contract in a constructor." + } +} diff --git a/src/features/parser/parserHelpers.js b/src/features/parser/parserHelpers.js index b699ba2..7ad6a77 100644 --- a/src/features/parser/parserHelpers.js +++ b/src/features/parser/parserHelpers.js @@ -1,16 +1,25 @@ -'use strict'; -/** +"use strict"; +/** * @author github.com/tintinweb * @license GPLv3 - * - * + * + * * */ //taken from https://github.com/ConsenSys/surya/blob/3147a190152caf8da5e3cfc79d4afcda54d3b0aa/src/utils/parserHelpers.js //thx goncalo and surya! const BUILTINS = [ - 'gasleft', 'require', 'assert', 'revert', 'addmod', 'mulmod', 'keccak256', - 'sha256', 'sha3', 'ripemd160', 'ecrecover', + "gasleft", + "require", + "assert", + "revert", + "addmod", + "mulmod", + "keccak256", + "sha256", + "sha3", + "ripemd160", + "ecrecover", ]; function isLowerCase(str) { @@ -18,42 +27,58 @@ function isLowerCase(str) { } const parserHelpers = { - isRegularFunctionCall: node => { + isRegularFunctionCall: (node) => { const expr = node.expression; // @TODO: replace lowercase for better filtering - return expr.type === 'Identifier' && isLowerCase(expr.name[0]) && !BUILTINS.includes(expr.name); + return ( + expr.type === "Identifier" && + isLowerCase(expr.name[0]) && + !BUILTINS.includes(expr.name) + ); }, - isMemberAccess: node => { + isMemberAccess: (node) => { const expr = node.expression; - return expr.type === 'MemberAccess' && !['push', 'pop'].includes(expr.memberName); + return ( + expr.type === "MemberAccess" && !["push", "pop"].includes(expr.memberName) + ); }, - isMemberAccessOfAddress: node => { + isMemberAccessOfAddress: (node) => { const expr = node.expression.expression; - return expr.type === 'FunctionCall' - && expr.expression.hasOwnProperty('typeName') - && expr.expression.typeName.name === 'address'; + return ( + expr.type === "FunctionCall" && + expr.expression.hasOwnProperty("typeName") && + expr.expression.typeName.name === "address" + ); }, - isAContractTypecast: node => { + isAContractTypecast: (node) => { const expr = node.expression.expression; // @TODO: replace lowercase for better filtering - return expr.type === 'FunctionCall' - && expr.expression.hasOwnProperty('name') - && !isLowerCase(expr.expression.name[0]); + return ( + expr.type === "FunctionCall" && + expr.expression.hasOwnProperty("name") && + !isLowerCase(expr.expression.name[0]) + ); }, - isUserDefinedDeclaration: node => { - return node.hasOwnProperty('typeName') && node.typeName.hasOwnProperty('type') && node.typeName.type === 'UserDefinedTypeName'; + isUserDefinedDeclaration: (node) => { + return ( + node.hasOwnProperty("typeName") && + node.typeName.hasOwnProperty("type") && + node.typeName.type === "UserDefinedTypeName" + ); }, - isAddressDeclaration: node => { - return node.hasOwnProperty('typeName') - && node.typeName.hasOwnProperty('type') - && node.typeName.type === 'ElementaryTypeName' - && node.typeName.name === 'address'; + isAddressDeclaration: (node) => { + return ( + node.hasOwnProperty("typeName") && + node.typeName.hasOwnProperty("type") && + node.typeName.type === "ElementaryTypeName" && + node.typeName.name === "address" + ); }, }; -module.exports = parserHelpers; \ No newline at end of file +module.exports = parserHelpers; diff --git a/src/features/references.js b/src/features/references.js index 2f35ef9..8d914f4 100644 --- a/src/features/references.js +++ b/src/features/references.js @@ -1,104 +1,107 @@ -/** +/** * @author github.com/tintinweb * @license GPLv3 - * - * + * + * * */ //API REF: https://code.visualstudio.com/api/references/vscode-api#ReferenceProvider -const vscode = require('vscode'); -const settings = require('../settings.js'); -const fs = require('fs').promises; +const vscode = require("vscode"); +const settings = require("../settings.js"); +const fs = require("fs").promises; function getIndicesOf(searchStr, str, caseSensitive) { - var searchStrLen = searchStr.length; - if (searchStrLen == 0) { - return []; - } - var startIndex = 0, index, indices = []; - if (!caseSensitive) { - str = str.toLowerCase(); - searchStr = searchStr.toLowerCase(); - } - while ((index = str.indexOf(searchStr, startIndex)) > -1) { - indices.push(index); - startIndex = index + searchStrLen; - } - return indices; + var searchStrLen = searchStr.length; + if (searchStrLen == 0) { + return []; + } + var startIndex = 0, + index, + indices = []; + if (!caseSensitive) { + str = str.toLowerCase(); + searchStr = searchStr.toLowerCase(); + } + while ((index = str.indexOf(searchStr, startIndex)) > -1) { + indices.push(index); + startIndex = index + searchStrLen; + } + return indices; } function getIndicesOfRex(searchRex, str) { - var regEx = new RegExp("\\b" + searchRex + "\\b", "g"); - let match; - let results = []; - while (match = regEx.exec(str)) { - results.push({ index: match.index, len: match[0].trim().length }); - } - return results; + var regEx = new RegExp("\\b" + searchRex + "\\b", "g"); + let match; + let results = []; + while ((match = regEx.exec(str))) { + results.push({ index: match.index, len: match[0].trim().length }); + } + return results; } function indicesToVscodeRange(uri, indices, data, cb) { - const lineIndices = getIndicesOf("\n", data, true); - indices.forEach(i => { - //find line - let lineIndex; + const lineIndices = getIndicesOf("\n", data, true); + indices.forEach((i) => { + //find line + let lineIndex; - let lineNumber = lineIndices.findIndex(li => i.index < li); - if (lineNumber <= 0) { - lineNumber = 0; //maybe firstline - lineIndex = 0; //firstline. - } else { - lineNumber--; // its the previous line - lineIndex = lineIndices[lineNumber]; - } + let lineNumber = lineIndices.findIndex((li) => i.index < li); + if (lineNumber <= 0) { + lineNumber = 0; //maybe firstline + lineIndex = 0; //firstline. + } else { + lineNumber--; // its the previous line + lineIndex = lineIndices[lineNumber]; + } - if (i.index > 0) { - i.index--; //vscode columns start at 1 - } + if (i.index > 0) { + i.index--; //vscode columns start at 1 + } - let pos = new vscode.Range( - new vscode.Position(lineNumber + 1, i.index - lineIndex), - new vscode.Position(lineNumber + 1, i.index - lineIndex + i.len) - ); - cb(new vscode.Location(uri, pos)); - }); + let pos = new vscode.Range( + new vscode.Position(lineNumber + 1, i.index - lineIndex), + new vscode.Position(lineNumber + 1, i.index - lineIndex + i.len), + ); + cb(new vscode.Location(uri, pos)); + }); } class SolidityReferenceProvider { + provideReferences(document, position, context, token) { + console.log("providing references ..."); + return new Promise(async (resolve, reject) => { + var locations = []; - provideReferences(document, position, context, token) { - console.log("providing references ..."); - return new Promise(async (resolve, reject) => { - var locations = []; + const range = document.getWordRangeAtPosition(position); + if (!range || range.length <= 0) { + return reject(); + } + const word = document.getText(range); - const range = document.getWordRangeAtPosition(position); - if (!range || range.length <= 0) { - return reject(); - } - const word = document.getText(range); - - /* + /* DANGER: UGLY HACK AHEAD. @todo: replace this with a clean solution. this is just an initial hack to make "find references" work. */ - await vscode.workspace.findFiles("**/*.sol", settings.DEFAULT_FINDFILES_EXCLUDES, 500) - .then(async uris => { - - await Promise.all(uris.map(async (uri) => { - let data = await fs.readFile(uri.fsPath, 'utf8'); - if (!data) { - return; - } - const indicesRex = getIndicesOfRex(word, data); - indicesToVscodeRange(uri, indicesRex, data, (elem) => locations.push(elem)); - })); - return resolve(locations); - }); - + await vscode.workspace + .findFiles("**/*.sol", settings.DEFAULT_FINDFILES_EXCLUDES, 500) + .then(async (uris) => { + await Promise.all( + uris.map(async (uri) => { + let data = await fs.readFile(uri.fsPath, "utf8"); + if (!data) { + return; + } + const indicesRex = getIndicesOfRex(word, data); + indicesToVscodeRange(uri, indicesRex, data, (elem) => + locations.push(elem), + ); + }), + ); + return resolve(locations); }); - } + }); + } } - module.exports = { - SolidityReferenceProvider: SolidityReferenceProvider -}; \ No newline at end of file + SolidityReferenceProvider: SolidityReferenceProvider, +}; diff --git a/src/features/symbols.js b/src/features/symbols.js index 9a87839..69d742f 100644 --- a/src/features/symbols.js +++ b/src/features/symbols.js @@ -1,643 +1,707 @@ -'use strict'; -/** +"use strict"; +/** * @author github.com/tintinweb * @license GPLv3 - * - * + * + * * */ -const vscode = require('vscode'); -const settings = require('../settings.js'); - -function getFakeNode(name, line){ - return { - name: name, - length:0, - loc: { - start:{ - line:line, - column:0 - }, - end:{ - line:line, - column:0} - } - }; +const vscode = require("vscode"); +const settings = require("../settings.js"); + +function getFakeNode(name, line) { + return { + name: name, + length: 0, + loc: { + start: { + line: line, + column: 0, + }, + end: { + line: line, + column: 0, + }, + }, + }; } const stateMutabilityToIcon = { - view:"👀", - pure:"🌳", - constant:"👀", - payable:"💰" + view: "👀", + pure: "🌳", + constant: "👀", + payable: "💰", }; const visibilityToIcon = { - external:"❗️", - public:"❗️", - private:"🔐", - internal:"🔒" + external: "❗️", + public: "❗️", + private: "🔐", + internal: "🔒", }; -function getStateMutabilityToIcon(state){ - let v = stateMutabilityToIcon[state]; - if (typeof v == "undefined") - return ""; - return v; +function getStateMutabilityToIcon(state) { + let v = stateMutabilityToIcon[state]; + if (typeof v == "undefined") return ""; + return v; } -function getVisibilityToIcon(state){ - let v = visibilityToIcon[state]; - if (typeof v == "undefined") - return ""; - return v; +function getVisibilityToIcon(state) { + let v = visibilityToIcon[state]; + if (typeof v == "undefined") return ""; + return v; } -function astNodeAsDocumentSymbol(document, node, kind, name, detail){ - return new vscode.DocumentSymbol( - typeof name!="undefined"?name:node.name, - typeof detail!="undefined"?detail:"", - kind, - new vscode.Range( - node.loc.start.line-1, - node.loc.start.column, - node.loc.end.line-1, - typeof node.length!="undefined"?node.loc.end.column+node.length:node.loc.end.column - ), - new vscode.Range( - node.loc.start.line-1, - node.loc.start.column, - node.loc.end.line-1, - typeof node.length!="undefined"?node.loc.end.column+node.length:node.loc.end.column - ) - ); - +function astNodeAsDocumentSymbol(document, node, kind, name, detail) { + return new vscode.DocumentSymbol( + typeof name != "undefined" ? name : node.name, + typeof detail != "undefined" ? detail : "", + kind, + new vscode.Range( + node.loc.start.line - 1, + node.loc.start.column, + node.loc.end.line - 1, + typeof node.length != "undefined" + ? node.loc.end.column + node.length + : node.loc.end.column, + ), + new vscode.Range( + node.loc.start.line - 1, + node.loc.start.column, + node.loc.end.line - 1, + typeof node.length != "undefined" + ? node.loc.end.column + node.length + : node.loc.end.column, + ), + ); } -function varDecIsArray(node){ - return node.typeName.type=="ArrayTypeName"; +function varDecIsArray(node) { + return node.typeName.type == "ArrayTypeName"; } -function varDecIsUserDefined(node){ - return node.typeName.type=="UserDefinedTypeName"; +function varDecIsUserDefined(node) { + return node.typeName.type == "UserDefinedTypeName"; } -function getVariableDeclarationType(node){ - if (typeof node.typeName != "undefined" && node.typeName != null){ - if(varDecIsArray(node)){ - node = node.typeName.baseTypeName; - } else - node = node.typeName; - } - - if(node.type=="ElementaryTypeName"){ - return node.name; - } else if (node.type=="UserDefinedTypeName"){ - return node.namePath; - } else if (node.type=="Mapping"){ - node.namePath = "mapping( " + getVariableDeclarationType(node.keyType)+ "=>" +getVariableDeclarationType(node.valueType)+ " )"; - return node.namePath; - } else { - return null; - } +function getVariableDeclarationType(node) { + if (typeof node.typeName != "undefined" && node.typeName != null) { + if (varDecIsArray(node)) { + node = node.typeName.baseTypeName; + } else node = node.typeName; + } + + if (node.type == "ElementaryTypeName") { + return node.name; + } else if (node.type == "UserDefinedTypeName") { + return node.namePath; + } else if (node.type == "Mapping") { + node.namePath = + "mapping( " + + getVariableDeclarationType(node.keyType) + + "=>" + + getVariableDeclarationType(node.valueType) + + " )"; + return node.namePath; + } else { + return null; + } } const varDecToSymbolType = { - string: vscode.SymbolKind.String, - array: vscode.SymbolKind.Array, - bool: vscode.SymbolKind.Boolean, - uint: vscode.SymbolKind.Number, - int: vscode.SymbolKind.Number, - bytes: vscode.SymbolKind.Array, - address: vscode.SymbolKind.Variable, - user: vscode.SymbolKind.Array + string: vscode.SymbolKind.String, + array: vscode.SymbolKind.Array, + bool: vscode.SymbolKind.Boolean, + uint: vscode.SymbolKind.Number, + int: vscode.SymbolKind.Number, + bytes: vscode.SymbolKind.Array, + address: vscode.SymbolKind.Variable, + user: vscode.SymbolKind.Array, }; -function getVariableDeclarationTypeAsSymbolKind(node, _default){ - if(varDecIsUserDefined(node)){ - return varDecToSymbolType.user; - } - - let solidityType = getVariableDeclarationType(node); - if (!solidityType) - return _default; - - if (solidityType.startsWith("uint") || solidityType.startsWith("int")){ - return varDecToSymbolType.uint; - } else if (solidityType.startsWith("bytes")){ - return varDecToSymbolType.bytes; - } - - let kind = varDecToSymbolType[solidityType]; - return typeof kind!="undefined"?kind:_default; - +function getVariableDeclarationTypeAsSymbolKind(node, _default) { + if (varDecIsUserDefined(node)) { + return varDecToSymbolType.user; + } + + let solidityType = getVariableDeclarationType(node); + if (!solidityType) return _default; + + if (solidityType.startsWith("uint") || solidityType.startsWith("int")) { + return varDecToSymbolType.uint; + } else if (solidityType.startsWith("bytes")) { + return varDecToSymbolType.bytes; + } + + let kind = varDecToSymbolType[solidityType]; + return typeof kind != "undefined" ? kind : _default; } -function getSymbolKindForDeclaration(node){ - let astnode = typeof node._node!="undefined"?node._node:node; - let result = { - symbol: vscode.SymbolKind.Variable, - prefix: "", - suffix: "", - name: typeof astnode.name!="undefined" ? astnode.name:"", - details: "" - }; - - switch(astnode.type) { - case "ModifierInvocation": - case "ModifierDefinition": - result.symbol = vscode.SymbolKind.Method; - - result.prefix += "Ⓜ "; - - if (settings.extensionConfig().outline.decorations){ - result.prefix += getVisibilityToIcon(astnode.visibility); - result.prefix += getStateMutabilityToIcon(astnode.stateMutability); - } - break; - case "EventDefinition": - result.symbol = vscode.SymbolKind.Event; - break; - case "FunctionDefinition": - if (astnode.isConstructor){ - result.symbol = vscode.SymbolKind.Constructor; - result.name = "⚜ __constructor__ " + (result.name?result.name:""); - } else { - result.symbol = vscode.SymbolKind.Function; - } - if (settings.extensionConfig().outline.decorations){ - result.prefix += getVisibilityToIcon(astnode.visibility); - result.prefix += getStateMutabilityToIcon(astnode.stateMutability); +function getSymbolKindForDeclaration(node) { + let astnode = typeof node._node != "undefined" ? node._node : node; + let result = { + symbol: vscode.SymbolKind.Variable, + prefix: "", + suffix: "", + name: typeof astnode.name != "undefined" ? astnode.name : "", + details: "", + }; + + switch (astnode.type) { + case "ModifierInvocation": + case "ModifierDefinition": + result.symbol = vscode.SymbolKind.Method; + + result.prefix += "Ⓜ "; + + if (settings.extensionConfig().outline.decorations) { + result.prefix += getVisibilityToIcon(astnode.visibility); + result.prefix += getStateMutabilityToIcon(astnode.stateMutability); + } + break; + case "EventDefinition": + result.symbol = vscode.SymbolKind.Event; + break; + case "FunctionDefinition": + if (astnode.isConstructor) { + result.symbol = vscode.SymbolKind.Constructor; + result.name = "⚜ __constructor__ " + (result.name ? result.name : ""); + } else { + result.symbol = vscode.SymbolKind.Function; + } + if (settings.extensionConfig().outline.decorations) { + result.prefix += getVisibilityToIcon(astnode.visibility); + result.prefix += getStateMutabilityToIcon(astnode.stateMutability); + } + + if (settings.extensionConfig().outline.extras) { + (result.suffix += " ( "), + (result.suffix += " complex: " + node.complexity); + result.suffix += " state: " + (node.accesses_svar ? "☑" : "☐"); + result.suffix += " )"; + } + break; + case "EnumDefinition": + result.symbol = vscode.SymbolKind.Enum; + break; + case "StructDefinition": + result.symbol = vscode.SymbolKind.Struct; + break; + case "VariableDeclaration": + if (settings.extensionConfig().outline.var.storage_annotations) { + if (astnode.storageLocation == "memory") { + result.prefix += "💾"; + result.details += astnode.storageLocation; + } else if (astnode.storageLocation == "storage") { + result.prefix += "💽"; + result.details += astnode.storageLocation; + } + } + if (varDecIsArray(astnode)) { + result.name += "[]"; + } + + if (astnode.isDeclaredConst) { + result.symbol = vscode.SymbolKind.Constant; + break; + } + //result.symbol = vscode.SymbolKind.Variable + + result.symbol = getVariableDeclarationTypeAsSymbolKind( + astnode, + vscode.SymbolKind.Variable, + ); + break; + case "Parameter": + if (settings.extensionConfig().outline.var.storage_annotations) { + if (astnode.storageLocation == "memory") { + result.prefix += "💾"; + result.details += astnode.storageLocation; + } else if (astnode.storageLocation == "storage") { + result.prefix += "💽"; + result.details += astnode.storageLocation; + } + } + if (varDecIsArray(astnode)) { + result.name += "[]"; + } + result.symbol = vscode.SymbolKind.TypeParameter; // lets misuse this kind for params + break; + case "ContractDefinition": + if (astnode.kind == "interface") { + result.symbol = vscode.SymbolKind.Interface; + } else if (astnode.kind == "library") { + result.symbol = vscode.SymbolKind.Class; + result.prefix += "📚"; + } else { + result.symbol = vscode.SymbolKind.Class; + } + break; + case "AssemblyFunctionDefinition": + result.symbol = vscode.SymbolKind.Function; + break; + default: + console.error("<-----"); + } + if (result.prefix) { + result.prefix = result.prefix + " "; //add space + } + return result; +} + +function getAstValueForExpression(astnode) { + switch (astnode.type) { + case "NumberLiteral": + return `${astnode.number}${ + astnode.subdenominator ? astnode.subdenominator : "" + }`; + case "BooleanLiteral": + return astnode.value ? "true" : "false"; + case "StringLiteral": + case "HexLiteral": + case "HexNumber": + case "DecimalNumber": + return astnode.value; + default: + return ""; + } +} + +class SolidityDocumentSymbolProvider { + constructor(g_workspace) { + this.g_workspace = g_workspace; + } + + provideDocumentSymbols(document, token) { + console.log("preparing symbols..."); + + return new Promise((resolve, reject) => { + return this.g_workspace + .add(document.fileName, { content: document.getText() }) + .then((insights) => { + var symbols = []; + + console.log(`✓ inspect ${insights.filePath}`); + + console.log("--- preparing symbols for: " + document.fileName); + + if (token.isCancellationRequested) { + reject(token); + return; + } + + var topLevelNode; + + if (settings.extensionConfig().outline.pragmas.show) { + topLevelNode = astNodeAsDocumentSymbol( + document, + getFakeNode("pragma", 1), + vscode.SymbolKind.Namespace, + "pragma", + "... (" + insights.pragmas.length + ")", + ); + symbols.push(topLevelNode); + insights.pragmas.forEach(function (item) { + topLevelNode.children.push( + astNodeAsDocumentSymbol( + document, + item, + vscode.SymbolKind.Namespace, + item.name + " → " + item.value, + ), + ); + }); + console.log("✓ pragmas "); + } + + if (settings.extensionConfig().outline.imports.show) { + topLevelNode = astNodeAsDocumentSymbol( + document, + getFakeNode("imports", 1), + vscode.SymbolKind.Namespace, + "imports", + "... (" + insights.imports.length + ")", + ); + symbols.push(topLevelNode); + insights.imports.forEach(function (item) { + topLevelNode.children.push( + astNodeAsDocumentSymbol( + document, + item, + vscode.SymbolKind.File, + item.path, + ), + ); + }); + + console.log("✓ imports "); + } + + for (var contractName in insights.contracts) { + let symbolAnnotation = getSymbolKindForDeclaration( + insights.contracts[contractName], + ); + topLevelNode = astNodeAsDocumentSymbol( + document, + insights.contracts[contractName]._node, + symbolAnnotation.symbol, + symbolAnnotation.prefix + + symbolAnnotation.name + + symbolAnnotation.suffix, + ); + symbols.push(topLevelNode); + + /** the document */ + console.log("✓ contracts " + contractName); + /** constructor - if known */ + if (insights.contracts[contractName].constructor) { + topLevelNode.children.push( + astNodeAsDocumentSymbol( + document, + insights.contracts[contractName].constructor._node, + vscode.SymbolKind.Constructor, + ), + ); } + console.log("✓ constructor"); + /** stateVars */ + for (var svar in insights.contracts[contractName].stateVars) { + let symbolAnnotation = getSymbolKindForDeclaration( + insights.contracts[contractName].stateVars[svar], + ); - if (settings.extensionConfig().outline.extras){ - result.suffix += " ( ", - result.suffix += " complex: " + node.complexity; - result.suffix += " state: " + (node.accesses_svar?"☑":"☐"); - result.suffix += " )"; + topLevelNode.children.push( + astNodeAsDocumentSymbol( + document, + insights.contracts[contractName].stateVars[svar], + symbolAnnotation.symbol, + symbolAnnotation.prefix + + symbolAnnotation.name + + symbolAnnotation.suffix, + symbolAnnotation.details, + ), + ); } - break; - case "EnumDefinition": - result.symbol = vscode.SymbolKind.Enum; - break; - case "StructDefinition": - result.symbol = vscode.SymbolKind.Struct; - break; - case "VariableDeclaration": - if(settings.extensionConfig().outline.var.storage_annotations){ - if(astnode.storageLocation=="memory"){ - result.prefix +="💾"; - result.details += astnode.storageLocation; - } else if(astnode.storageLocation=="storage"){ - result.prefix +="💽"; - result.details += astnode.storageLocation; - } + console.log("✓ statevars"); + + for (let name in insights.contracts[contractName].enums) { + topLevelNode.children.push( + astNodeAsDocumentSymbol( + document, + insights.contracts[contractName].enums[name], + vscode.SymbolKind.Enum, + ), + ); } - if(varDecIsArray(astnode)){ - result.name += "[]"; + console.log("✓ enums"); + for (let name in insights.contracts[contractName].structs) { + topLevelNode.children.push( + astNodeAsDocumentSymbol( + document, + insights.contracts[contractName].structs[name], + vscode.SymbolKind.Struct, + ), + ); } + console.log("✓ structs"); + var functionLevelNode; + /** functions - may include constructor / fallback */ + for (let funcObj of insights.contracts[contractName].functions) { + let symbolAnnotation = getSymbolKindForDeclaration(funcObj); + functionLevelNode = astNodeAsDocumentSymbol( + document, + funcObj._node, + symbolAnnotation.symbol, + symbolAnnotation.prefix + + symbolAnnotation.name + + symbolAnnotation.suffix, + symbolAnnotation.details, + ); - if(astnode.isDeclaredConst){ - result.symbol = vscode.SymbolKind.Constant; - break; - } - //result.symbol = vscode.SymbolKind.Variable - - result.symbol = getVariableDeclarationTypeAsSymbolKind(astnode, vscode.SymbolKind.Variable); - break; - case "Parameter": - if(settings.extensionConfig().outline.var.storage_annotations){ - if(astnode.storageLocation=="memory"){ - result.prefix +="💾"; - result.details += astnode.storageLocation; - } else if(astnode.storageLocation=="storage"){ - result.prefix +="💽"; - result.details += astnode.storageLocation; + topLevelNode.children.push(functionLevelNode); + // add a fake modifiers list to outline + // add pseudonode modifiers + let numModifiers = Object.keys(funcObj.modifiers).length; + if (numModifiers !== 0) { + let modifiersLevelNode = astNodeAsDocumentSymbol( + document, + getFakeNode("modifiers", 1), + vscode.SymbolKind.Namespace, + "modifiers", + "... (" + numModifiers + ")", + ); + functionLevelNode.children.push(modifiersLevelNode); + // add modifiers + for (let modifierName in funcObj.modifiers) { + let vardec = funcObj.modifiers[modifierName]; + + let symbolAnnotation = getSymbolKindForDeclaration(vardec); + + modifiersLevelNode.children.push( + astNodeAsDocumentSymbol( + document, + vardec, + symbolAnnotation.symbol, + symbolAnnotation.prefix + + symbolAnnotation.name + + symbolAnnotation.suffix, + symbolAnnotation.details, + ), + ); + } + } + + // add fake assembly functions list to outline + let numAssemblyFuncDefs = Object.keys( + funcObj.assemblyFunctions, + ).length; + if (numAssemblyFuncDefs !== 0) { + let assemblyLevelNode = astNodeAsDocumentSymbol( + document, + getFakeNode("assembly..", 1), + vscode.SymbolKind.Namespace, + "assembly", + "... (" + numAssemblyFuncDefs + ")", + ); + + functionLevelNode.children.push(assemblyLevelNode); + // add modifiers + for (let modifierName in funcObj.assemblyFunctions) { + let vardec = funcObj.assemblyFunctions[modifierName]; + + let symbolAnnotation = getSymbolKindForDeclaration(vardec); + + assemblyLevelNode.children.push( + astNodeAsDocumentSymbol( + document, + vardec, + symbolAnnotation.symbol, + symbolAnnotation.prefix + + symbolAnnotation.name + + symbolAnnotation.suffix, + symbolAnnotation.details, + ), + ); } + } + //get all declarations in function + + for (let declaration in funcObj.declarations) { + let vardec = funcObj.declarations[declaration]; + if (declaration == "null") continue; + + let symbolAnnotation = getSymbolKindForDeclaration(vardec); + + functionLevelNode.children.push( + astNodeAsDocumentSymbol( + document, + vardec, + symbolAnnotation.symbol, + symbolAnnotation.prefix + + symbolAnnotation.name + + symbolAnnotation.suffix, + symbolAnnotation.details, + ), + ); + } } - if(varDecIsArray(astnode)){ - result.name += "[]"; + console.log("✓ functions"); + + /** modifiers */ + for (let functionName in insights.contracts[contractName] + .modifiers) { + let symbolAnnotation = getSymbolKindForDeclaration( + insights.contracts[contractName].modifiers[functionName], + ); + functionLevelNode = astNodeAsDocumentSymbol( + document, + insights.contracts[contractName].modifiers[functionName]._node, + symbolAnnotation.symbol, + symbolAnnotation.prefix + + symbolAnnotation.name + + symbolAnnotation.suffix, + symbolAnnotation.details, + ); + + topLevelNode.children.push(functionLevelNode); + //get all declarations in function + for (let declaration in insights.contracts[contractName] + .modifiers[functionName].declarations) { + let vardec = + insights.contracts[contractName].modifiers[functionName] + .declarations[declaration]; + if (declaration == "null") continue; + let symbolAnnotation = getSymbolKindForDeclaration(vardec); + functionLevelNode.children.push( + astNodeAsDocumentSymbol( + document, + vardec, + symbolAnnotation.symbol, + symbolAnnotation.prefix + + symbolAnnotation.name + + symbolAnnotation.suffix, + symbolAnnotation.details, + ), + ); + } } - result.symbol = vscode.SymbolKind.TypeParameter; // lets misuse this kind for params - break; - case "ContractDefinition": - if(astnode.kind=="interface"){ - result.symbol = vscode.SymbolKind.Interface; - } else if(astnode.kind=="library"){ - result.symbol = vscode.SymbolKind.Class; - result.prefix += "📚"; - } else { - result.symbol = vscode.SymbolKind.Class; + console.log("✓ modifiers"); + /** events */ + for (let eventObj of insights.contracts[contractName].events) { + let symbolAnnotation = getSymbolKindForDeclaration(eventObj); + functionLevelNode = astNodeAsDocumentSymbol( + document, + eventObj._node, + symbolAnnotation.symbol, + symbolAnnotation.prefix + + symbolAnnotation.name + + symbolAnnotation.suffix, + symbolAnnotation.details, + ); + + topLevelNode.children.push(functionLevelNode); + + //get all declarations in function + for (let declaration in eventObj.declarations) { + let vardec = eventObj.declarations[declaration]; + if (declaration == "null") continue; + let symbolAnnotation = getSymbolKindForDeclaration(vardec); + functionLevelNode.children.push( + astNodeAsDocumentSymbol( + document, + vardec, + symbolAnnotation.symbol, + symbolAnnotation.prefix + + symbolAnnotation.name + + symbolAnnotation.suffix, + symbolAnnotation.details, + ), + ); + } } - break; - case "AssemblyFunctionDefinition": - result.symbol = vscode.SymbolKind.Function; - break; - default: - console.error("<-----"); - } - if(result.prefix){ - result.prefix = result.prefix + " "; //add space - } - return result; -} - -function getAstValueForExpression(astnode){ - - switch(astnode.type) { - case "NumberLiteral": - return `${astnode.number}${astnode.subdenominator ? astnode.subdenominator : ''}`; - case "BooleanLiteral": - return astnode.value ? "true":"false"; - case "StringLiteral": - case "HexLiteral": - case "HexNumber": - case "DecimalNumber": - return astnode.value; - default: - return ""; - } -} + console.log("✓ events"); + /** functions - may include constructor / fallback */ + if (settings.extensionConfig().outline.inheritance.show) { + var inheritedLevelNode = astNodeAsDocumentSymbol( + document, + getFakeNode("↖ ...", 1), + vscode.SymbolKind.Namespace, + ); + topLevelNode.children.push(inheritedLevelNode); + let contractCache = {}; + let contractNodes = {}; + for (var name in insights.contracts[contractName] + .inherited_names) { + //skip self + let inheritedFromContract = + insights.contracts[contractName].inherited_names[name]; + let inheritedFromContractName = inheritedFromContract.name; + if (inheritedFromContractName == contractName) continue; + //skip functions, modifiers, events of local contract + if ( + typeof insights.contracts[contractName].names[name] != + "undefined" + ) + continue; -class SolidityDocumentSymbolProvider{ + let _contract = contractCache[inheritedFromContractName]; - constructor(g_workspace, cb_analyze){ - this.g_workspace = g_workspace; - this.cb_analyze = cb_analyze; - } - - provideDocumentSymbols(document, token){ - console.log("preparing symbols..."); + if (!_contract) { + let _contract = this.g_workspace.findContractsByNameSync( + inheritedFromContractName, + ); + if (_contract.length == 0) { + console.warn( + `symbol/inheritance: contract ${inheritedFromContractName} not found :/. skipping.`, + ); + continue; + } + _contract = _contract.pop(); //pop one item. ignore multiple results + contractCache[inheritedFromContractName] = _contract; + } - return new Promise((resolve, reject) => { - var symbols = []; + let symbolAnnotation; + if (typeof _contract == "undefined") { + //contract not found :/ + symbolAnnotation = { + symbol: vscode.SymbolKind.Class, + name: inheritedFromContractName, + prefix: "", + suffix: "", + details: "", + }; + } else { + symbolAnnotation = getSymbolKindForDeclaration(_contract); + } - console.log("force ast refresh..!"); //fixme! - this.cb_analyze(token, document); //remove this hack - - if(token.isCancellationRequested){ - reject(token); - return; - } - //var insights = this.g_workspace.inspect(document.getText(), document.fileName, true, token); - try { - this.g_workspace.add(document.fileName, { content: document.getText() }).then((insights)=>{ - console.log(`✓ inspect ${insights.filePath}`); - - console.log("--- preparing symbols for: "+ document.fileName); - - if(token.isCancellationRequested){ - reject(token); - return; - } - - var topLevelNode; - - if(settings.extensionConfig().outline.pragmas.show){ - topLevelNode = astNodeAsDocumentSymbol( - document, - getFakeNode("pragma",1), - vscode.SymbolKind.Namespace, - "pragma", - "... (" + insights.pragmas.length + ")" - ); - symbols.push(topLevelNode); - insights.pragmas.forEach(function(item){ - topLevelNode.children.push(astNodeAsDocumentSymbol( - document, - item, - vscode.SymbolKind.Namespace, - item.name + " → " + item.value)); - }); - console.log("✓ pragmas "); - } - - if(settings.extensionConfig().outline.imports.show){ - topLevelNode = astNodeAsDocumentSymbol( - document, - getFakeNode("imports",1), - vscode.SymbolKind.Namespace, - "imports", - "... (" + insights.imports.length + ")" - ); - symbols.push(topLevelNode); - insights.imports.forEach(function(item){ - topLevelNode.children.push(astNodeAsDocumentSymbol( - document, - item, - vscode.SymbolKind.File, - item.path)); - }); - - console.log("✓ imports "); - } - - for (var contractName in insights.contracts) { - - let symbolAnnotation = getSymbolKindForDeclaration(insights.contracts[contractName]); - topLevelNode = astNodeAsDocumentSymbol( - document, - insights.contracts[contractName]._node, - symbolAnnotation.symbol, - symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix - ); - symbols.push(topLevelNode); - - /** the document */ - console.log("✓ contracts " + contractName); - /** constructor - if known */ - if (insights.contracts[contractName].constructor){ - topLevelNode.children.push(astNodeAsDocumentSymbol(document, insights.contracts[contractName].constructor._node, vscode.SymbolKind.Constructor)); - } - console.log("✓ constructor"); - /** stateVars */ - for (var svar in insights.contracts[contractName].stateVars){ - let symbolAnnotation = getSymbolKindForDeclaration(insights.contracts[contractName].stateVars[svar]); - - topLevelNode.children.push(astNodeAsDocumentSymbol( - document, - insights.contracts[contractName].stateVars[svar], - symbolAnnotation.symbol, - symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details)); - - } - console.log("✓ statevars"); - - for (let name in insights.contracts[contractName].enums){ - topLevelNode.children.push(astNodeAsDocumentSymbol( - document, - insights.contracts[contractName].enums[name], - vscode.SymbolKind.Enum)); - } - console.log("✓ enums"); - for (let name in insights.contracts[contractName].structs){ - topLevelNode.children.push(astNodeAsDocumentSymbol(document, insights.contracts[contractName].structs[name], vscode.SymbolKind.Struct)); - } - console.log("✓ structs"); - var functionLevelNode; - /** functions - may include constructor / fallback */ - for (let funcObj of insights.contracts[contractName].functions){ - - - let symbolAnnotation = getSymbolKindForDeclaration(funcObj); - functionLevelNode = astNodeAsDocumentSymbol( - document, - funcObj._node, - symbolAnnotation.symbol, - symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details); - - topLevelNode.children.push(functionLevelNode); - // add a fake modifiers list to outline - // add pseudonode modifiers - let numModifiers = Object.keys(funcObj.modifiers).length; - if(numModifiers!==0){ - let modifiersLevelNode = astNodeAsDocumentSymbol( - document, - getFakeNode("modifiers",1), - vscode.SymbolKind.Namespace, - "modifiers", - "... (" + numModifiers + ")" - ); - functionLevelNode.children.push(modifiersLevelNode); - // add modifiers - for (let modifierName in funcObj.modifiers){ - let vardec = funcObj.modifiers[modifierName]; - - let symbolAnnotation = getSymbolKindForDeclaration(vardec); - - modifiersLevelNode.children.push(astNodeAsDocumentSymbol( - document, - vardec, - symbolAnnotation.symbol, - symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details - )); - } - } - - // add fake assembly functions list to outline - let numAssemblyFuncDefs = Object.keys(funcObj.assemblyFunctions).length; - if(numAssemblyFuncDefs!==0){ - let assemblyLevelNode = astNodeAsDocumentSymbol( - document, - getFakeNode("assembly..",1), - vscode.SymbolKind.Namespace, - "assembly", - "... (" + numAssemblyFuncDefs + ")" - ); - - functionLevelNode.children.push(assemblyLevelNode); - // add modifiers - for (let modifierName in funcObj.assemblyFunctions){ - let vardec = funcObj.assemblyFunctions[modifierName]; - - let symbolAnnotation = getSymbolKindForDeclaration(vardec); - - assemblyLevelNode.children.push(astNodeAsDocumentSymbol( - document, - vardec, - symbolAnnotation.symbol, - symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details - )); - } - } - //get all declarations in function - - - for (let declaration in funcObj.declarations){ - let vardec = funcObj.declarations[declaration]; - if(declaration=="null") - continue; - - let symbolAnnotation = getSymbolKindForDeclaration(vardec); - - functionLevelNode.children.push(astNodeAsDocumentSymbol( - document, - vardec, - symbolAnnotation.symbol, - symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details - )); - } - - } - console.log("✓ functions"); - - /** modifiers */ - for (let functionName in insights.contracts[contractName].modifiers){ - - let symbolAnnotation = getSymbolKindForDeclaration(insights.contracts[contractName].modifiers[functionName]); - functionLevelNode = astNodeAsDocumentSymbol( - document, - insights.contracts[contractName].modifiers[functionName]._node, - symbolAnnotation.symbol, - symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details); - - topLevelNode.children.push(functionLevelNode); - //get all declarations in function - for (let declaration in insights.contracts[contractName].modifiers[functionName].declarations){ - let vardec = insights.contracts[contractName].modifiers[functionName].declarations[declaration]; - if(declaration=="null") - continue; - let symbolAnnotation = getSymbolKindForDeclaration(vardec); - functionLevelNode.children.push(astNodeAsDocumentSymbol( - document, - vardec, - symbolAnnotation.symbol, - symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details - )); - - } - } - console.log("✓ modifiers"); - /** events */ - for (let eventObj of insights.contracts[contractName].events){ - - let symbolAnnotation = getSymbolKindForDeclaration(eventObj); - functionLevelNode = astNodeAsDocumentSymbol( - document, - eventObj._node, - symbolAnnotation.symbol, - symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details); - - topLevelNode.children.push(functionLevelNode); - - //get all declarations in function - for (let declaration in eventObj.declarations){ - let vardec = eventObj.declarations[declaration]; - if(declaration=="null") - continue; - let symbolAnnotation = getSymbolKindForDeclaration(vardec); - functionLevelNode.children.push(astNodeAsDocumentSymbol( - document, - vardec, - symbolAnnotation.symbol, - symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details - )); - } - } - console.log("✓ events"); - /** functions - may include constructor / fallback */ - if(settings.extensionConfig().outline.inheritance.show){ - - var inheritedLevelNode = astNodeAsDocumentSymbol( - document, - getFakeNode("↖ ...", 1), - vscode.SymbolKind.Namespace, - ); - topLevelNode.children.push(inheritedLevelNode); - - let contractCache = {}; - let contractNodes = {}; - for (var name in insights.contracts[contractName].inherited_names){ - //skip self - let inheritedFromContract = insights.contracts[contractName].inherited_names[name]; - let inheritedFromContractName = inheritedFromContract.name; - if(inheritedFromContractName==contractName) - continue; - //skip functions, modifiers, events of local contract - if(typeof insights.contracts[contractName].names[name]!="undefined") - continue; - - let _contract = contractCache[inheritedFromContractName]; - - if(!_contract){ - let _contract = this.g_workspace.findContractsByNameSync(inheritedFromContractName); - if(_contract.length==0){ - console.warn(`symbol/inheritance: contract ${inheritedFromContractName} not found :/. skipping.`) - continue; - } - _contract = _contract.pop(); //pop one item. ignore multiple results - contractCache[inheritedFromContractName] = _contract; - } - - - let symbolAnnotation; - if(typeof _contract=="undefined"){ - //contract not found :/ - symbolAnnotation = { - symbol:vscode.SymbolKind.Class, - name:inheritedFromContractName, - prefix:"", - suffix:"", - details:"", - }; - } else { - symbolAnnotation = getSymbolKindForDeclaration(_contract); - } - - let currentContractNode = contractNodes[inheritedFromContractName]; - if(typeof currentContractNode=="undefined"){ - currentContractNode = astNodeAsDocumentSymbol( - document, - getFakeNode(inheritedFromContractName, 1), - symbolAnnotation.symbol, - " ↖ "+ symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details); - contractNodes[inheritedFromContractName] = currentContractNode; - inheritedLevelNode.children.push(currentContractNode); - - } - // get the item to calculate range/location - let varSymbol; - try { - varSymbol = getSymbolKindForDeclaration(_contract.names[name]); - } catch(e){ - varSymbol = { - symbol:vscode.SymbolKind.Variable, - name:name, - prefix:"", - suffix:"", - details:"", - }; - } - let inheritanceNode = astNodeAsDocumentSymbol( - document, - getFakeNode(varSymbol.name, 1), - varSymbol.symbol, - " ↖ "+ varSymbol.prefix + varSymbol.name + varSymbol.suffix, - varSymbol.details); - currentContractNode.children.push(inheritanceNode); - } - - } - console.log("✓ inheritance"); - } - if(token.isCancellationRequested){ - reject(token); - return; - } - console.log("✓✓✓ done preparing symbols for: "+ document.fileName); - resolve(symbols); - - }).catch(e => { - console.warn(`Error adding file or one of its dependencies to workspace (parser error): ${document.fileName}`); - if(settings.extensionConfig().debug.parser.showExceptions){ - console.error(e); - } - }); - } catch (e){ - console.warn(`Error adding file or one of its dependencies to workspace (parser error): ${document.fileName}`); - if(settings.extensionConfig().debug.parser.showExceptions){ - console.error(e); + let currentContractNode = + contractNodes[inheritedFromContractName]; + if (typeof currentContractNode == "undefined") { + currentContractNode = astNodeAsDocumentSymbol( + document, + getFakeNode(inheritedFromContractName, 1), + symbolAnnotation.symbol, + " ↖ " + + symbolAnnotation.prefix + + symbolAnnotation.name + + symbolAnnotation.suffix, + symbolAnnotation.details, + ); + contractNodes[inheritedFromContractName] = + currentContractNode; + inheritedLevelNode.children.push(currentContractNode); + } + // get the item to calculate range/location + let varSymbol; + try { + varSymbol = getSymbolKindForDeclaration( + _contract.names[name], + ); + } catch (e) { + varSymbol = { + symbol: vscode.SymbolKind.Variable, + name: name, + prefix: "", + suffix: "", + details: "", + }; } + let inheritanceNode = astNodeAsDocumentSymbol( + document, + getFakeNode(varSymbol.name, 1), + varSymbol.symbol, + " ↖ " + + varSymbol.prefix + + varSymbol.name + + varSymbol.suffix, + varSymbol.details, + ); + currentContractNode.children.push(inheritanceNode); + } } - + console.log("✓ inheritance"); + } + if (token.isCancellationRequested) { + return reject(token); + } + console.log("✓✓✓ done preparing symbols for: " + document.fileName); + return resolve(symbols); + }) + .catch((e) => { + console.warn( + `Error adding file or one of its dependencies to workspace (parser error): ${document.fileName}`, + ); + if (settings.extensionConfig().debug.parser.showExceptions) { + console.error(e); + } + return reject(e); }); - - } + }); + } } - module.exports = { - SolidityDocumentSymbolProvider:SolidityDocumentSymbolProvider, - getVariableDeclarationType:getVariableDeclarationType, - getAstValueForExpression:getAstValueForExpression -}; \ No newline at end of file + SolidityDocumentSymbolProvider: SolidityDocumentSymbolProvider, + getVariableDeclarationType: getVariableDeclarationType, + getAstValueForExpression: getAstValueForExpression, +}; diff --git a/src/features/templates.js b/src/features/templates.js index 29e7b76..fb50ea4 100644 --- a/src/features/templates.js +++ b/src/features/templates.js @@ -1,31 +1,33 @@ -'use strict'; -/** +"use strict"; +/** * @author github.com/tintinweb * @license GPLv3 - * - * + * + * * */ -const vscode = require('vscode'); - -function generateUnittestStubForContract(document, g_workspace, contractName){ - let contract = { - name: contractName, - path: document.uri.fsPath - }; +const vscode = require("vscode"); + +function generateUnittestStubForContract(document, g_workspace, contractName) { + let contract = { + name: contractName, + path: document.uri.fsPath, + }; + + if (!contractName) { + //take first + let sourceUnit = g_workspace.get(document.uri.fsPath); + if (!sourceUnit || Object.keys(sourceUnit.contracts).length <= 0) { + vscode.window.showErrorMessage( + `[Solidity VA] unable to create unittest stub for current contract. missing analysis for source-unit: ${document.uri.fsPath}`, + ); + return; + } - if(!contractName){ - //take first - let sourceUnit = g_workspace.get(document.uri.fsPath); - if(!sourceUnit || Object.keys(sourceUnit.contracts).length<=0){ - vscode.window.showErrorMessage(`[Solidity VA] unable to create unittest stub for current contract. missing analysis for source-unit: ${document.uri.fsPath}`); - return; - } + contract.name = Object.keys(sourceUnit.contracts)[0]; + } - contract.name = Object.keys(sourceUnit.contracts)[0]; - } - - let content = ` + let content = ` /** * * autogenerated by solidity-visual-auditor @@ -91,28 +93,33 @@ contract('${contract.name}', (accounts) => { }) }); `; - return content; + return content; } +function generateHardhatUnittestStubForContract( + document, + g_parser, + contractName, +) { + let contract = { + name: contractName, + path: document.uri.fsPath, + }; + + if (!contractName) { + //take first + let sourceUnit = g_parser.sourceUnits[document.uri.fsPath]; + if (!sourceUnit || Object.keys(sourceUnit.contracts).length <= 0) { + vscode.window.showErrorMessage( + `[Solidity VA] unable to create hardhat-unittest stub for current contract. missing analysis for source-unit: ${document.uri.fsPath}`, + ); + return; + } -function generateHardhatUnittestStubForContract(document, g_parser, contractName){ - let contract = { - name: contractName, - path: document.uri.fsPath - }; - - if(!contractName){ - //take first - let sourceUnit = g_parser.sourceUnits[document.uri.fsPath]; - if(!sourceUnit || Object.keys(sourceUnit.contracts).length<=0){ - vscode.window.showErrorMessage(`[Solidity VA] unable to create hardhat-unittest stub for current contract. missing analysis for source-unit: ${document.uri.fsPath}`); - return; - } + contract.name = Object.keys(sourceUnit.contracts)[0]; + } - contract.name = Object.keys(sourceUnit.contracts)[0]; - } - - let content = ` + let content = ` /** * * autogenerated by solidity-visual-auditor @@ -203,16 +210,11 @@ describe('${contract.name}', () => { }) }); `; - return content; + return content; } module.exports = { - generateUnittestStubForContract:generateUnittestStubForContract, - generateHardhatUnittestStubForContract:generateHardhatUnittestStubForContract + generateUnittestStubForContract: generateUnittestStubForContract, + generateHardhatUnittestStubForContract: + generateHardhatUnittestStubForContract, }; - - - - - - \ No newline at end of file diff --git a/src/features/utils.js b/src/features/utils.js index 0cec7d1..6cc73ce 100644 --- a/src/features/utils.js +++ b/src/features/utils.js @@ -1,131 +1,69 @@ -'use strict'; -/** +"use strict"; +/** * @author github.com/tintinweb * @license GPLv3 - * - * + * + * * */ -const commentRegex = () => new RegExp(`(?:${commentRegex.line().source})|(?:${commentRegex.block().source})`, 'gm'); +const commentRegex = () => + new RegExp( + `(?:${commentRegex.line().source})|(?:${commentRegex.block().source})`, + "gm", + ); commentRegex.line = () => /(?:^|\s)\/\/(.+?)$/gm; commentRegex.block = () => /\/\*([\S\s]*?)\*\//gm; -class CommentMapperRex{ - - constructor(input) { - this.commentIdxs = []; - this.input = input; - this.regex = commentRegex(); - } - - isRangeOffsetInComment(start, end) { - if(typeof this.input!=="undefined" && this.input!==null){ - this.getComments(this.input); - this.input = null; //free space - } - for (var i = 0; i < this.commentIdxs.length; i += 1) { - let item = this.commentIdxs[i]; - - if(start>=item[0] && end<=item[1]){ - return true; - } - } - return false; - } - - getComments(input) { - var match; - do { - match=this.regex.exec(input); - if(match){ - this.commentIdxs.push([match.index, match.index+match[0].length]); - } - - } while(match); - } - -} - - - -const createKeccakHash = require('keccak'); - -// https://github.com/ethereum/eth-abi/blob/b02fc85b01a9674add88483b0d6144029c09e0a0/eth_abi/grammar.py#L402-L408 -const TYPE_ALIASES = { - 'int': 'int256', - 'uint': 'uint256', - 'fixed': 'fixed128x18', - 'ufixed': 'ufixed128x18', - 'function': 'bytes24', -}; -const evmTypeRegex = new RegExp(`(?(${Object.keys(TYPE_ALIASES).join('|')}))(?(\\[[^\\]]*\\])?)$`, 'g'); - -function canonicalizeEvmType(evmArg) { - function replacer(...groups) { - const foundings = groups.pop(); - return `${TYPE_ALIASES[foundings.type]}${foundings.tail}`; +class CommentMapperRex { + constructor(input) { + this.commentIdxs = []; + this.input = input; + this.regex = commentRegex(); + } + + isRangeOffsetInComment(start, end) { + if (typeof this.input !== "undefined" && this.input !== null) { + this.getComments(this.input); + this.input = null; //free space } - return evmArg.replace(evmTypeRegex, replacer); -} + for (var i = 0; i < this.commentIdxs.length; i += 1) { + let item = this.commentIdxs[i]; -function functionSignatureExtractor(content) { - const funcSigRegex = /function\s+(?[^\(\s]+)\s?\((?[^\)]*)\)/g; - let match; - let sighashes = {}; - let collisions = []; - // cleanup newlines, cleanup comment blocks - while (match = funcSigRegex.exec(content)) { - let args = match.groups.args.replace(commentRegex(), "").split(",").map(item => canonicalizeEvmType(item.trim().split(" ")[0])); - let fnsig = `${match.groups.name.trim()}(${args.join(',')})`; - let sighash = createKeccakHash('keccak256').update(fnsig).digest('hex').toString('hex').slice(0, 8); - - if(sighash in sighashes && sighashes[sighash]!==fnsig){ - collisions.push(sighash); - } - sighashes[sighash] = fnsig; + if (start >= item[0] && end <= item[1]) { + return true; + } } - return {sighashes:sighashes, collisions:collisions}; + return false; + } + + getComments(input) { + var match; + do { + match = this.regex.exec(input); + if (match) { + this.commentIdxs.push([match.index, match.index + match[0].length]); + } + } while (match); + } } -function getCanonicalizedArgumentFromAstNode(node){ - let arraySuffix = ''; - if (typeof node.typeName != "undefined" && node.typeName != null){ - if (node.typeName.type=="ArrayTypeName") { - //is array - node = node.typeName.baseTypeName ; - arraySuffix = "[]"; - } else { - node = node.typeName; - } - } - - if(node.type=="ElementaryTypeName"){ - return node.name + arraySuffix; - } else if (node.type=="UserDefinedTypeName"){ - // TODO: assumes address which is not correct. this might as well unwind to an elementary type but that needs more effort to resolve. - return "address" + arraySuffix; //assume address instead of resolving node.namePath - } else { - return null; - } -} - -function functionSignatureFromAstNode(item){ - - let funcname = item._node.name; - - let argsItem = item._node.parameters.type === "ParameterList" ? item._node.parameters.parameters : item._node.parameters; - let args = argsItem.map(o => canonicalizeEvmType(getCanonicalizedArgumentFromAstNode(o))); - - let fnsig = `${funcname}(${args.join(',')})`; - let sighash = createKeccakHash('keccak256').update(fnsig).digest('hex').toString('hex').slice(0, 8); - - let result = {}; - result[sighash] = fnsig; - return result; +function functionSignatureForASTItem(item) { + switch (item._node?.type) { + case "FunctionDefinition": + const res = item.getFunctionSignature(); //call getFunctionSignature from Workspace on function node + return [res]; + case "ContractDefinition": + return Object.values(item.functions) + .filter( + (fn) => fn.name && ["external", "public"].includes(fn.visibility), + ) + .map((fn) => fn.getFunctionSignature()); + default: + throw new Error("Unsupported node type"); + } } module.exports = { - CommentMapperRex : CommentMapperRex, - functionSignatureExtractor : functionSignatureExtractor, - functionSignatureFromAstNode : functionSignatureFromAstNode -}; \ No newline at end of file + CommentMapperRex: CommentMapperRex, + functionSignatureForASTItem: functionSignatureForASTItem, +}; diff --git a/src/features/whatsnew/interactiveWebview.js b/src/features/whatsnew/interactiveWebview.js index 9a55e01..92240b5 100644 --- a/src/features/whatsnew/interactiveWebview.js +++ b/src/features/whatsnew/interactiveWebview.js @@ -1,201 +1,239 @@ -'use strict'; -/** +"use strict"; +/** * @author github.com/tintinweb * @license GPLv3 - * -* */ - + * + * */ /** imports */ const vscode = require("vscode"); -const path = require("path"); +const path = require("path"); const fs = require("fs"); /** global vars */ - /** classdecs */ class InteractiveWebviewGenerator { - - constructor(context, content_folder) { - this.context = context; - this.webviewPanels = new Map(); - this.timeout = null; - this.content_folder = content_folder; - } - - setNeedsRebuild(uri, needsRebuild) { - let panel = this.webviewPanels.get(uri); - - if (panel) { - panel.setNeedsRebuild(needsRebuild); - this.rebuild(); - } - } - - getPanel(uri){ - return this.webviewPanels.get(uri); - } - - dispose() { - } - - rebuild() { - this.webviewPanels.forEach(panel => { - if(panel.getNeedsRebuild() && panel.getPanel().visible) { - this.updateContent(panel, vscode.workspace.textDocuments.find(doc => doc.uri == panel.uri)); - } - }); - } - - async revealOrCreatePreview(displayColumn, doc) { - let that = this; - return new Promise(function(resolve, reject) { - let previewPanel = that.webviewPanels.get(doc.uri); - - if (previewPanel) { - previewPanel.reveal(displayColumn); - } - else { - previewPanel = that.createPreviewPanel(doc, displayColumn); - that.webviewPanels.set(doc.uri, previewPanel); - // when the user closes the tab, remove the panel - previewPanel.getPanel().onDidDispose(() => that.webviewPanels.delete(doc.uri), undefined, that.context.subscriptions); - // when the pane becomes visible again, refresh it - previewPanel.getPanel().onDidChangeViewState(_ => that.rebuild()); - - previewPanel.getPanel().webview.onDidReceiveMessage(e => that.handleMessage(previewPanel, e), undefined, that.context.subscriptions); - } - - that.updateContent(previewPanel, doc) - .then(previewPanel => { - resolve(previewPanel); - }); - }); - } - - handleMessage(previewPanel, message) { - console.log(`Message received from the webview: ${message.command}`); - - switch(message.command){ - case 'onRenderFinished': - previewPanel.onRenderFinished(message); - break; - case 'onPageLoaded': - previewPanel.onPageLoaded(message); - break; - case 'onClick': - previewPanel.onClick(message); - break; - case 'onDblClick': - console.log("dblclick --> navigate to code location"); - break; - default: - previewPanel.handleMessage(message); - //forward unhandled messages to previewpanel - } - } - - createPreviewPanel(doc, displayColumn ) { - let previewTitle = `Welcome: Solidity Auditor`; - - let webViewPanel = vscode.window.createWebviewPanel('whatsNew', previewTitle, displayColumn, { - enableFindWidget: false, - enableScripts: true, - retainContextWhenHidden: true, - localResourceRoots: [vscode.Uri.file(path.join(this.context.extensionPath, this.content_folder))] - }); - - webViewPanel.iconPath = vscode.Uri.file(this.context.asAbsolutePath(path.join(this.content_folder, "icon.png"))); - - return new PreviewPanel(this, doc.uri, webViewPanel); - } - - async updateContent(previewPanel, doc) { - return new Promise(async (resolve, reject) => { - if(!previewPanel.getPanel().webview.html) { - previewPanel.getPanel().webview.html = "Please wait..."; - } - previewPanel.setNeedsRebuild(false); - previewPanel.getPanel().webview.html = await this.getPreviewHtml(previewPanel, doc); - return resolve(previewPanel); - }); - } - - async getPreviewTemplate(context, templateName){ - let previewPath = context.asAbsolutePath(path.join(this.content_folder, templateName)); - - return new Promise((resolve, reject) => { - fs.readFile(previewPath, "utf8", function (err, data) { - if (err) reject(err); - else resolve(data); - }); - }); - } - - async getPreviewHtml(previewPanel, doc){ - let templateHtml = await this.getPreviewTemplate(this.context, "index.html"); - - templateHtml = templateHtml.replace(/ - + - - -
- - \ No newline at end of file + + +
+ +