From c87f6ecc59054fa66597e3fdf6261de745a372c5 Mon Sep 17 00:00:00 2001 From: Valentin Date: Thu, 26 Jan 2023 11:53:47 +0100 Subject: [PATCH 01/32] Compute function signatures using AST and add a debounce before re-parsing source --- src/extension.js | 1659 ++++++++++++++++++++++---------------- src/features/codelens.js | 386 +++++---- src/features/commands.js | 1320 +++++++++++++++++------------- src/features/symbols.js | 1250 ++++++++++++++-------------- src/features/utils.js | 239 +++--- 5 files changed, 2728 insertions(+), 2126 deletions(-) diff --git a/src/extension.js b/src/extension.js index 51ae9fe..a483b0e 100644 --- a/src/extension.js +++ b/src/extension.js @@ -1,23 +1,28 @@ '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 { + 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 { + SolidityCodeLensProvider, + SolidityParserLensProvider, +} = require('./features/codelens'); const settings = require('./settings'); const { Cockpit } = require('./features/cockpit.js'); const { SolidityReferenceProvider } = require('./features/references'); @@ -28,553 +33,745 @@ const { WhatsNewHandler } = require('./features/whatsnew/whatsNew'); 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 debounceTimer; 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); + 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]); - } + 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]); + } } - - /*** 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)); - } - }); + 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)); + } + }); + return decorations; } function analyzeSourceUnit(cancellationToken, document, editor) { - console.log("inspect ..."); - - if (!document) { - console.error("-BUG- cannot analyze empty document!"); - return; - } + console.log('inspect ...'); + + if (!document) { + console.error('-BUG- cannot analyze empty document!'); + return; + } + + 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); + } + }); - 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; } - - - 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; + let currentConfig = settings.extensionConfig(); + let shouldDecorate = + currentConfig.deco.statevars || + currentConfig.deco.arguments || + currentConfig.deco.warn.reserved; - if (shouldDecorate && editor) { - var decorations = []; + if (shouldDecorate && editor) { + var decorations = []; - let this_sourceUnit = g_workspace.get(document.fileName); + let this_sourceUnit = g_workspace.get(document.fileName); - console.log("+ (decorate) in sourceunit: " + this_sourceUnit.filePath); + 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"); + 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 ' + subcontract + ); + return; + } + if (subcontract.name == contract.name) { + return; //skip self + } + + if (subcontract._node.kind === 'interface') { + //only consider structs + for (let _var in subcontract.structs) { + contract.inherited_names[_var] = subcontract; + contract.inherited_structs[_var] = subcontract.structs[_var]; } + return; //skip other 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) { + contract.inherited_names[_var] = subcontract; + contract.inherited_structs[_var] = subcontract.structs[_var]; + } + 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 + ) + ); - 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 "); + /*** 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 + ) + ); } - console.log("✓ decorate scope done "); - if (cancellationToken.isCancellationRequested) { - //abort - new analysis running already + + 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 + ) + ); } - - setDecorations(editor, decorations); - console.log("✓ apply decorations - scope"); + 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("✓ analyzeSourceUnit - done"); + } + 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'); + }); } /** 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 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(); - console.log("--- on-did-change"); - try { - analyzeSourceUnit(currentCancellationTokens.onDidChange.token, document, editor); - } catch (err) { - if (typeof err !== "object") { //CancellationToken - throw err; - } +function refresh(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(); + console.log('--- on-did-change'); + try { + analyzeSourceUnit( + currentCancellationTokens.onDidChange.token, + document, + editor + ); + } catch (err) { + if (typeof err !== 'object') { + //CancellationToken + throw err; } + } + console.log('✓✓✓ on-did-change - resolved'); +} - console.log("✓✓✓ on-did-change - resolved"); +function onDidChange(editor) { + clearTimeout(debounceTimer); + // refresh(editor) + debounceTimer = setTimeout(() => refresh(editor), 500); //only re-parse every 500ms } function onActivate(context) { + activeEditor = vscode.window.activeTextEditor; - 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; + 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(activeEditor); + + 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 + ); } - /** 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]); - /* + ) + ); + + 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 +782,288 @@ 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*/) - ) - ); + }); } - - if (settings.extensionConfig().codelens.enable) { - context.subscriptions.push( - vscode.languages.registerCodeLensProvider( - docSel, - new SolidityCodeLensProvider(g_workspace, analyzeSourceUnit) - ) - ); + ) + ); + + context.subscriptions.push( + vscode.commands.registerCommand( + 'solidity-va.tools.flattenCandidates', + function () { + commands.flattenCandidates(); } - - if (settings.extensionConfig().findAllReferences.enable) { - context.subscriptions.push( - vscode.languages.registerReferenceProvider( - docSel, - new SolidityReferenceProvider() - ) + ) + ); + + 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.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) { + refresh(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) + ) + ); + } - /** - * trigger decorations for visible editors - */ - vscode.window.visibleTextEditors.map(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) + ) + ); + + context.subscriptions.push( + vscode.languages.registerCodeLensProvider( + docSel, + new SolidityParserLensProvider(g_workspace) + ) + ); + } + + 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/codelens.js b/src/features/codelens.js index d59c0e5..edd8403 100644 --- a/src/features/codelens.js +++ b/src/features/codelens.js @@ -1,9 +1,9 @@ 'use strict'; -/** +/** * @author github.com/tintinweb * @license GPLv3 - * - * + * + * * */ const vscode = require('vscode'); const settings = require('../settings.js'); @@ -12,39 +12,38 @@ 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 SolidityCodeLensProvider { + constructor(g_workspace, cb_analyze) { + this.g_workspace = g_workspace; + this.cb_analyze = cb_analyze; + 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 +54,206 @@ 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.flatten.enable && codeLens.push( - new vscode.CodeLens( - firstLine, { - command: 'solidity-va.tools.flaterra', - title: 'flatten', - 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.funcSigs.enable && codeLens.push( - new vscode.CodeLens( - firstLine, { - command: 'solidity-va.tools.function.signatures', - title: 'funcSigs', - arguments: [document] - } - ) - ); + config.flatten.enable && + codeLens.push( + new vscode.CodeLens(firstLine, { + command: 'solidity-va.tools.flaterra', + title: 'flatten', + arguments: [document], + }) + ); + return codeLens; + } - 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; - } + async provideCodeLenses(document, token) { + if (this.codeLenses.length == 0) { + this.codeLenses = this.init(document, token); + } + return this.codeLenses; + } +} - config.uml.enable && codeLens.push(new vscode.CodeLens(firstLine, { - command: 'solidity-va.uml.contract.outline', - title: 'uml', - arguments: [document, Object.values(parser.contracts)] +class SolidityParserLensProvider { + 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 + .getSourceUnitByPath(document.fileName) + .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.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)], }) - ); - + ); - 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; - } + }); + } - 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 + SolidityCodeLensProvider: SolidityCodeLensProvider, + SolidityParserLensProvider: SolidityParserLensProvider, }; diff --git a/src/features/commands.js b/src/features/commands.js index 5dcfc83..d9db70b 100644 --- a/src/features/commands.js +++ b/src/features/commands.js @@ -1,9 +1,9 @@ 'use strict'; -/** +/** * @author github.com/tintinweb * @license GPLv3 - * - * + * + * * */ const vscode = require('vscode'); @@ -16,632 +16,832 @@ 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 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 { + files = [ + documentOrListItems.uri.fsPath, + ...Object.keys(this.g_workspace.sourceUnits), + ]; //better only add imported files. need to resolve that somehow + } + } - 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); + }); + } } - vscode.workspace.openTextDocument({content: content, language: "markdown"}) - .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)); - } - - async listFunctionSignatureForAstItem(item, asJson) { - - let sighashes = mod_utils.functionSignatureFromAstNode(item); - - 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"; + ) + .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`; } - - 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)); + vscode.workspace + .openTextDocument({ content: content, language: 'markdown' }) + .then((doc) => + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) + ); + } + + // async listFunctionSignatures(document, asJson) { + // let sighash_colls = mod_utils.functionSignaturesForSourceUnit( + // document. + // ); + // 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); + // } 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: content, language: "markdown" }) + // .then((doc) => + // vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) + // ); + // } + + // async listFunctionSignaturesForWorkspace(asJson) { + // let sighashes = {}; + // let collisions = []; + + // 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 + + // let currSigs = sig_colls.sighashes; + // for (let k in currSigs) { + // sighashes[k] = currSigs[k]; + // } + // } catch (e) {} + // }); + // }); + + // 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"); + // } + // } + // vscode.workspace + // .openTextDocument({ content: content, language: "markdown" }) + // .then((doc) => + // vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) + // ); + // } + + async signatureForAstItem(item) { + let results; + let err; + try { + results = mod_utils.functionSignatureForASTItem(item); + } catch (e) { + console.log(e.message); + err = e.message; } - - 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}`); } - ); - }) - ); + let content; + if (!err) { + const header = + 'Function Name | Sighash | Function Signature | \n ------------ | ------------ | ------------ |\n'; + content = + header + + results + .map((r) => `${r.name} | ${r.sighash} | ${r.signature} |`) + .join('\n'); + } else { + content = 'Failed to compute function signature: ' + err; } -} - + vscode.workspace + .openTextDocument({ content: content, language: 'markdown' }) + .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/symbols.js b/src/features/symbols.js index 9a87839..0f2826c 100644 --- a/src/features/symbols.js +++ b/src/features/symbols.js @@ -1,643 +1,713 @@ '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} - } - }; +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, cb_analyze) { + this.g_workspace = g_workspace; + this.cb_analyze = cb_analyze; + } + + provideDocumentSymbols(document, token) { + console.log('preparing symbols...'); + + return new Promise((resolve, reject) => { + var symbols = []; + + // 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); + this.g_workspace + .getSourceUnitByPath(document.fileName) + .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] + ); - 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) { + 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); + } }); - - } + }); + } } - 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/utils.js b/src/features/utils.js index 0cec7d1..f5e4a80 100644 --- a/src/features/utils.js +++ b/src/features/utils.js @@ -1,131 +1,164 @@ '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; +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]; - getComments(input) { - var match; - do { - match=this.regex.exec(input); - if(match){ - this.commentIdxs.push([match.index, match.index+match[0].length]); - } - - } while(match); + 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', + int: 'int256', + uint: 'uint256', + fixed: 'fixed128x18', + ufixed: 'ufixed128x18', + function: 'bytes24', }; -const evmTypeRegex = new RegExp(`(?(${Object.keys(TYPE_ALIASES).join('|')}))(?(\\[[^\\]]*\\])?)$`, 'g'); +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}`; - } - return evmArg.replace(evmTypeRegex, replacer); + function replacer(...groups) { + const foundings = groups.pop(); + return `${TYPE_ALIASES[foundings.type]}${foundings.tail}`; + } + return evmArg.replace(evmTypeRegex, replacer); } -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; - } - return {sighashes:sighashes, collisions:collisions}; +function getCanonicalizedArgumentFromAstNode( + node, + _parent, + array = false, + isStruct = false +) { + if (!array && !node.typeName) { + console.log(node); + throw new Error('Failed to unpack function argument type'); + } + const argStorageLocation = node.storageLocation; + const argTypeNode = !array ? node.typeName : node; + switch (argTypeNode.type) { + case 'ElementaryTypeName': + return argTypeNode.name; + case 'ArrayTypeName': + const repr = + getCanonicalizedArgumentFromAstNode( + argTypeNode.baseTypeName, + _parent, + true + ) + '[]'; + return repr; + case 'UserDefinedTypeName': + if (!argStorageLocation && !isStruct) { + return 'address'; + } + const contract = _parent.parent; + const sourceUnit = contract._parent; + const struct = + contract.structs[argTypeNode.namePath] || + contract.inherited_structs[argTypeNode.namePath] || + sourceUnit.structs[argTypeNode.namePath]; + if (!struct) { + throw new Error( + `Failed to resolve struct ${node.namePath} in current scope.` + ); + } + const structTypes = struct.members.map((m) => + getCanonicalizedArgumentFromAstNode(m, _parent, false, true) + ); + const structSig = '(' + structTypes.join(',') + ')'; + return structSig; + default: + console.log(argTypeNode); + throw new Error('wrong argument type: ' + argTypeNode.name); + } } -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); +function signatureFromFunctionASTNode(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, item)) + ); + + let fnsig = `${funcname}(${args.join(',')})`; + let sighash = createKeccakHash('keccak256') + .update(fnsig) + .digest('hex') + .toString('hex') + .slice(0, 8); + + return { + name: funcname, + signature: fnsig, + sighash: sighash, + }; +} - let result = {}; - result[sighash] = fnsig; - return result; +function functionSignatureForASTItem(item) { + switch (item._node?.type) { + case 'FunctionDefinition': + const res = signatureFromFunctionASTNode(item); + return [res]; + case 'ContractDefinition': + return Object.values(item.functions) + .filter((fn) => ['external', 'public'].includes(fn.visibility)) + .map((fn) => signatureFromFunctionASTNode(fn)); + 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, +}; From 46170afd750eed9a351fba00cabf95d34d9d9297 Mon Sep 17 00:00:00 2001 From: Valentin Date: Wed, 1 Feb 2023 17:29:36 +0100 Subject: [PATCH 02/32] Move funcSig to solidity workspace, optimize codeLens, symbol provider, parsing refresh logic --- package-lock.json | 294 +++------------------------------------ package.json | 2 +- src/extension.js | 74 ++-------- src/features/codelens.js | 3 +- src/features/symbols.js | 24 ++-- src/features/utils.js | 101 +------------- 6 files changed, 37 insertions(+), 461 deletions(-) diff --git a/package-lock.json b/package-lock.json index 812774a..2249162 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,13 +10,26 @@ "dependencies": { "c3-linearization": "^0.3.0", "keccak": "^3.0.2", - "solidity-workspace": "^0.1.7", + "solidity-workspace": "file:../solidity-workspace", "surya": "^0.4.6" }, "engines": { "vscode": "^1.26.2" } }, + "../solidity-workspace": { + "version": "0.1.8", + "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", "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.3.tgz", @@ -25,28 +38,6 @@ "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", @@ -65,19 +56,6 @@ "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", @@ -86,22 +64,6 @@ "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", @@ -133,11 +95,6 @@ "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", @@ -146,14 +103,6 @@ "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", @@ -182,14 +131,6 @@ "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", @@ -225,14 +166,6 @@ "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", @@ -543,18 +476,8 @@ "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" - } + "resolved": "../solidity-workspace", + "link": true }, "node_modules/string_decoder": { "version": "1.3.0", @@ -564,30 +487,6 @@ "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", @@ -791,59 +690,10 @@ "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.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", - "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", - "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.0.0" - }, - "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": { @@ -855,19 +705,6 @@ "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", "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", @@ -883,34 +720,11 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==" }, - "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", @@ -933,11 +747,6 @@ "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", @@ -946,11 +755,6 @@ "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", @@ -973,11 +777,6 @@ "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", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -1004,11 +803,6 @@ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" }, - "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", @@ -1229,9 +1023,7 @@ "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==", + "version": "file:../solidity-workspace", "requires": { "@solidity-parser/parser": "^0.14.3", "c3-linearization": "^0.3.0", @@ -1247,24 +1039,6 @@ "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", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -1430,44 +1204,10 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==" }, - "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", "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==" - }, - "yargs": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", - "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", - "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.0.0" - } - }, - "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 534e548..2d6bb78 100644 --- a/package.json +++ b/package.json @@ -541,7 +541,7 @@ "dependencies": { "c3-linearization": "^0.3.0", "keccak": "^3.0.2", - "solidity-workspace": "^0.1.7", + "solidity-workspace": "file:../solidity-workspace", "surya": "^0.4.6" } } diff --git a/src/extension.js b/src/extension.js index a483b0e..d9cf245 100644 --- a/src/extension.js +++ b/src/extension.js @@ -113,7 +113,7 @@ function checkReservedIdentifiers(identifiers) { return decorations; } -function analyzeSourceUnit(cancellationToken, document, editor) { +function analyzeSourceUnit(cancellationToken, document, editor, initialLoad=false) { console.log('inspect ...'); if (!document) { @@ -135,7 +135,7 @@ function analyzeSourceUnit(cancellationToken, document, editor) { } }); - g_workspace.withParserReady().then((finished) => { + g_workspace.withParserReady(document.fileName, initialLoad).then((finished) => { console.log('✓ workspace ready (linearized, resolved deps, ..)'); if ( cancellationToken.isCancellationRequested || @@ -171,64 +171,6 @@ function analyzeSourceUnit(cancellationToken, document, editor) { 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 ' + subcontract - ); - return; - } - if (subcontract.name == contract.name) { - return; //skip self - } - - if (subcontract._node.kind === 'interface') { - //only consider structs - for (let _var in subcontract.structs) { - contract.inherited_names[_var] = subcontract; - contract.inherited_structs[_var] = subcontract.structs[_var]; - } - return; //skip other 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) { - contract.inherited_names[_var] = subcontract; - contract.inherited_structs[_var] = subcontract.structs[_var]; - } - 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) { @@ -547,7 +489,7 @@ function onDidSave(document) { } } -function refresh(editor) { +function refresh(editor, initialLoad=false) { let document = editor && editor.document ? editor.document @@ -569,7 +511,8 @@ function refresh(editor) { analyzeSourceUnit( currentCancellationTokens.onDidChange.token, document, - editor + editor, + initialLoad ); } catch (err) { if (typeof err !== 'object') { @@ -582,7 +525,6 @@ function refresh(editor) { function onDidChange(editor) { clearTimeout(debounceTimer); - // refresh(editor) debounceTimer = setTimeout(() => refresh(editor), 500); //only re-parse every 500ms } @@ -606,7 +548,7 @@ function onActivate(context) { } /** module init */ onInitModules(context, type); - onDidChange(activeEditor); + refresh(activeEditor, true); let commands = new Commands(g_workspace); let cockpit = new Cockpit(commands); @@ -1024,7 +966,7 @@ function onActivate(context) { context.subscriptions.push( vscode.languages.registerDocumentSymbolProvider( docSel, - new SolidityDocumentSymbolProvider(g_workspace, analyzeSourceUnit) + new SolidityDocumentSymbolProvider(g_workspace) ) ); } @@ -1033,7 +975,7 @@ function onActivate(context) { context.subscriptions.push( vscode.languages.registerCodeLensProvider( docSel, - new SolidityCodeLensProvider(g_workspace, analyzeSourceUnit) + new SolidityCodeLensProvider(g_workspace) ) ); diff --git a/src/features/codelens.js b/src/features/codelens.js index edd8403..cf5226f 100644 --- a/src/features/codelens.js +++ b/src/features/codelens.js @@ -24,9 +24,8 @@ function elemLocToRange(elem) { } class SolidityCodeLensProvider { - constructor(g_workspace, cb_analyze) { + constructor(g_workspace) { this.g_workspace = g_workspace; - this.cb_analyze = cb_analyze; this.codeLenses = []; } diff --git a/src/features/symbols.js b/src/features/symbols.js index 0f2826c..e859c95 100644 --- a/src/features/symbols.js +++ b/src/features/symbols.js @@ -267,28 +267,20 @@ function getAstValueForExpression(astnode) { } class SolidityDocumentSymbolProvider { - constructor(g_workspace, cb_analyze) { + constructor(g_workspace) { this.g_workspace = g_workspace; - this.cb_analyze = cb_analyze; } provideDocumentSymbols(document, token) { console.log('preparing symbols...'); return new Promise((resolve, reject) => { - var symbols = []; - - // 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); - this.g_workspace + return this.g_workspace .getSourceUnitByPath(document.fileName) .then((insights) => { + + var symbols = []; + console.log(`✓ inspect ${insights.filePath}`); console.log('--- preparing symbols for: ' + document.fileName); @@ -688,11 +680,10 @@ class SolidityDocumentSymbolProvider { console.log('✓ inheritance'); } if (token.isCancellationRequested) { - reject(token); - return; + return reject(token); } console.log('✓✓✓ done preparing symbols for: ' + document.fileName); - resolve(symbols); + return resolve(symbols); }) .catch((e) => { console.warn( @@ -701,6 +692,7 @@ class SolidityDocumentSymbolProvider { if (settings.extensionConfig().debug.parser.showExceptions) { console.error(e); } + return reject(e); }); }); } diff --git a/src/features/utils.js b/src/features/utils.js index f5e4a80..40421b6 100644 --- a/src/features/utils.js +++ b/src/features/utils.js @@ -47,112 +47,15 @@ class CommentMapperRex { } } -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}`; - } - return evmArg.replace(evmTypeRegex, replacer); -} - -function getCanonicalizedArgumentFromAstNode( - node, - _parent, - array = false, - isStruct = false -) { - if (!array && !node.typeName) { - console.log(node); - throw new Error('Failed to unpack function argument type'); - } - const argStorageLocation = node.storageLocation; - const argTypeNode = !array ? node.typeName : node; - switch (argTypeNode.type) { - case 'ElementaryTypeName': - return argTypeNode.name; - case 'ArrayTypeName': - const repr = - getCanonicalizedArgumentFromAstNode( - argTypeNode.baseTypeName, - _parent, - true - ) + '[]'; - return repr; - case 'UserDefinedTypeName': - if (!argStorageLocation && !isStruct) { - return 'address'; - } - const contract = _parent.parent; - const sourceUnit = contract._parent; - const struct = - contract.structs[argTypeNode.namePath] || - contract.inherited_structs[argTypeNode.namePath] || - sourceUnit.structs[argTypeNode.namePath]; - if (!struct) { - throw new Error( - `Failed to resolve struct ${node.namePath} in current scope.` - ); - } - const structTypes = struct.members.map((m) => - getCanonicalizedArgumentFromAstNode(m, _parent, false, true) - ); - const structSig = '(' + structTypes.join(',') + ')'; - return structSig; - default: - console.log(argTypeNode); - throw new Error('wrong argument type: ' + argTypeNode.name); - } -} - -function signatureFromFunctionASTNode(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, item)) - ); - - let fnsig = `${funcname}(${args.join(',')})`; - let sighash = createKeccakHash('keccak256') - .update(fnsig) - .digest('hex') - .toString('hex') - .slice(0, 8); - - return { - name: funcname, - signature: fnsig, - sighash: sighash, - }; -} - function functionSignatureForASTItem(item) { switch (item._node?.type) { case 'FunctionDefinition': - const res = signatureFromFunctionASTNode(item); + const res = item.getFunctionSignature(); //call getFunctionSignature from Workspace on function node return [res]; case 'ContractDefinition': return Object.values(item.functions) .filter((fn) => ['external', 'public'].includes(fn.visibility)) - .map((fn) => signatureFromFunctionASTNode(fn)); + .map((fn) => fn.getFunctionSignature()); default: throw new Error('Unsupported node type'); } From 39051a3b0a081f226cf86683b71f54b02c2921bf Mon Sep 17 00:00:00 2001 From: Valentin Date: Thu, 2 Feb 2023 14:56:44 +0100 Subject: [PATCH 03/32] Add package-lock --- package-lock.json | 879 +++++++++++++++++++++++++--------------------- 1 file changed, 483 insertions(+), 396 deletions(-) diff --git a/package-lock.json b/package-lock.json index fdfd293..cc4c4cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,10 +17,9 @@ "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==", + "../solidity-workspace": { + "version": "0.1.8", + "license": "MIT", "dependencies": { "@solidity-parser/parser": "^0.14.3", "c3-linearization": "^0.3.0", @@ -31,52 +30,276 @@ "solidity-workspace": "src/cli.js" } }, + "../solidity-workspace/node_modules/@solidity-parser/parser": { + "version": "0.14.3", + "license": "MIT", + "dependencies": { + "antlr4ts": "^0.5.0-alpha.4" + } + }, + "../solidity-workspace/node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../solidity-workspace/node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../solidity-workspace/node_modules/antlr4ts": { + "version": "0.5.0-alpha.4", + "license": "BSD-3-Clause" + }, + "../solidity-workspace/node_modules/c3-linearization": { + "version": "0.3.0", + "license": "MIT" + }, + "../solidity-workspace/node_modules/cliui": { + "version": "8.0.1", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "../solidity-workspace/node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "../solidity-workspace/node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "../solidity-workspace/node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT" + }, + "../solidity-workspace/node_modules/escalade": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "../solidity-workspace/node_modules/get-caller-file": { + "version": "2.0.5", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "../solidity-workspace/node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "../solidity-workspace/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../solidity-workspace/node_modules/keccak": { + "version": "3.0.2", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "../solidity-workspace/node_modules/node-addon-api": { + "version": "2.0.2", + "license": "MIT" + }, + "../solidity-workspace/node_modules/node-gyp-build": { + "version": "4.5.0", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "../solidity-workspace/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "../solidity-workspace/node_modules/require-directory": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "../solidity-workspace/node_modules/safe-buffer": { + "version": "5.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "../solidity-workspace/node_modules/string_decoder": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "../solidity-workspace/node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../solidity-workspace/node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../solidity-workspace/node_modules/util-deprecate": { + "version": "1.0.2", + "license": "MIT" + }, + "../solidity-workspace/node_modules/wrap-ansi": { + "version": "7.0.0", + "license": "MIT", + "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" + } + }, + "../solidity-workspace/node_modules/y18n": { + "version": "5.0.8", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "../solidity-workspace/node_modules/yargs": { + "version": "17.6.0", + "license": "MIT", + "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.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "../solidity-workspace/node_modules/yargs-parser": { + "version": "21.1.1", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "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==", + "version": "0.14.3", + "license": "MIT", "dependencies": { "antlr4ts": "^0.5.0-alpha.4" } }, "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==" + "license": "BSD-3-Clause" }, "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==" + "license": "MIT" }, "node_modules/camelcase": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==", + "license": "MIT", "engines": { "node": ">=4" } }, "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==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/colors": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "license": "MIT", "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==", + "license": "MIT", "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -90,24 +313,21 @@ }, "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==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "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==", + "license": "MIT", "dependencies": { "once": "^1.4.0" } }, "node_modules/execa": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "license": "MIT", "dependencies": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", @@ -123,8 +343,7 @@ }, "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==", + "license": "MIT", "dependencies": { "locate-path": "^2.0.0" }, @@ -134,8 +353,7 @@ }, "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==", + "license": "MIT", "dependencies": { "pump": "^3.0.0" }, @@ -145,8 +363,7 @@ }, "node_modules/graphviz": { "version": "0.0.9", - "resolved": "https://registry.npmjs.org/graphviz/-/graphviz-0.0.9.tgz", - "integrity": "sha512-SmoY2pOtcikmMCqCSy2NO1YsRfu9OO0wpTlOYW++giGjfX1a6gax/m1Fo8IdUd0/3H15cTOfR1SMKwohj4LKsg==", + "license": "GPL-3.0", "dependencies": { "temp": "~0.4.0" }, @@ -156,35 +373,30 @@ }, "node_modules/inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "license": "ISC" }, "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==", + "license": "MIT", "engines": { "node": ">=4" } }, "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==", + "license": "MIT", "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==" + "license": "ISC" }, "node_modules/keccak": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.3.tgz", - "integrity": "sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ==", + "version": "3.0.2", "hasInstallScript": true, + "license": "MIT", "dependencies": { "node-addon-api": "^2.0.0", "node-gyp-build": "^4.2.0", @@ -196,8 +408,7 @@ }, "node_modules/lcid": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "license": "MIT", "dependencies": { "invert-kv": "^2.0.0" }, @@ -207,8 +418,7 @@ }, "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==", + "license": "MIT", "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -219,8 +429,7 @@ }, "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==", + "license": "MIT", "dependencies": { "p-defer": "^1.0.0" }, @@ -230,8 +439,7 @@ }, "node_modules/mem": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "license": "MIT", "dependencies": { "map-age-cleaner": "^0.1.1", "mimic-fn": "^2.0.0", @@ -243,26 +451,22 @@ }, "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==", + "license": "MIT", "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==" + "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==" + "license": "MIT" }, "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==", + "version": "4.5.0", + "license": "MIT", "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -271,8 +475,7 @@ }, "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==", + "license": "MIT", "dependencies": { "path-key": "^2.0.0" }, @@ -282,24 +485,21 @@ }, "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==", + "license": "MIT", "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==", + "license": "ISC", "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==", + "license": "MIT", "dependencies": { "execa": "^1.0.0", "lcid": "^2.0.0", @@ -311,32 +511,28 @@ }, "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==", + "license": "MIT", "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==", + "license": "MIT", "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==", + "license": "MIT", "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==", + "license": "MIT", "dependencies": { "p-try": "^1.0.0" }, @@ -346,8 +542,7 @@ }, "node_modules/p-locate": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "license": "MIT", "dependencies": { "p-limit": "^1.1.0" }, @@ -357,32 +552,28 @@ }, "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==", + "license": "MIT", "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==", + "license": "MIT", "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==", + "license": "MIT", "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==", + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -390,8 +581,7 @@ }, "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==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -403,21 +593,17 @@ }, "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==", + "license": "MIT", "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==" + "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", @@ -431,31 +617,27 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/semver": { "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "license": "ISC", "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==" + "license": "ISC" }, "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." + "license": "MIT" }, "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==", + "license": "MIT", "dependencies": { "shebang-regex": "^1.0.0" }, @@ -465,16 +647,14 @@ }, "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==", + "license": "MIT", "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==" + "license": "ISC" }, "node_modules/solidity-workspace": { "resolved": "../solidity-workspace", @@ -482,24 +662,21 @@ }, "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==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } }, "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==", + "license": "MIT", "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==", + "license": "Apache-2.0", "dependencies": { "@solidity-parser/parser": "^0.14.1", "c3-linearization": "^0.3.0", @@ -515,16 +692,14 @@ }, "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==", + "license": "MIT", "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==", + "license": "ISC", "dependencies": { "string-width": "^2.1.1", "strip-ansi": "^4.0.0", @@ -533,21 +708,18 @@ }, "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==" + "license": "ISC" }, "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==", + "license": "MIT", "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==", + "license": "MIT", "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" @@ -558,8 +730,7 @@ }, "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==", + "license": "MIT", "dependencies": { "ansi-regex": "^3.0.0" }, @@ -569,8 +740,7 @@ }, "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==", + "license": "MIT", "dependencies": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" @@ -581,16 +751,14 @@ }, "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==", + "license": "MIT", "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==", + "license": "MIT", "dependencies": { "number-is-nan": "^1.0.0" }, @@ -600,8 +768,7 @@ }, "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==", + "license": "MIT", "dependencies": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -613,8 +780,7 @@ }, "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==", + "license": "MIT", "dependencies": { "ansi-regex": "^2.0.0" }, @@ -624,13 +790,11 @@ }, "node_modules/surya/node_modules/y18n": { "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" + "license": "ISC" }, "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==", + "license": "MIT", "dependencies": { "cliui": "^4.0.0", "decamelize": "^1.1.1", @@ -648,37 +812,31 @@ }, "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==", + "license": "ISC", "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==", + "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==" + "license": "MIT" }, "node_modules/which": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -688,86 +846,37 @@ }, "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==" + "license": "ISC" }, "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" - } + "license": "ISC" } }, "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==", + "version": "0.14.3", "requires": { "antlr4ts": "^0.5.0-alpha.4" } }, "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==" + "version": "0.5.0-alpha.4" }, "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==" + "version": "0.3.0" }, "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==" + "version": "4.1.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==" + "version": "1.1.0" }, "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + "version": "1.4.0" }, "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", @@ -777,22 +886,16 @@ } }, "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" + "version": "1.2.0" }, "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" } }, "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", @@ -805,52 +908,36 @@ }, "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" } }, "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==" + "version": "2.0.4" }, "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": "2.0.0" }, "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==" + "version": "1.1.0" }, "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "version": "2.0.0" }, "keccak": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.3.tgz", - "integrity": "sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ==", + "version": "3.0.2", "requires": { "node-addon-api": "^2.0.0", "node-gyp-build": "^4.2.0", @@ -859,16 +946,12 @@ }, "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" @@ -876,16 +959,12 @@ }, "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", @@ -893,50 +972,34 @@ } }, "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + "version": "2.1.0" }, "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + "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==" + "version": "2.0.2" }, "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==" + "version": "4.5.0" }, "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==" + "version": "1.0.1" }, "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", @@ -944,55 +1007,37 @@ } }, "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==" + "version": "1.0.0" }, "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==" + "version": "1.0.0" }, "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==" + "version": "2.1.0" }, "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==" + "version": "1.0.0" }, "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + "version": "3.0.0" }, "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==" + "version": "2.0.1" }, "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" @@ -1000,8 +1045,6 @@ }, "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", @@ -1009,52 +1052,34 @@ } }, "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==" + "version": "2.1.1" }, "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==" + "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==" + "version": "5.2.1" }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "5.7.1" }, "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==" + "version": "2.0.0" }, "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==" + "version": "1.0.4" }, "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==" + "version": "1.0.0" }, "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==" + "version": "3.0.7" }, "solidity-workspace": { "version": "file:../solidity-workspace", @@ -1063,25 +1088,151 @@ "c3-linearization": "^0.3.0", "keccak": "^3.0.2", "yargs": "^17.5.1" + }, + "dependencies": { + "@solidity-parser/parser": { + "version": "0.14.3", + "requires": { + "antlr4ts": "^0.5.0-alpha.4" + } + }, + "ansi-regex": { + "version": "5.0.1" + }, + "ansi-styles": { + "version": "4.3.0", + "requires": { + "color-convert": "^2.0.1" + } + }, + "antlr4ts": { + "version": "0.5.0-alpha.4" + }, + "c3-linearization": { + "version": "0.3.0" + }, + "cliui": { + "version": "8.0.1", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4" + }, + "emoji-regex": { + "version": "8.0.0" + }, + "escalade": { + "version": "3.1.1" + }, + "get-caller-file": { + "version": "2.0.5" + }, + "inherits": { + "version": "2.0.4" + }, + "is-fullwidth-code-point": { + "version": "3.0.0" + }, + "keccak": { + "version": "3.0.2", + "requires": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" + } + }, + "node-addon-api": { + "version": "2.0.2" + }, + "node-gyp-build": { + "version": "4.5.0" + }, + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "require-directory": { + "version": "2.1.1" + }, + "safe-buffer": { + "version": "5.2.1" + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-width": { + "version": "4.2.3", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "util-deprecate": { + "version": "1.0.2" + }, + "wrap-ansi": { + "version": "7.0.0", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8" + }, + "yargs": { + "version": "17.6.0", + "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.0.0" + } + }, + "yargs-parser": { + "version": "21.1.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" } }, "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==" + "version": "1.0.0" }, "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", @@ -1093,14 +1244,10 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==" + "version": "3.0.1" }, "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", @@ -1108,19 +1255,13 @@ } }, "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==" + "version": "1.0.3" }, "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==" + "version": "2.0.0" }, "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" @@ -1128,38 +1269,28 @@ }, "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==" + "version": "2.1.1" }, "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", @@ -1168,8 +1299,6 @@ }, "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" } @@ -1177,14 +1306,10 @@ } }, "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" + "version": "3.2.2" }, "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", @@ -1202,8 +1327,6 @@ }, "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" } @@ -1211,61 +1334,25 @@ } }, "temp": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.4.0.tgz", - "integrity": "sha512-IsFisGgDKk7qzK9erMIkQe/XwiSUdac7z3wYOsjcLkhPBy3k1SlvLoIh2dAHIlEpgA971CgguMrx9z8fFg7tSA==" + "version": "0.4.0" }, "treeify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", - "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==" + "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==" + "version": "1.0.2" }, "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": "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==" - }, - "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" - } - }, - "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": "1.0.2" } } } From 5d80c5f2a053550bb76e95f1736184f253144d46 Mon Sep 17 00:00:00 2001 From: Valentin Date: Thu, 2 Feb 2023 15:22:37 +0100 Subject: [PATCH 04/32] Modify CodeLens provider names for clarity --- src/extension.js | 8 ++++---- src/features/codelens.js | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/extension.js b/src/extension.js index d9cf245..fa5c474 100644 --- a/src/extension.js +++ b/src/extension.js @@ -20,8 +20,8 @@ const mod_parser = require('solidity-workspace'); const { DiliDiagnosticCollection } = require('./features/genericDiag'); const { Commands } = require('./features/commands'); const { - SolidityCodeLensProvider, - SolidityParserLensProvider, + StaticLensProvider, + ParserLensProvider, } = require('./features/codelens'); const settings = require('./settings'); const { Cockpit } = require('./features/cockpit.js'); @@ -975,14 +975,14 @@ function onActivate(context) { context.subscriptions.push( vscode.languages.registerCodeLensProvider( docSel, - new SolidityCodeLensProvider(g_workspace) + new StaticLensProvider(g_workspace) ) ); context.subscriptions.push( vscode.languages.registerCodeLensProvider( docSel, - new SolidityParserLensProvider(g_workspace) + new ParserLensProvider(g_workspace) ) ); } diff --git a/src/features/codelens.js b/src/features/codelens.js index cf5226f..85d8e94 100644 --- a/src/features/codelens.js +++ b/src/features/codelens.js @@ -23,7 +23,7 @@ function elemLocToRange(elem) { ); } -class SolidityCodeLensProvider { +class StaticLensProvider { constructor(g_workspace) { this.g_workspace = g_workspace; this.codeLenses = []; @@ -105,7 +105,7 @@ class SolidityCodeLensProvider { } } -class SolidityParserLensProvider { +class ParserLensProvider { constructor(g_workspace) { this.g_workspace = g_workspace; } @@ -253,6 +253,6 @@ class SolidityParserLensProvider { } module.exports = { - SolidityCodeLensProvider: SolidityCodeLensProvider, - SolidityParserLensProvider: SolidityParserLensProvider, + StaticLensProvider, + ParserLensProvider, }; From 97d3d421f2bae7fb1339c88b4d2de5a875407b0b Mon Sep 17 00:00:00 2001 From: tintinweb Date: Tue, 14 Feb 2023 14:50:27 +0100 Subject: [PATCH 05/32] cleanup package.json, update deps add funcsig command --- package-lock.json | 489 ++-------------------------------------------- package.json | 10 +- 2 files changed, 22 insertions(+), 477 deletions(-) diff --git a/package-lock.json b/package-lock.json index cc4c4cb..2cab688 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,20 +8,18 @@ "name": "solidity-visual-auditor", "version": "0.1.5", "dependencies": { - "c3-linearization": "^0.3.0", - "keccak": "^3.0.2", - "solidity-workspace": "file:../solidity-workspace", + "solidity-workspace": "file:../../js/solidity-workspace", "surya": "^0.4.6" }, "engines": { "vscode": "^1.26.2" } }, - "../solidity-workspace": { - "version": "0.1.8", + "../../js/solidity-workspace": { + "version": "0.2.0", "license": "MIT", "dependencies": { - "@solidity-parser/parser": "^0.14.3", + "@solidity-parser/parser": "^0.15.0", "c3-linearization": "^0.3.0", "keccak": "^3.0.2", "yargs": "^17.5.1" @@ -30,235 +28,18 @@ "solidity-workspace": "src/cli.js" } }, - "../solidity-workspace/node_modules/@solidity-parser/parser": { - "version": "0.14.3", - "license": "MIT", - "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" - } - }, - "../solidity-workspace/node_modules/ansi-regex": { - "version": "5.0.1", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "../solidity-workspace/node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "../solidity-workspace/node_modules/antlr4ts": { - "version": "0.5.0-alpha.4", - "license": "BSD-3-Clause" - }, - "../solidity-workspace/node_modules/c3-linearization": { - "version": "0.3.0", - "license": "MIT" - }, - "../solidity-workspace/node_modules/cliui": { - "version": "8.0.1", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "../solidity-workspace/node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "../solidity-workspace/node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "../solidity-workspace/node_modules/emoji-regex": { - "version": "8.0.0", - "license": "MIT" - }, - "../solidity-workspace/node_modules/escalade": { - "version": "3.1.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "../solidity-workspace/node_modules/get-caller-file": { - "version": "2.0.5", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "../solidity-workspace/node_modules/inherits": { - "version": "2.0.4", - "license": "ISC" - }, - "../solidity-workspace/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "../solidity-workspace/node_modules/keccak": { - "version": "3.0.2", - "hasInstallScript": true, + "../solidity-workspace": { + "version": "0.1.8", + "extraneous": true, "license": "MIT", "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" + "@solidity-parser/parser": "^0.14.3", + "c3-linearization": "^0.3.0", + "keccak": "^3.0.2", + "yargs": "^17.5.1" }, - "engines": { - "node": ">=10.0.0" - } - }, - "../solidity-workspace/node_modules/node-addon-api": { - "version": "2.0.2", - "license": "MIT" - }, - "../solidity-workspace/node_modules/node-gyp-build": { - "version": "4.5.0", - "license": "MIT", "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "../solidity-workspace/node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "../solidity-workspace/node_modules/require-directory": { - "version": "2.1.1", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "../solidity-workspace/node_modules/safe-buffer": { - "version": "5.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "../solidity-workspace/node_modules/string_decoder": { - "version": "1.3.0", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "../solidity-workspace/node_modules/string-width": { - "version": "4.2.3", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "../solidity-workspace/node_modules/strip-ansi": { - "version": "6.0.1", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "../solidity-workspace/node_modules/util-deprecate": { - "version": "1.0.2", - "license": "MIT" - }, - "../solidity-workspace/node_modules/wrap-ansi": { - "version": "7.0.0", - "license": "MIT", - "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" - } - }, - "../solidity-workspace/node_modules/y18n": { - "version": "5.0.8", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "../solidity-workspace/node_modules/yargs": { - "version": "17.6.0", - "license": "MIT", - "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.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "../solidity-workspace/node_modules/yargs-parser": { - "version": "21.1.1", - "license": "ISC", - "engines": { - "node": ">=12" + "solidity-workspace": "src/cli.js" } }, "node_modules/@solidity-parser/parser": { @@ -371,10 +152,6 @@ "node": ">=0.6.8" } }, - "node_modules/inherits": { - "version": "2.0.4", - "license": "ISC" - }, "node_modules/invert-kv": { "version": "2.0.0", "license": "MIT", @@ -393,19 +170,6 @@ "version": "2.0.0", "license": "ISC" }, - "node_modules/keccak": { - "version": "3.0.2", - "hasInstallScript": true, - "license": "MIT", - "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", @@ -460,19 +224,6 @@ "version": "1.0.5", "license": "MIT" }, - "node_modules/node-addon-api": { - "version": "2.0.2", - "license": "MIT" - }, - "node_modules/node-gyp-build": { - "version": "4.5.0", - "license": "MIT", - "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", @@ -579,18 +330,6 @@ "once": "^1.3.1" } }, - "node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "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", @@ -602,24 +341,6 @@ "version": "1.0.1", "license": "ISC" }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/semver": { "version": "5.7.1", "license": "ISC", @@ -657,16 +378,9 @@ "license": "ISC" }, "node_modules/solidity-workspace": { - "resolved": "../solidity-workspace", + "resolved": "../../js/solidity-workspace", "link": true }, - "node_modules/string_decoder": { - "version": "1.3.0", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/strip-eof": { "version": "1.0.0", "license": "MIT", @@ -830,10 +544,6 @@ "node": ">=0.6" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "license": "MIT" - }, "node_modules/which": { "version": "1.3.1", "license": "ISC", @@ -924,9 +634,6 @@ "temp": "~0.4.0" } }, - "inherits": { - "version": "2.0.4" - }, "invert-kv": { "version": "2.0.0" }, @@ -936,14 +643,6 @@ "isexe": { "version": "2.0.0" }, - "keccak": { - "version": "3.0.2", - "requires": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" - } - }, "lcid": { "version": "2.0.0", "requires": { @@ -977,12 +676,6 @@ "nice-try": { "version": "1.0.5" }, - "node-addon-api": { - "version": "2.0.2" - }, - "node-gyp-build": { - "version": "4.5.0" - }, "npm-run-path": { "version": "2.0.2", "requires": { @@ -1043,23 +736,12 @@ "once": "^1.3.1" } }, - "readable-stream": { - "version": "3.6.0", - "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" - }, "semver": { "version": "5.7.1" }, @@ -1082,150 +764,12 @@ "version": "3.0.7" }, "solidity-workspace": { - "version": "file:../solidity-workspace", + "version": "file:../../js/solidity-workspace", "requires": { - "@solidity-parser/parser": "^0.14.3", + "@solidity-parser/parser": "^0.15.0", "c3-linearization": "^0.3.0", "keccak": "^3.0.2", "yargs": "^17.5.1" - }, - "dependencies": { - "@solidity-parser/parser": { - "version": "0.14.3", - "requires": { - "antlr4ts": "^0.5.0-alpha.4" - } - }, - "ansi-regex": { - "version": "5.0.1" - }, - "ansi-styles": { - "version": "4.3.0", - "requires": { - "color-convert": "^2.0.1" - } - }, - "antlr4ts": { - "version": "0.5.0-alpha.4" - }, - "c3-linearization": { - "version": "0.3.0" - }, - "cliui": { - "version": "8.0.1", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4" - }, - "emoji-regex": { - "version": "8.0.0" - }, - "escalade": { - "version": "3.1.1" - }, - "get-caller-file": { - "version": "2.0.5" - }, - "inherits": { - "version": "2.0.4" - }, - "is-fullwidth-code-point": { - "version": "3.0.0" - }, - "keccak": { - "version": "3.0.2", - "requires": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" - } - }, - "node-addon-api": { - "version": "2.0.2" - }, - "node-gyp-build": { - "version": "4.5.0" - }, - "readable-stream": { - "version": "3.6.0", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "require-directory": { - "version": "2.1.1" - }, - "safe-buffer": { - "version": "5.2.1" - }, - "string_decoder": { - "version": "1.3.0", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-width": { - "version": "4.2.3", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "util-deprecate": { - "version": "1.0.2" - }, - "wrap-ansi": { - "version": "7.0.0", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8" - }, - "yargs": { - "version": "17.6.0", - "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.0.0" - } - }, - "yargs-parser": { - "version": "21.1.1" - } - } - }, - "string_decoder": { - "version": "1.3.0", - "requires": { - "safe-buffer": "~5.2.0" } }, "strip-eof": { @@ -1339,9 +883,6 @@ "treeify": { "version": "1.1.0" }, - "util-deprecate": { - "version": "1.0.2" - }, "which": { "version": "1.3.1", "requires": { diff --git a/package.json b/package.json index f3b0eaf..671f08c 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "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", @@ -232,6 +233,11 @@ "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)", @@ -539,9 +545,7 @@ "tintinweb.vscode-ethover" ], "dependencies": { - "c3-linearization": "^0.3.0", - "keccak": "^3.0.2", - "solidity-workspace": "file:../solidity-workspace", + "solidity-workspace": "file:../../js/solidity-workspace", "surya": "^0.4.6" } } From cca1e356e549ae20347c44bfac43dde804720f6d Mon Sep 17 00:00:00 2001 From: tintinweb Date: Tue, 14 Feb 2023 14:50:57 +0100 Subject: [PATCH 06/32] ignore constructor/fallback/receive --- src/features/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/utils.js b/src/features/utils.js index 40421b6..903f097 100644 --- a/src/features/utils.js +++ b/src/features/utils.js @@ -54,7 +54,7 @@ function functionSignatureForASTItem(item) { return [res]; case 'ContractDefinition': return Object.values(item.functions) - .filter((fn) => ['external', 'public'].includes(fn.visibility)) + .filter((fn) => fn.name && ['external', 'public'].includes(fn.visibility)) .map((fn) => fn.getFunctionSignature()); default: throw new Error('Unsupported node type'); From 768d137d2ddcd04a244854364976e4f97fa13e19 Mon Sep 17 00:00:00 2001 From: tintinweb Date: Tue, 14 Feb 2023 14:51:24 +0100 Subject: [PATCH 07/32] add command: funcsigs for workspace (markdown) --- src/extension.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/extension.js b/src/extension.js index fa5c474..799561b 100644 --- a/src/extension.js +++ b/src/extension.js @@ -783,6 +783,15 @@ function onActivate(context) { ) ); + 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', From c567d6d63fe6e7c9bb94f55cf5257fd934bfeef6 Mon Sep 17 00:00:00 2001 From: tintinweb Date: Tue, 14 Feb 2023 14:51:52 +0100 Subject: [PATCH 08/32] new: codelens 'funcSigs' for source unit (line1) --- src/features/codelens.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/features/codelens.js b/src/features/codelens.js index 85d8e94..786b95f 100644 --- a/src/features/codelens.js +++ b/src/features/codelens.js @@ -134,6 +134,15 @@ class ParserLensProvider { }) ); + 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']; /** all contract decls */ for (let contractObj of Object.values(parser.contracts)) { From f1493d8b2f99f3dc8faddf858a13ba9d467047a4 Mon Sep 17 00:00:00 2001 From: tintinweb Date: Tue, 14 Feb 2023 14:52:34 +0100 Subject: [PATCH 09/32] reimplement funcsigs for workspace --- src/features/commands.js | 214 +++++++++++++++++++-------------------- 1 file changed, 105 insertions(+), 109 deletions(-) diff --git a/src/features/commands.js b/src/features/commands.js index d9db70b..29a745c 100644 --- a/src/features/commands.js +++ b/src/features/commands.js @@ -451,7 +451,7 @@ class Commands { sourceUnit.contracts[contractName].dependencies; contractToFile[contractName] = solfile; } - } catch (e) {} + } catch (e) { } }); }); } else { @@ -518,7 +518,7 @@ ${topLevelContractsText}`; // command not available vscode.window.showWarningMessage( 'Error running `tintinweb.vscode-solidity-flattener`. Please make sure the extension is installed.\n' + - error + error ); }); }, @@ -671,9 +671,8 @@ ${topLevelContractsText}`; let outpath_flat = vscode.Uri.file( path.join(outpath.dir, 'flat_' + outpath.base) ); - content += `${ - !fs.existsSync(outpath_flat.fsPath) ? '[ERR] ' : '' - }${name} => ${outpath_flat} \n`; + content += `${!fs.existsSync(outpath_flat.fsPath) ? '[ERR] ' : '' + }${name} => ${outpath_flat} \n`; } vscode.workspace .openTextDocument({ content: content, language: 'markdown' }) @@ -682,115 +681,112 @@ ${topLevelContractsText}`; ); } - // async listFunctionSignatures(document, asJson) { - // let sighash_colls = mod_utils.functionSignaturesForSourceUnit( - // document. - // ); - // 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); - // } 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: content, language: "markdown" }) - // .then((doc) => - // vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) - // ); - // } - - // async listFunctionSignaturesForWorkspace(asJson) { - // let sighashes = {}; - // let collisions = []; - - // 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 - - // let currSigs = sig_colls.sighashes; - // for (let k in currSigs) { - // sighashes[k] = currSigs[k]; - // } - // } catch (e) {} - // }); - // }); - - // 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"); - // } - // } - // vscode.workspace - // .openTextDocument({ content: content, language: "markdown" }) - // .then((doc) => - // vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) - // ); - // } - - async signatureForAstItem(item) { - let results; - let err; - try { - results = mod_utils.functionSignatureForASTItem(item); - } catch (e) { - console.log(e.message); - err = e.message; + 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 revealSignatures(signatures, format){ + format = format || 'markdown'; + let errs = []; + + const res = {}; + + 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); + } } + let content; - if (!err) { - const header = - 'Function Name | Sighash | Function Signature | \n ------------ | ------------ | ------------ |\n'; - content = - header + - results - .map((r) => `${r.name} | ${r.sighash} | ${r.signature} |`) - .join('\n'); - } else { - content = 'Failed to compute function signature: ' + err; + + 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"); + } + + if (errs.length) { + content += "\n\n"; + content += + "🐞 Errors \n========================\n"; + content += [...new Set(errs)].join('\n'); + } } vscode.workspace - .openTextDocument({ content: content, language: 'markdown' }) + .openTextDocument({ content: content, language: format }) .then((doc) => vscode.window.showTextDocument(doc, { viewColumn: vscode.ViewColumn.Beside, From 963d5afdde92ab7a6c60b249015a16166d0ed51e Mon Sep 17 00:00:00 2001 From: tintinweb Date: Tue, 14 Feb 2023 15:00:52 +0100 Subject: [PATCH 10/32] drawio export: resolve receive()/fallback() names --- src/features/writer/drawio.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/features/writer/drawio.js b/src/features/writer/drawio.js index cdc8128..f0de791 100644 --- a/src/features/writer/drawio.js +++ b/src/features/writer/drawio.js @@ -53,14 +53,21 @@ const contractNameColorMapping = { "library": "#d5e8d4" //strokeColor=#82b366 }; -function _mapAstFunctionName(name) { - switch (name) { +function _mapAstNodeToFunctionName(node) { + if(node.isConstructor){ + return "__constr__"; + } else if(node.isReceiveEther){ + return "__receive__"; + } else if(node.isFallback){ + return "__fallback__"; + } + switch (node.name) { case null: return "__constr__"; case "": return "__fallback__"; default: - return name; + return node.name; } } @@ -150,7 +157,7 @@ class DrawioContract { ), this); // add methods: 2,test,1, this.methods.forEach((funcObj, i) => { - let method = `${stateMutabilityToIcon[funcObj._node.stateMutability] || ""}${_mapAstFunctionName(funcObj._node.name)}`; + let method = `${stateMutabilityToIcon[funcObj._node.stateMutability] || ""}${_mapAstNodeToFunctionName(funcObj._node)}`; content.push(serializeCsv({ "id": `${this.id}_f${i}`, "rparent": `${this.id}`, From 57d5890e99fa971f4d45845727d9b3ef92d9f154 Mon Sep 17 00:00:00 2001 From: tintinweb Date: Tue, 14 Feb 2023 15:05:07 +0100 Subject: [PATCH 11/32] plantuml export: resolve receive()/fallback() names --- src/features/writer/plantuml.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/features/writer/plantuml.js b/src/features/writer/plantuml.js index da76c63..23f72a5 100644 --- a/src/features/writer/plantuml.js +++ b/src/features/writer/plantuml.js @@ -36,14 +36,21 @@ const contractNameMapping = { "library":"abstract" }; -function _mapAstFunctionName(name) { - switch(name) { +function _mapAstNodeToFunctionName(node) { + if(node.isConstructor){ + return "**__constructor__**"; + } else if(node.isReceiveEther){ + return "**__receive__**"; + } else if(node.isFallback){ + return "**__fallback__**"; + } + switch (node.name) { case null: return "**__constructor__**"; case "": return "**__fallback__**"; default: - return name; + return node.name; } } @@ -83,7 +90,7 @@ ${Object.values(contractObj.stateVars).reduce((umlSvarTxt, astNode) => { } ' -- methods -- ${contractObj.functions.reduce((umlFuncTxt, funcObj) => { - return umlFuncTxt + `\t${functionVisibility[funcObj._node.visibility] || ""}${stateMutabilityToIcon[funcObj._node.stateMutability]||""}${_mapAstFunctionName(funcObj._node.name)}()\n`; + return umlFuncTxt + `\t${functionVisibility[funcObj._node.visibility] || ""}${stateMutabilityToIcon[funcObj._node.stateMutability]||""}${_mapAstNodeToFunctionName(funcObj._node)}()\n`; }, "") } } From 6036c1708f6b9a83ddf8405184799b63d84ad8b6 Mon Sep 17 00:00:00 2001 From: tintinweb Date: Tue, 14 Feb 2023 15:28:58 +0100 Subject: [PATCH 12/32] fix: ftrace failing due to non-fs-files being passed to surya --- src/features/commands.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/features/commands.js b/src/features/commands.js index 29a745c..7b13b76 100644 --- a/src/features/commands.js +++ b/src/features/commands.js @@ -191,10 +191,11 @@ class Commands { }); }); } else { + //better only add imported files. need to resolve that somehow files = [ documentOrListItems.uri.fsPath, ...Object.keys(this.g_workspace.sourceUnits), - ]; //better only add imported files. need to resolve that somehow + ].filter(p => fs.existsSync(p)); //only feed existing files into surya or it might die 🥲 } } From 3fffd1ccdeed1fb91d1f052e5fd99d0533ee84cc Mon Sep 17 00:00:00 2001 From: tintinweb Date: Tue, 14 Feb 2023 15:29:20 +0100 Subject: [PATCH 13/32] fix: cockpit/external calls view failed to resolve functions that were declared on one line. fixed by adding target column to function lookup --- src/features/cockpit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/cockpit.js b/src/features/cockpit.js index e36d910..471b611 100644 --- a/src/features/cockpit.js +++ b/src/features/cockpit.js @@ -898,7 +898,7 @@ class ExtCallView extends BaseView { // data format: obj[contract][function][calls]=[target, target]; let extcalls = focusSolidityElement.getExternalCalls().reduce((obj, c) => { - let result = sourceUnit.getFunctionAtLocation(c._node.loc.start.line, 0); + let result = sourceUnit.getFunctionAtLocation(c._node.loc.start.line, c._node.loc.start.column); let key = `${result.function.name}`; let data = obj[key]; From 36f1167c7dee3e5d2f77d335368d86bdb19b174c Mon Sep 17 00:00:00 2001 From: tintinweb Date: Tue, 14 Feb 2023 15:50:58 +0100 Subject: [PATCH 14/32] update changelog, prep 0.2.0 --- CHANGELOG.md | 9 +++++++++ src/features/whatsnew/whatsNew.js | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78725f1..8744861 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ Note: Don't forget to check out `preferences → Settings → Solidity Visual Developer` to customize features, look and feel. +## v0.2.0 - 💖 Happy Valentine's Days, spread some love! 💖 +- fix: includes parser performance optimizations with [solidity-workspace@v0.2.0](https://github.com/tintinweb/solidity-workspace/releases/tag/v0.2.0) (🙏 @vquelque) +- update: completely refactored function signature computation - #127 +- fix: performance optimizations (debounce) - #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 ## v0.1.5 - 🏂 - fix: find all references not working - #119 diff --git a/src/features/whatsnew/whatsNew.js b/src/features/whatsnew/whatsNew.js index deae394..7c33e08 100644 --- a/src/features/whatsnew/whatsNew.js +++ b/src/features/whatsnew/whatsNew.js @@ -36,6 +36,17 @@ ___ The complete changelog can be found [here](https://github.com/ConsenSys/vscode-solidity-auditor/blob/master/CHANGELOG.md). +## v0.2.0 - 💖 Happy Valentine's Days, spread some love! 💖 + +- fix: includes parser performance optimizations with [solidity-workspace@v0.2.0](https://github.com/tintinweb/solidity-workspace/releases/tag/v0.2.0) (🙏 @vquelque) +- update: completely refactored function signature computation - #127 +- fix: performance optimizations (debounce) - #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 + ## v0.1.5 - 🏂 - fix: find all references not working - #119 From f7750fc5fc84bf2e0cb511526322d91ae7d99af8 Mon Sep 17 00:00:00 2001 From: Valentin Date: Wed, 4 Oct 2023 18:00:41 +0200 Subject: [PATCH 15/32] refactor decoration --- src/extension.js | 715 ++++++----------------- src/features/deco.js | 1276 ++++++++++++++++++++++++++---------------- 2 files changed, 980 insertions(+), 1011 deletions(-) diff --git a/src/extension.js b/src/extension.js index 799561b..170c0d9 100644 --- a/src/extension.js +++ b/src/extension.js @@ -1,4 +1,4 @@ -'use strict'; +"use strict"; /** * @author github.com/tintinweb * @license GPLv3 @@ -6,35 +6,35 @@ * * */ /** imports */ -const vscode = require('vscode'); -const { CancellationTokenSource } = require('vscode'); -const path = require('path'); +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 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'); +} = 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'); +} = 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 { 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) + vscode.workspace.workspaceFolders.map((wf) => wf.uri.fsPath), ); var activeEditor; var g_diagnostics; @@ -53,7 +53,7 @@ function editorJumptoRange(editor, range) { range.start.line, range.start.character, range.end.line, - range.end.character + range.end.character, ); if (range.start.line === editor.selection.active.line) { revealType = vscode.TextEditorRevealType.InCenterIfOutsideViewport; @@ -63,25 +63,6 @@ function editorJumptoRange(editor, range) { 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]); - } -} - /*** EVENTS *********************************************** */ function onInitModules(context, type) { @@ -90,34 +71,20 @@ function onInitModules(context, type) { //globals init g_diagnostics = new DiliDiagnosticCollection( context, - vscode.workspace.rootPath + 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)); - } - }); - return decorations; -} - -function analyzeSourceUnit(cancellationToken, document, editor, initialLoad=false) { - console.log('inspect ...'); +function analyzeSourceUnit( + cancellationToken, + document, + editor, + initialLoad = false, +) { + console.log("inspect ..."); if (!document) { - console.error('-BUG- cannot analyze empty document!'); + console.error("-BUG- cannot analyze empty document!"); return; } @@ -128,351 +95,40 @@ function analyzeSourceUnit(cancellationToken, document, editor, initialLoad=fals }) .catch((e) => { console.warn( - `Error adding file or one of its dependencies to workspace (parser error): ${document.fileName}` + `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(document.fileName, initialLoad).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'); + g_workspace + .withParserReady(document.fileName, initialLoad) + .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; } - for (var contract of Object.values(this_sourceUnit.contracts)) { - console.log('+ in contract: ' + contract.name); - - /** 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 - ) - ); + let currentConfig = settings.extensionConfig(); + let shouldDecorate = + currentConfig.deco.statevars || + currentConfig.deco.arguments || + currentConfig.deco.warn.reserved; - /*** 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; + if (shouldDecorate && editor) { + let this_sourceUnit = g_workspace.get(document.fileName); + mod_decorator.decorateSourceUnit(document, editor, this_sourceUnit); + //decorate } - - setDecorations(editor, decorations); - console.log('✓ apply decorations - scope'); - } - console.log('✓ analyzeSourceUnit - done'); - }); + console.log("✓ analyzeSourceUnit - done"); + }); } /** events */ @@ -489,7 +145,7 @@ function onDidSave(document) { } } -function refresh(editor, initialLoad=false) { +function refresh(editor, initialLoad = false) { let document = editor && editor.document ? editor.document @@ -497,30 +153,30 @@ function refresh(editor, initialLoad=false) { ? vscode.window.activeTextEditor.document : undefined; if (!document) { - console.warn('change event on non-document'); + console.warn("change event on non-document"); return; } if (document.languageId != languageId) { - console.log('ondidchange: wrong langid'); + console.log("ondidchange: wrong langid"); return; } - currentCancellationTokens.onDidChange.dispose(); + currentCancellationTokens.onDidChange.cancel(); currentCancellationTokens.onDidChange = new CancellationTokenSource(); - console.log('--- on-did-change'); + console.log("--- on-did-change"); try { analyzeSourceUnit( currentCancellationTokens.onDidChange.token, document, editor, - initialLoad + initialLoad, ); } catch (err) { - if (typeof err !== 'object') { + if (typeof err !== "object") { //CancellationToken throw err; } } - console.log('✓✓✓ on-did-change - resolved'); + console.log("✓✓✓ on-did-change - resolved"); } function onDidChange(editor) { @@ -531,7 +187,7 @@ function onDidChange(editor) { function onActivate(context) { activeEditor = vscode.window.activeTextEditor; - console.log('onActivate'); + console.log("onActivate"); registerDocType(languageId, docSelector); @@ -542,7 +198,7 @@ function onActivate(context) { if (!settings.extensionConfig().mode.active) { console.log( - 'ⓘ activate extension: entering passive mode. not registering any active code augmentation support.' + "ⓘ activate extension: entering passive mode. not registering any active code augmentation support.", ); return; } @@ -555,44 +211,44 @@ function onActivate(context) { /** command setup */ context.subscriptions.push( - vscode.commands.registerCommand('solidity-va.whatsNew.show', function () { + vscode.commands.registerCommand("solidity-va.whatsNew.show", function () { new WhatsNewHandler().showMessage(context); - }) + }), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.test.createTemplate', + "solidity-va.test.createTemplate", function (doc, contractName) { commands.generateUnittestStubForContract( doc || vscode.window.activeTextEditor.document, - contractName + contractName, ); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.surya.mdreport', + "solidity-va.surya.mdreport", function (doc, multiSelectTreeItems) { doc = multiSelectTreeItems || doc; commands.surya( doc || vscode.window.activeTextEditor.document, - 'mdreport' + "mdreport", ); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.surya.graph', + "solidity-va.surya.graph", function (doc, files) { if ( files && - typeof files[0] === 'object' && - files[0].hasOwnProperty('children') + typeof files[0] === "object" && + files[0].hasOwnProperty("children") ) { //treeItem or fspaths doc = files; @@ -600,31 +256,31 @@ function onActivate(context) { } commands.surya( doc || vscode.window.activeTextEditor.document, - 'graph', - files + "graph", + files, ); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.surya.graphThis', + "solidity-va.surya.graphThis", function () { - commands.surya(vscode.window.activeTextEditor.document, 'graph', [ + commands.surya(vscode.window.activeTextEditor.document, "graph", [ vscode.window.activeTextEditor.document.uri.fsPath, ]); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.surya.graphSimple', + "solidity-va.surya.graphSimple", function (doc, files) { if ( files && - typeof files[0] === 'object' && - files[0].hasOwnProperty('children') + typeof files[0] === "object" && + files[0].hasOwnProperty("children") ) { //treeItem or fspaths doc = files; @@ -632,83 +288,83 @@ function onActivate(context) { } commands.surya( doc || vscode.window.activeTextEditor.document, - 'graphSimple', - files + "graphSimple", + files, ); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.surya.inheritance', + "solidity-va.surya.inheritance", function (doc, multiSelectTreeItems) { doc = multiSelectTreeItems || doc; commands.surya( doc || vscode.window.activeTextEditor.document, - 'inheritance' + "inheritance", ); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.surya.parse', + "solidity-va.surya.parse", function (doc) { commands.surya( doc || vscode.window.activeTextEditor.document, - 'parse' + "parse", ); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.surya.dependencies', + "solidity-va.surya.dependencies", function (doc, ContractName) { commands.surya( doc || vscode.window.activeTextEditor.document, - 'dependencies', - [ContractName] + "dependencies", + [ContractName], ); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.surya.ftrace', + "solidity-va.surya.ftrace", function (doc, contractName, functionName, mode) { commands.surya( doc || vscode.window.activeTextEditor.document, - 'ftrace', - [contractName, functionName, mode] + "ftrace", + [contractName, functionName, mode], ); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.insights.topLevelContracts', + "solidity-va.insights.topLevelContracts", function () { commands.findTopLevelContracts(); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.tools.flaterra', + "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', + "solidity-va.cockpit.explorer.context.flatten", async function (treeItem, multiSelectTreeItems) { multiSelectTreeItems = multiSelectTreeItems || []; [...multiSelectTreeItems, treeItem].forEach(async (treeItem) => { @@ -725,158 +381,157 @@ function onActivate(context) { }); */ }); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.tools.flattenCandidates', + "solidity-va.tools.flattenCandidates", function () { commands.flattenCandidates(); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.cockpit.topLevelContracts.flatten', + "solidity-va.cockpit.topLevelContracts.flatten", function () { let sourceFiles = cockpit.views.topLevelContracts.dataProvider.data.reduce(function ( obj, - item + item, ) { - obj[path.basename(item.path, '.sol')] = vscode.Uri.file( - item.path + 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', + "solidity-va.tools.function.signatures", function (doc, asJson) { commands.listFunctionSignatures( doc || vscode.window.activeTextEditor.document, - asJson + asJson, ); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.tools.function.signatures.json', + "solidity-va.tools.function.signatures.json", function (doc) { commands.listFunctionSignatures( doc || vscode.window.activeTextEditor.document, - true + true, ); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.tools.function.signatures.forWorkspace', + "solidity-va.tools.function.signatures.forWorkspace", function (doc) { commands.listFunctionSignaturesForWorkspace(false); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.tools.function.signatures.forWorkspace.json', + "solidity-va.tools.function.signatures.forWorkspace.json", function (doc) { commands.listFunctionSignaturesForWorkspace(true); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.tools.function.signatureForAstItem', + "solidity-va.tools.function.signatureForAstItem", function (item) { commands.signatureForAstItem(item); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.tools.remix.openExternal', + "solidity-va.tools.remix.openExternal", function () { vscode.env.openExternal( - vscode.Uri.parse('https://remix.ethereum.org') + vscode.Uri.parse("https://remix.ethereum.org"), ); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.uml.contract.outline', + "solidity-va.uml.contract.outline", function (doc, contractObjects) { commands.umlContractsOutline(contractObjects); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.uml.contract.export.drawio.csv', + "solidity-va.uml.contract.export.drawio.csv", function (doc, contractObjects) { commands.drawioContractsOutlineAsCSV(contractObjects); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.cockpit.topLevelContracts.refresh', + "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) + .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', + "solidity-va.cockpit.explorer.refresh", async () => { cockpit.views.explorer.refresh(); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.cockpit.flatFiles.refresh', + "solidity-va.cockpit.flatFiles.refresh", async () => { cockpit.views.flatFiles.refresh(); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.cockpit.jumpToRange', + "solidity-va.cockpit.jumpToRange", (documentUri, range) => { vscode.workspace.openTextDocument(documentUri).then((doc) => { vscode.window.showTextDocument(doc).then((editor) => { @@ -885,22 +540,22 @@ function onActivate(context) { } }); }); - } - ) + }, + ), ); context.subscriptions.push( vscode.commands.registerCommand( - 'solidity-va.cockpit.settings.toggle', + "solidity-va.cockpit.settings.toggle", async (treeItem) => { let cfg = vscode.workspace.getConfiguration( - treeItem.metadata.extension + treeItem.metadata.extension, ); let current = cfg.get(treeItem.metadata.section); await cfg.update(treeItem.metadata.section, !current); cockpit.views.settings.refresh(); - } - ) + }, + ), ); /** event setup */ @@ -913,7 +568,7 @@ function onActivate(context) { } }, null, - context.subscriptions + context.subscriptions, ); vscode.workspace.onDidChangeTextDocument( (event) => { @@ -926,7 +581,7 @@ function onActivate(context) { } }, null, - context.subscriptions + context.subscriptions, ); /***** OnSave */ @@ -935,7 +590,7 @@ function onActivate(context) { onDidSave(document); }, null, - context.subscriptions + context.subscriptions, ); /****** OnOpen */ @@ -944,7 +599,7 @@ function onActivate(context) { onDidSave(document); }, null, - context.subscriptions + context.subscriptions, ); /****** onDidChangeTextEditorSelection */ @@ -953,7 +608,7 @@ function onActivate(context) { cockpit.onDidSelectionChange(event); // let cockpit handle the event }, null, - context.subscriptions + context.subscriptions, ); context.subscriptions.push( @@ -964,10 +619,10 @@ function onActivate(context) { position, token, type, - g_workspace + g_workspace, ); }, - }) + }), ); /** experimental */ @@ -975,8 +630,8 @@ function onActivate(context) { context.subscriptions.push( vscode.languages.registerDocumentSymbolProvider( docSel, - new SolidityDocumentSymbolProvider(g_workspace) - ) + new SolidityDocumentSymbolProvider(g_workspace), + ), ); } @@ -984,15 +639,15 @@ function onActivate(context) { context.subscriptions.push( vscode.languages.registerCodeLensProvider( docSel, - new StaticLensProvider(g_workspace) - ) + new StaticLensProvider(g_workspace), + ), ); context.subscriptions.push( vscode.languages.registerCodeLensProvider( docSel, - new ParserLensProvider(g_workspace) - ) + new ParserLensProvider(g_workspace), + ), ); } @@ -1000,8 +655,8 @@ function onActivate(context) { context.subscriptions.push( vscode.languages.registerReferenceProvider( docSel, - new SolidityReferenceProvider() - ) + new SolidityReferenceProvider(), + ), ); } diff --git a/src/features/deco.js b/src/features/deco.js index d01d272..431e17f 100644 --- a/src/features/deco.js +++ b/src/features/deco.js @@ -1,582 +1,896 @@ -'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"); 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` - }, + 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' - }, + 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, +const decoStyleStateVarImmutable = vscode.window.createTextEditorDecorationType( + { + borderWidth: "1px", + borderStyle: "dotted", + overviewRulerLane: settings.extensionConfig().overviewruler.decorations + .enable + ? vscode.OverviewRulerLane.Right + : undefined, light: { - borderColor: 'DarkOrchid' + borderColor: "DarkOrchid", }, dark: { - borderColor: 'Orchid' + borderColor: "Orchid", }, -}); + }, +); const decoStyleLightGreen = vscode.window.createTextEditorDecorationType({ - borderWidth: '1px', - borderStyle: 'dotted', - light: { - borderColor: 'darkgreen' - }, - dark: { - borderColor: 'green' - }, + 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' - }, + 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' - }, + 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({ +const decoStyleBlueBoldForeground = + vscode.window.createTextEditorDecorationType({ light: { - fontWeight: 'bold', + fontWeight: "bold", }, dark: { - color: 'Chocolate' + color: "Chocolate", }, -}); - + }); var styles = { - decoStyleStateVar: decoStyleStateVar, - decoStyleStateVarImmutable: decoStyleStateVarImmutable, - decoStyleLightGreen: decoStyleLightGreen, - decoStyleLightOrange: decoStyleLightOrange, - decoStyleLightBlue: decoStyleLightBlue, - decoStyleRedLine: decoStyleRedLine, - decoStyleBookmarkGreen: undefined, - decoStyleBookmarkRed: undefined, - decoStyleExternalCall: undefined - + decoStyleStateVar: decoStyleStateVar, + decoStyleStateVarImmutable: decoStyleStateVarImmutable, + decoStyleLightGreen: decoStyleLightGreen, + decoStyleLightOrange: decoStyleLightOrange, + decoStyleLightBlue: decoStyleLightBlue, + decoStyleRedLine: decoStyleRedLine, + decoStyleBookmarkGreen: undefined, + decoStyleBookmarkRed: undefined, + decoStyleExternalCall: undefined, }; +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 "); +} -async function decorateWords(editor, words, decoStyle, commentMapper) { - if (!editor) { - return; +function handleIdentifiers( + identifiers, + document, + contract, + settings, + decorations, +) { + let highlightIdentifiers = []; + + 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]; + + 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); + } +} + +/** 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)); + } + }); +} + +async function setDecorations(editor, decorations) { + if (!editor) return; + + const decoMap = {}; + + for (const styleKey in styles) { + decoMap[styleKey] = []; + } + + for (const deco of decorations) { + decoMap[deco.decoStyle].push(deco); + } + + for (const styleKey in decoMap) { + editor.setDecorations(styles[styleKey], decoMap[styleKey]); + } } -function doDeco(editor, decoArr) { - if (!editor) { - return; +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); } - editor.setDecorations(decoStyleStateVar, decoArr); + }); + console.log("✓ decorateWords " + words); + editor.setDecorations(decoStyle, smallNumbers); } function HSLtoRGB(h, s, l) { - let r, g, b; + let r, g, b; - const rd = (a) => { - return Math.floor(Math.max(Math.min(a * 256, 255), 0)); - }; + const rd = (a) => { + return Math.floor(Math.max(Math.min(a * 256, 255), 0)); + }; - 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; - }; + 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; + }; - const q = l < 0.5 ? l * (1 + s) : l + s - l * s; - const p = 2 * l - q; + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; + const p = 2 * l - q; - r = hueToRGB(p, q, h + 1 / 3); - g = hueToRGB(p, q, h); - b = hueToRGB(p, q, h - 1 / 3); + 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)]; + return [rd(r), rd(g), rd(b)]; } function RGBtoHex(r, g, b) { - return `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`; + return `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`; } var gutterIcons = {}; - function varDecIsArray(node) { - return node && node.typeName && node.typeName.type == "ArrayTypeName"; + 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 == "UserDefinedTypeName"; } function getVariableDeclarationType(node) { - if(!node){ - return null; - } + 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.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; + if (typeof node.typeName != "undefined" && node.typeName != null) { + if (varDecIsArray(node)) { + node = node.typeName.baseTypeName; } else { - return null; + 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 semanticHighlightFunctionParameters(arrIdents) { - - if (arrIdents.length <= 0) { - return []; - } +function semanticHighlightFunctionParameters(arrIdents, decorations) { + if (arrIdents.length <= 0) { + return []; + } - let index = 0; - let colorAssign = {}; + let index = 0; + let colorAssign = {}; - let funcNode = arrIdents[0].extra.inFunction; // just take the first items ref to function - var decorations = []; + let funcNode = arrIdents[0].extra.inFunction; // just take the first items ref to function - 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] - }); + 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)) } - - - 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] - }); - - + 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], + }); + } + 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], }); - console.log("✓ semantic highlight - " + funcNode._node.name); - return decorations; + }); + console.log("✓ semantic highlight - " + funcNode._node.name); } 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"; - - [...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"); - - styles.decoStyleBookmarkRed = vscode.window.createTextEditorDecorationType({ - gutterIconPath: gutterIcons.red, - 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' - }, - /* + 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: { - textDecoration: "underline overline #FF3028", - contentText: "<--" - - } - */ - }); - styles.decoStyleBookmarkGreen = vscode.window.createTextEditorDecorationType({ - gutterIconPath: gutterIcons.green, - light: { - - //color: 'GoldenRod', - fontWeight: 'bold', - //backgroundColor: 'DarkSlateGray' + contentText: decoSuffix, + fontStyle: "normal", + color: afterColor, }, - 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.decoStyleBookmarkIssue = vscode.window.createTextEditorDecorationType({ - gutterIconPath: gutterIcons.issue, - light: { + 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"); - //color: 'GoldenRod', - fontWeight: 'bold', - //backgroundColor: 'DarkSlateGray' - }, - dark: { - - color: 'Chocolate', - //backgroundColor: 'Black', - //fontWeight: 'bold', - //textDecoration: 'underline overline #FF3028', - //borderColor: 'GoldenRod', - //borderStyle: 'solid', - //borderWidth: '0.1px' - }, - /* + styles.decoStyleBookmarkRed = vscode.window.createTextEditorDecorationType({ + gutterIconPath: gutterIcons.red, + 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.decoStyleBookmarkGreen = vscode.window.createTextEditorDecorationType({ + gutterIconPath: gutterIcons.green, + light: { + fontWeight: "bold", + }, + dark: { + color: "Chocolate", + }, + }); + styles.decoStyleBookmarkBlue = vscode.window.createTextEditorDecorationType({ + gutterIconPath: gutterIcons.blue, + light: { + fontWeight: "bold", + }, + dark: { + color: "Chocolate", + }, + }); + styles.decoStyleBookmarkIssue = vscode.window.createTextEditorDecorationType({ + gutterIconPath: gutterIcons.issue, + light: { + fontWeight: "bold", + }, + dark: { + color: "Chocolate", + }, + }); } 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 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}** ` : ""; } - 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}** ` : ''; - } - 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 - }; + if (node.hasOwnProperty("isImmutable") && node.isImmutable) { + prefix = "**IMMUTABLE** "; + decoStyle = "decoStyleStateVarImmutable"; } - 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"; - } - - 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 - }; + 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}** ` : ""; } - 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 (svar.hasOwnProperty("isImmutable") && svar.isImmutable) { + prefix = "**IMMUTABLE** "; + decoStyle = "decoStyleStateVarImmutable"; + } - 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 - }; + 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 + + "#" + + declaration.loc.start.line + + "](" + + uri + + "#" + + declaration.loc.start.line + + "))"; + knownType = getVariableDeclarationType(declaration); } - 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); - } - 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 { + 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); } -} + 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, + }; + } +} module.exports = { - init: init, - decoStyleStateVar: decoStyleStateVar, - styles: styles, - doDeco: doDeco, - decorateWords: decorateWords, - semanticHighlightFunctionParameters: semanticHighlightFunctionParameters, - CreateDecoStyle: CreateDecoStyle -}; \ No newline at end of file + init: init, + decoStyleStateVar: decoStyleStateVar, + decorateSourceUnit: decorateSourceUnit, + styles: styles, + decorateWords: decorateWords, + semanticHighlightFunctionParameters: semanticHighlightFunctionParameters, + CreateDecoStyle: CreateDecoStyle, +}; From 9a6aeb68e6ea18684787e85c9c6df6d6cb464582 Mon Sep 17 00:00:00 2001 From: Valentin Date: Thu, 5 Oct 2023 13:09:23 +0200 Subject: [PATCH 16/32] Add prettier and prettify all sources --- .vscode/launch.json | 32 +- .vscode/tasks.json | 22 +- CHANGELOG.md | 106 +- README.md | 306 +- package.json | 1092 ++--- src/features/cockpit.js | 1737 ++++---- src/features/codelens.js | 122 +- src/features/commands.js | 368 +- src/features/genericDiag.js | 248 +- src/features/hover.js | 230 +- src/features/hover/asm.json | 4002 ++++++++---------- src/features/hover/builtins.json | 807 ++-- src/features/parser/parserHelpers.js | 77 +- src/features/references.js | 157 +- src/features/symbols.js | 316 +- src/features/templates.js | 100 +- src/features/utils.js | 16 +- src/features/whatsnew/interactiveWebview.js | 386 +- src/features/whatsnew/whatsNew.js | 130 +- src/features/writer/drawio.js | 344 +- src/features/writer/plantuml.js | 242 +- src/language-configuration.json | 48 +- src/settings.js | 36 +- whats_new/index.html | 4146 ++++++++++++++++++- 24 files changed, 9455 insertions(+), 5615 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index bd7615f..359bccd 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,20 +1,16 @@ { - "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}"], + "stopOnEntry": false, + "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 8744861..16461af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Note: Don't forget to check out `preferences → Settings → Solidity Visual Developer` to customize features, look and feel. ## v0.2.0 - 💖 Happy Valentine's Days, spread some love! 💖 + - fix: includes parser performance optimizations with [solidity-workspace@v0.2.0](https://github.com/tintinweb/solidity-workspace/releases/tag/v0.2.0) (🙏 @vquelque) - update: completely refactored function signature computation - #127 - fix: performance optimizations (debounce) - #127 @@ -13,9 +14,11 @@ Note: Don't forget to check out `preferences → Settings → Solidity Visual De - fix: external function call list in cockpit view faile to resolve one-liner function declarations - #127 ## 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 @@ -24,50 +27,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 @@ -82,7 +86,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) @@ -97,7 +101,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. @@ -111,7 +114,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!) @@ -129,19 +132,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 @@ -149,57 +154,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 @@ -211,6 +225,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 @@ -219,28 +234,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) @@ -252,38 +270,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`) @@ -309,6 +330,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/package.json b/package.json index 671f08c..c48c5b8 100644 --- a/package.json +++ b/package.json @@ -1,551 +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.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" + }, + "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", - "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 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" + } + ] }, - "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", - "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" - } - ], - "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": { - "solidity-workspace": "file:../../js/solidity-workspace", - "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.1.7", + "surya": "^0.4.6" + }, + "devDependencies": { + "prettier": "^3.0.3" + } } diff --git a/src/features/cockpit.js b/src/features/cockpit.js index 471b611..fdd4cfe 100644 --- a/src/features/cockpit.js +++ b/src/features/cockpit.js @@ -1,267 +1,275 @@ -'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 = []; + 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; } - - async dataGetRoot() { - 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, - } - ); + if (this.listStyle === "flat") { + this._addPathFlat(uri); + } else { + this._addPathTree(uri); } + } - addPath(uri) { - if (uri.scheme === undefined) { - uri = vscode.Uri.file(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; - } + _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, - } - ); + } + + _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); } - - 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 +277,786 @@ 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; + 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 []; } - - 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, - }; - }); + 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; } - 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, - }; - }); - } - - - 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; + 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..."; + } - let contractObj = commands.g_workspace.sourceUnits[documentUri.fsPath]; - let knownFiles = Object.keys(commands.g_workspace.sourceUnits).filter(f => f.endsWith(".sol")); + 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"), + ); - if (!contractObj) { - console.warn("surya.ftrace: not a file: " + documentUri.fsPath); - return; - } + if (!contractObj) { + console.warn("surya.ftrace: not a file: " + documentUri.fsPath); + 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 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 (!focusSolidityElement.function) { - return; - } + if (!focusSolidityElement.function) { + return; + } - let functionName = focusSolidityElement.function._node.name; - - 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 = [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, + }; } + 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; - } - - 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; + 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) => { + 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. } 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 focusSolidityElement = contractObj.getFunctionAtLocation( + focus.line, + focus.character, + ); + if (!focusSolidityElement) { + 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 = 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 = ""; } - - 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; + obj[newKey] = 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; + 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(); } - - 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; - } - - /** 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 || []; - } - - /** 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("{**/*_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; - }, []); + 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 []; } - dataGetChildren(element) { - return element.children; - } - - /** 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]; + + 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; + } + + /** 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, c._node.loc.start.column); - 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("surya.ftrace: contract not found: " + documentUri.fsPath); + return; } -} + // data format: obj[contract][function][calls]=[target, target]; + let extcalls = focusSolidityElement.getExternalCalls().reduce((obj, c) => { + let result = sourceUnit.getFunctionAtLocation( + c._node.loc.start.line, + c._node.loc.start.column, + ); + let key = `${result.function.name}`; + let data = obj[key]; + + if (!data) { + data = []; + } + + data.push({ resource: documentUri, call: c, parent: result }); + + 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)); + 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 } - 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 - } - - 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 786b95f..a6e0801 100644 --- a/src/features/codelens.js +++ b/src/features/codelens.js @@ -1,12 +1,12 @@ -'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',}) @@ -18,8 +18,8 @@ function elemLocToRange(elem) { 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 - ) + elem.loc.start.column + name.length, + ), ); } @@ -38,9 +38,9 @@ class StaticLensProvider { config.report.enable && codeLens.push( new vscode.CodeLens(firstLine, { - command: 'solidity-va.surya.mdreport', - title: 'report', - }) + command: "solidity-va.surya.mdreport", + title: "report", + }), ); /* does not yet return values but writes to console codeLens.push( @@ -56,43 +56,43 @@ class StaticLensProvider { config.graphThis.enable && codeLens.push( new vscode.CodeLens(firstLine, { - command: 'solidity-va.surya.graph', - title: 'graph (this)', + 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', + 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', + 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', + 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', + command: "solidity-va.tools.flaterra", + title: "flatten", arguments: [document], - }) + }), ); return codeLens; } @@ -119,31 +119,31 @@ class ParserLensProvider { config.uml.enable && codeLens.push( new vscode.CodeLens(firstLine, { - command: 'solidity-va.uml.contract.outline', - title: 'uml', + 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', + 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', + 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) { @@ -152,25 +152,25 @@ class ParserLensProvider { if (annotateContractTypes.indexOf(contractObj._node.kind) >= 0) { codeLens = codeLens.concat( - this.onContractDecl(document, contractObj) + this.onContractDecl(document, contractObj), ); /** all function decls */ for (let funcObj of contractObj.functions) { codeLens = codeLens.concat( - this.onFunctionDecl(document, contractObj.name, funcObj) + this.onFunctionDecl(document, contractObj.name, funcObj), ); } - } else if (contractObj._node.kind == 'interface') { + } 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', + command: "solidity-va.uml.contract.outline", + title: "uml", arguments: [document, [item]], - }) + }), ); } } @@ -187,46 +187,46 @@ class ParserLensProvider { config.unittestStub.enable && lenses.push( new vscode.CodeLens(range, { - command: 'solidity-va.test.createTemplate', - title: 'UnitTest stub', + 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', + command: "solidity-va.surya.dependencies", + title: "dependencies", arguments: [document, item.name, []], - }) + }), ); config.uml.enable && lenses.push( new vscode.CodeLens(range, { - command: 'solidity-va.uml.contract.outline', - title: 'uml', + command: "solidity-va.uml.contract.outline", + title: "uml", arguments: [document, [item]], - }) + }), ); config.funcSigs.enable && lenses.push( new vscode.CodeLens(range, { - command: 'solidity-va.tools.function.signatureForAstItem', - title: 'funcSigs', + command: "solidity-va.tools.function.signatureForAstItem", + title: "funcSigs", arguments: [item], - }) + }), ); config.drawio.enable && lenses.push( new vscode.CodeLens(range, { - command: 'solidity-va.uml.contract.export.drawio.csv', - title: 'draw.io', + command: "solidity-va.uml.contract.export.drawio.csv", + title: "draw.io", arguments: [document, [item]], - }) + }), ); return lenses; @@ -241,20 +241,20 @@ class ParserLensProvider { config.ftrace.enable && lenses.push( new vscode.CodeLens(range, { - command: 'solidity-va.surya.ftrace', - title: 'ftrace', - arguments: [document, contractName, item._node.name, 'all'], - }) + 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', + command: "solidity-va.tools.function.signatureForAstItem", + title: "funcSig", arguments: [item], - }) + }), ); return lenses; diff --git a/src/features/commands.js b/src/features/commands.js index 7b13b76..48f574f 100644 --- a/src/features/commands.js +++ b/src/features/commands.js @@ -1,4 +1,4 @@ -'use strict'; +"use strict"; /** * @author github.com/tintinweb * @license GPLv3 @@ -6,66 +6,66 @@ * * */ -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 mod_templates = require("./templates"); +const mod_utils = require("./utils"); -const { DrawIoCsvWriter } = require('./writer/drawio'); -const { PlantumlWriter } = require('./writer/plantuml'); +const { DrawIoCsvWriter } = require("./writer/drawio"); +const { PlantumlWriter } = require("./writer/plantuml"); -const surya = require('surya'); +const surya = require("surya"); const suryaDefaultColorSchemeDark = { digraph: { - bgcolor: '#2e3e56', + bgcolor: "#2e3e56", nodeAttribs: { - style: 'filled', - fillcolor: '#edad56', - color: '#edad56', - penwidth: '3', + style: "filled", + fillcolor: "#edad56", + color: "#edad56", + penwidth: "3", }, edgeAttribs: { - color: '#fcfcfc', - penwidth: '2', - fontname: 'helvetica Neue Ultra Light', + color: "#fcfcfc", + penwidth: "2", + fontname: "helvetica Neue Ultra Light", }, }, visibility: { isFilled: true, - public: '#FF9797', - external: '#ffbdb9', - private: '#edad56', - internal: '#f2c383', + public: "#FF9797", + external: "#ffbdb9", + private: "#edad56", + internal: "#f2c383", }, nodeType: { isFilled: false, - shape: 'doubleoctagon', - modifier: '#1bc6a6', - payable: 'brown', + shape: "doubleoctagon", + modifier: "#1bc6a6", + payable: "brown", }, call: { - default: 'white', - regular: '#1bc6a6', - this: '#80e097', + default: "white", + regular: "#1bc6a6", + this: "#80e097", }, contract: { defined: { - bgcolor: '#445773', - color: '#445773', - fontcolor: '#f0f0f0', - style: 'rounded', + bgcolor: "#445773", + color: "#445773", + fontcolor: "#f0f0f0", + style: "rounded", }, undefined: { - bgcolor: '#3b4b63', - color: '#e8726d', - fontcolor: '#f0f0f0', - style: 'rounded,dashed', + bgcolor: "#3b4b63", + color: "#e8726d", + fontcolor: "#f0f0f0", + style: "rounded,dashed", }, }, }; @@ -74,26 +74,26 @@ function runCommand(cmd, args, env, cwd, stdin) { cwd = cwd || vscode.workspace.rootPath; return new Promise((resolve, reject) => { - console.log(`running command: ${cmd} ${args.join(' ')}`); + 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) { + p.stdout.on("data", function (data) { if (stdin) { - p.stdin.setEncoding('utf-8'); + p.stdin.setEncoding("utf-8"); p.stdin.write(stdin); p.stdin.end(); } }); if (err === null || err.code === 0) { - console.log('success'); + console.log("success"); return resolve(err); } err.stderr = stderr; return reject(err); - } + }, ); }); } @@ -106,9 +106,9 @@ class Commands { _checkIsSolidity(document) { if (!document || document.languageId != settings.languageId) { vscode.window.showErrorMessage( - `[Solidity VA] not a solidity source file ${vscode.window.activeTextEditor.document.uri.fsPath}` + `[Solidity VA] not a solidity source file ${vscode.window.activeTextEditor.document.uri.fsPath}`, ); - throw new Error('not a solidity file'); + throw new Error("not a solidity file"); } } @@ -116,44 +116,44 @@ class Commands { this._checkIsSolidity(document); let content; - if (settings.extensionConfig().test.defaultUnittestTemplate === 'hardhat') { + if (settings.extensionConfig().test.defaultUnittestTemplate === "hardhat") { content = mod_templates.generateHardhatUnittestStubForContract( document, this.g_parser, - contractName + contractName, ); } else { content = mod_templates.generateUnittestStubForContract( document, this.g_parser, - contractName + contractName, ); } vscode.workspace - .openTextDocument({ content: content, language: 'javascript' }) + .openTextDocument({ content: content, language: "javascript" }) .then((doc) => - vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) + 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'); + throw new Error("not a file or list item"); } let ret; let files = []; - if (documentOrListItems.hasOwnProperty('children')) { + if (documentOrListItems.hasOwnProperty("children")) { //hack ;) documentOrListItems = [documentOrListItems]; //allow non array calls } if (Array.isArray(documentOrListItems)) { for (let documentOrListItem of documentOrListItems) { - if (documentOrListItem.hasOwnProperty('children')) { + if (documentOrListItem.hasOwnProperty("children")) { // is a list item -> item.resource.fsPath if (!!path.extname(documentOrListItem.resource.fsPath)) { //file @@ -164,13 +164,13 @@ class Commands { .findFiles( `${documentOrListItem.path}/**/*.sol`, settings.DEFAULT_FINDFILES_EXCLUDES, - 500 + 500, ) .then((uris) => { files = files.concat( uris.map(function (uri) { return uri.fsPath; - }) + }), ); }); } @@ -181,10 +181,10 @@ class Commands { this._checkIsSolidity(documentOrListItems); // throws if ( - settings.extensionConfig().tools.surya.input.contracts == 'workspace' + settings.extensionConfig().tools.surya.input.contracts == "workspace" ) { await vscode.workspace - .findFiles('**/*.sol', settings.DEFAULT_FINDFILES_EXCLUDES, 500) + .findFiles("**/*.sol", settings.DEFAULT_FINDFILES_EXCLUDES, 500) .then((uris) => { files = uris.map(function (uri) { return uri.fsPath; @@ -195,22 +195,22 @@ class Commands { 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 🥲 + ].filter((p) => fs.existsSync(p)); //only feed existing files into surya or it might die 🥲 } } switch (command) { - case 'describe': + case "describe": ret = surya.describe(files, {}, true); vscode.workspace - .openTextDocument({ content: ret, language: 'markdown' }) + .openTextDocument({ content: ret, language: "markdown" }) .then((doc) => - vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), ); break; - case 'graphSimple': - case 'graph': - if (command == 'graphSimple') { + case "graphSimple": + case "graph": + if (command == "graphSimple") { ret = surya.graphSimple(args || files, { colorScheme: suryaDefaultColorSchemeDark, }); @@ -221,11 +221,11 @@ class Commands { } //solidity-va.preview.render.markdown vscode.workspace - .openTextDocument({ content: ret, language: 'dot' }) + .openTextDocument({ content: ret, language: "dot" }) .then((doc) => { if (settings.extensionConfig().preview.dot) { vscode.commands - .executeCommand('graphviz-interactive-preview.preview.beside', { + .executeCommand("graphviz-interactive-preview.preview.beside", { document: doc, content: ret, callback: null, @@ -233,7 +233,7 @@ class Commands { }) .catch((error) => { vscode.commands - .executeCommand('interactive-graphviz.preview.beside', { + .executeCommand("interactive-graphviz.preview.beside", { document: doc, content: ret, callback: null, @@ -241,14 +241,14 @@ class Commands { }) //TODO: remove this in future version. only for transition to new command .catch((error) => { vscode.commands - .executeCommand('graphviz.previewToSide', doc.uri) + .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 + .executeCommand("graphviz.showPreview", editor) // creates new pane .catch((error) => { //command not available - do nothing }); @@ -265,14 +265,14 @@ class Commands { .then(doc => vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside)) */ break; - case 'inheritance': + case "inheritance": ret = surya.inheritance(files, { draggable: false }); vscode.workspace - .openTextDocument({ content: ret, language: 'dot' }) + .openTextDocument({ content: ret, language: "dot" }) .then((doc) => { if (settings.extensionConfig().preview.dot) { vscode.commands - .executeCommand('graphviz-interactive-preview.preview.beside', { + .executeCommand("graphviz-interactive-preview.preview.beside", { document: doc, content: ret, callback: null, @@ -280,7 +280,7 @@ class Commands { }) .catch((error) => { vscode.commands - .executeCommand('interactive-graphviz.preview.beside', { + .executeCommand("interactive-graphviz.preview.beside", { document: doc, content: ret, callback: null, @@ -288,14 +288,14 @@ class Commands { }) //TODO: remove this in future version. only for transition to new command .catch((error) => { vscode.commands - .executeCommand('graphviz.previewToSide', doc.uri) + .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 + .executeCommand("graphviz.showPreview", editor) // creates new pane .catch((error) => { //command not available - do nothing }); @@ -313,15 +313,15 @@ class Commands { createWebViewBesides('imgPreview','imgPreview',draggable) */ break; - case 'parse': + case "parse": ret = surya.parse(documentOrListItems.uri.fsPath); vscode.workspace - .openTextDocument({ content: ret, language: 'markdown' }) + .openTextDocument({ content: ret, language: "markdown" }) .then((doc) => - vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), ); break; - case 'dependencies': + case "dependencies": ret = surya.dependencies(files, args[0]); let outTxt = []; @@ -330,7 +330,7 @@ class Commands { outTxt.push(ret[0]); if (ret.length < 2) { - outTxt = ['No Dependencies Found']; + outTxt = ["No Dependencies Found"]; } else { ret.shift(); const reducer = (accumulator, currentValue) => @@ -340,40 +340,40 @@ class Commands { vscode.workspace .openTextDocument({ - content: outTxt.join('\n'), - language: 'markdown', + content: outTxt.join("\n"), + language: "markdown", }) .then((doc) => - vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), ); } break; - case 'ftrace': + case "ftrace": // contract::func, all, files if (args[1] === null) { - args[1] = ''; - } else if (args[1] === '') { - args[1] = ''; + args[1] = ""; + } else if (args[1] === "") { + args[1] = ""; } try { ret = surya.ftrace( - args[0] + '::' + args[1], - args[2] || 'all', + args[0] + "::" + args[1], + args[2] || "all", files, {}, - true + true, ); vscode.workspace - .openTextDocument({ content: ret, language: 'markdown' }) + .openTextDocument({ content: ret, language: "markdown" }) .then((doc) => - vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), ); } catch (e) { console.error(e); } break; - case 'mdreport': + case "mdreport": ret = surya.mdreport(files, { negModifiers: settings.extensionConfig().tools.surya.option.negModifiers, @@ -382,13 +382,13 @@ class Commands { return; } vscode.workspace - .openTextDocument({ content: ret, language: 'markdown' }) + .openTextDocument({ content: ret, language: "markdown" }) .then((doc) => { if (settings.extensionConfig().preview.markdown) { vscode.commands .executeCommand( - 'markdown-preview-enhanced.openPreview', - doc.uri + "markdown-preview-enhanced.openPreview", + doc.uri, ) .catch((error) => { //command does not exist @@ -396,7 +396,7 @@ class Commands { .showTextDocument(doc, vscode.ViewColumn.Beside) .then((editor) => { vscode.commands - .executeCommand('markdown.extension.togglePreview') + .executeCommand("markdown.extension.togglePreview") .catch((error) => { //command does not exist }); @@ -423,13 +423,13 @@ class Commands { : [workspaceRelativeBaseDirs]; let searchFileString = - '{' + + "{" + workspaceRelativeBaseDirs .map((d) => - d === undefined ? '**/*.sol' : d + path.sep + '**/*.sol' + d === undefined ? "**/*.sol" : d + path.sep + "**/*.sol", ) - .join(',') + - '}'; + .join(",") + + "}"; await vscode.workspace .findFiles(searchFileString, settings.DEFAULT_FINDFILES_EXCLUDES, 500) @@ -443,7 +443,7 @@ class Commands { for (let contractName in sourceUnit.contracts) { if ( - sourceUnit.contracts[contractName]._node.kind == 'interface' + sourceUnit.contracts[contractName]._node.kind == "interface" ) { //ignore interface contracts continue; @@ -452,7 +452,7 @@ class Commands { sourceUnit.contracts[contractName].dependencies; contractToFile[contractName] = solfile; } - } catch (e) { } + } catch (e) {} }); }); } else { @@ -460,7 +460,7 @@ class Commands { //files set: only take these sourceUnits await this.g_workspace .getAllContracts() - .filter((c) => c._node.kind != 'interface' && c._node.kind != 'library') + .filter((c) => c._node.kind != "interface" && c._node.kind != "library") .forEach((c) => { dependencies[c.name] = c.dependencies; }); @@ -482,7 +482,7 @@ class Commands { async findTopLevelContracts(files, scanfiles) { let topLevelContracts = await this._findTopLevelContracts(files, scanfiles); - let topLevelContractsText = Object.keys(topLevelContracts).join('\n'); + let topLevelContractsText = Object.keys(topLevelContracts).join("\n"); /* for (var name in topLevelContracts) { topLevelContractsText += name + ' (' + topLevelContracts[name]+')\n'; @@ -495,22 +495,22 @@ Top Level Contracts ${topLevelContractsText}`; vscode.workspace - .openTextDocument({ content: content, language: 'markdown' }) + .openTextDocument({ content: content, language: "markdown" }) .then((doc) => - vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), ); } async solidityFlattener(files, callback, showErrors) { switch (settings.extensionConfig().flatten.mode) { - case 'truffle': + case "truffle": vscode.extensions - .getExtension('tintinweb.vscode-solidity-flattener') + .getExtension("tintinweb.vscode-solidity-flattener") .activate() .then( (active) => { vscode.commands - .executeCommand('vscode-solidity-flattener.flatten', { + .executeCommand("vscode-solidity-flattener.flatten", { files: files, callback: callback, showErrors: showErrors, @@ -518,16 +518,16 @@ ${topLevelContractsText}`; .catch((error) => { // command not available vscode.window.showWarningMessage( - 'Error running `tintinweb.vscode-solidity-flattener`. Please make sure the extension is installed.\n' + - error + "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}` + `Solidity Auditor: Failed to activate "tintinweb.vscode-solidity-flattener". Make sure the extension is installed from the marketplace. Details: ${err}`, ); - } + }, ); break; default: @@ -549,9 +549,9 @@ ${topLevelContractsText}`; callback(uri.fsPath, undefined, flat); } else { vscode.workspace - .openTextDocument({ content: flat, language: 'solidity' }) + .openTextDocument({ content: flat, language: "solidity" }) .then((doc) => - vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), ); } } catch (e) { @@ -563,16 +563,16 @@ ${topLevelContractsText}`; async flaterra(documentOrUri, noTryInstall) { let docUri = documentOrUri; - if (documentOrUri.hasOwnProperty('uri')) { + if (documentOrUri.hasOwnProperty("uri")) { this._checkIsSolidity(documentOrUri); docUri = documentOrUri.uri; } - let cmd = 'python3'; + let cmd = "python3"; let args = [ - '-m', - 'flaterra', - '--contract', + "-m", + "flaterra", + "--contract", vscode.workspace.asRelativePath(docUri), ]; @@ -582,47 +582,47 @@ ${topLevelContractsText}`; vscode.window.showInformationMessage( `Contract flattened: ${path.basename( docUri.fsPath, - '.sol' - )}_flat.sol` + ".sol", + )}_flat.sol`, ); }, (err) => { - if (err.code === 'ENOENT') { + if (err.code === "ENOENT") { vscode.window.showErrorMessage( - "'`flaterra` failed with error: unable to execute python3" + "'`flaterra` failed with error: unable to execute python3", ); - } else if (err.stderr.indexOf(': No module named flaterra') >= 0) { + } 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' + "Contract Flattener `flaterra` is not installed.\n run `pip3 install flaterra --user` to install? ", + "Install", ) .then((selection) => { - if (selection == 'Install') { + if (selection == "Install") { runCommand( - 'pip3', - ['install', 'flaterra', '--user'], + "pip3", + ["install", "flaterra", "--user"], undefined, undefined, - 'y\n' + "y\n", ) .then( (success) => { vscode.window.showInformationMessage( - 'Successfully installed flaterra.' + "Successfully installed flaterra.", ); this.flaterra(documentOrUri, true); }, (error) => { vscode.window.showErrorMessage( - 'Failed to install flaterra.' + "Failed to install flaterra.", ); - } + }, ) .catch((err) => { vscode.window.showErrorMessage( - 'Failed to install flaterra. ' + err + "Failed to install flaterra. " + err, ); }); } else { @@ -632,22 +632,22 @@ ${topLevelContractsText}`; } } else { vscode.window - .showErrorMessage('`flaterra` failed with: ' + err) + .showErrorMessage("`flaterra` failed with: " + err) .then((selection) => { console.log(selection); }); } - } + }, ) .catch((err) => { - console.log('runcommand threw exception: ' + err); + console.log("runcommand threw exception: " + err); }); } async flattenCandidates(candidates) { // takes object key=contractName value=fsPath let topLevelContracts = candidates || (await this._findTopLevelContracts()); - let content = ''; + let content = ""; this.solidityFlattener( Object.values(topLevelContracts), @@ -655,40 +655,41 @@ ${topLevelContractsText}`; let outpath = path.parse(filepath); fs.writeFile( - path.join(outpath.dir, 'flat_' + outpath.base), + 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) + path.join(outpath.dir, "flat_" + outpath.base), ); - content += `${!fs.existsSync(outpath_flat.fsPath) ? '[ERR] ' : '' - }${name} => ${outpath_flat} \n`; + content += `${ + !fs.existsSync(outpath_flat.fsPath) ? "[ERR] " : "" + }${name} => ${outpath_flat} \n`; } vscode.workspace - .openTextDocument({ content: content, language: 'markdown' }) + .openTextDocument({ content: content, language: "markdown" }) .then((doc) => - vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) + 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); - }); + 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) { @@ -706,21 +707,22 @@ ${topLevelContractsText}`; }); 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); - + const signatures = await this._signatureForAstItem( + this.g_workspace.getAllContracts(), + ); + await this.revealSignatures(signatures, asJson ? "json" : undefined); } - async signatureForAstItem(items){ + 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 + items = [items]; //arrayify } for (let item of items) { try { @@ -732,14 +734,14 @@ ${topLevelContractsText}`; return results; } - async revealSignatures(signatures, format){ - format = format || 'markdown'; + async revealSignatures(signatures, format) { + format = format || "markdown"; let errs = []; const res = {}; for (const sig of signatures) { - if (sig.hasOwnProperty('err')) { + if (sig.hasOwnProperty("err")) { errs.push(sig.err); continue; //skip errors } @@ -753,36 +755,40 @@ ${topLevelContractsText}`; let content; switch (format) { - case 'json': + 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)); + { + 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'; + "| Function Name | Sighash | Function Signature | \n | ------------ | ------------ | ------------ |\n"; content = header + signatures .map((r) => `| ${r.name} | ${r.sighash} | ${r.signature} |`) - .join('\n'); + .join("\n"); - const collisions = Object.values(res).filter(v => v.size > 1); + 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"); + content += collisions.map((s) => [...s]).join("\n"); } if (errs.length) { content += "\n\n"; - content += - "🐞 Errors \n========================\n"; - content += [...new Set(errs)].join('\n'); + content += "🐞 Errors \n========================\n"; + content += [...new Set(errs)].join("\n"); } } @@ -792,7 +798,7 @@ ${topLevelContractsText}`; vscode.window.showTextDocument(doc, { viewColumn: vscode.ViewColumn.Beside, preview: true, - }) + }), ); } @@ -801,9 +807,9 @@ ${topLevelContractsText}`; const content = writer.export(contractObj); vscode.workspace - .openTextDocument({ content: content, language: 'csv' }) + .openTextDocument({ content: content, language: "csv" }) .then((doc) => - vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside) + vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside), ); } @@ -812,29 +818,29 @@ ${topLevelContractsText}`; const content = writer.export(contractObjects); vscode.workspace - .openTextDocument({ content: content, language: 'plantuml' }) + .openTextDocument({ content: content, language: "plantuml" }) .then((doc) => vscode.window .showTextDocument(doc, vscode.ViewColumn.Beside) .then((editor) => { vscode.extensions - .getExtension('jebbs.plantuml') + .getExtension("jebbs.plantuml") .activate() .then( (active) => { vscode.commands - .executeCommand('plantuml.preview') + .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}` + `Solidity Auditor: Failed to activate "jebbs.plantuml". Make sure the extension is installed from the marketplace. Details: ${err}`, ); - } + }, ); - }) + }), ); } } 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 e859c95..4a7731e 100644 --- a/src/features/symbols.js +++ b/src/features/symbols.js @@ -1,4 +1,4 @@ -'use strict'; +"use strict"; /** * @author github.com/tintinweb * @license GPLv3 @@ -6,8 +6,8 @@ * * */ -const vscode = require('vscode'); -const settings = require('../settings.js'); +const vscode = require("vscode"); +const settings = require("../settings.js"); function getFakeNode(name, line) { return { @@ -27,80 +27,80 @@ function getFakeNode(name, line) { } 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 ''; + if (typeof v == "undefined") return ""; return v; } function getVisibilityToIcon(state) { let v = visibilityToIcon[state]; - if (typeof v == 'undefined') return ''; + 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 : '', + 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' + typeof node.length != "undefined" ? node.loc.end.column + node.length - : node.loc.end.column + : 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' + typeof node.length != "undefined" ? node.loc.end.column + node.length - : node.loc.end.column - ) + : node.loc.end.column, + ), ); } function varDecIsArray(node) { - return node.typeName.type == 'ArrayTypeName'; + return node.typeName.type == "ArrayTypeName"; } function varDecIsUserDefined(node) { - return node.typeName.type == 'UserDefinedTypeName'; + return node.typeName.type == "UserDefinedTypeName"; } function getVariableDeclarationType(node) { - if (typeof node.typeName != 'undefined' && node.typeName != null) { + if (typeof node.typeName != "undefined" && node.typeName != null) { if (varDecIsArray(node)) { node = node.typeName.baseTypeName; } else node = node.typeName; } - if (node.type == 'ElementaryTypeName') { + if (node.type == "ElementaryTypeName") { return node.name; - } else if (node.type == 'UserDefinedTypeName') { + } else if (node.type == "UserDefinedTypeName") { return node.namePath; - } else if (node.type == 'Mapping') { + } else if (node.type == "Mapping") { node.namePath = - 'mapping( ' + + "mapping( " + getVariableDeclarationType(node.keyType) + - '=>' + + "=>" + getVariableDeclarationType(node.valueType) + - ' )'; + " )"; return node.namePath; } else { return null; @@ -126,45 +126,45 @@ function getVariableDeclarationTypeAsSymbolKind(node, _default) { let solidityType = getVariableDeclarationType(node); if (!solidityType) return _default; - if (solidityType.startsWith('uint') || solidityType.startsWith('int')) { + if (solidityType.startsWith("uint") || solidityType.startsWith("int")) { return varDecToSymbolType.uint; - } else if (solidityType.startsWith('bytes')) { + } else if (solidityType.startsWith("bytes")) { return varDecToSymbolType.bytes; } let kind = varDecToSymbolType[solidityType]; - return typeof kind != 'undefined' ? kind : _default; + return typeof kind != "undefined" ? kind : _default; } function getSymbolKindForDeclaration(node) { - let astnode = typeof node._node != 'undefined' ? node._node : 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: '', + prefix: "", + suffix: "", + name: typeof astnode.name != "undefined" ? astnode.name : "", + details: "", }; switch (astnode.type) { - case 'ModifierInvocation': - case 'ModifierDefinition': + case "ModifierInvocation": + case "ModifierDefinition": result.symbol = vscode.SymbolKind.Method; - result.prefix += 'Ⓜ '; + result.prefix += "Ⓜ "; if (settings.extensionConfig().outline.decorations) { result.prefix += getVisibilityToIcon(astnode.visibility); result.prefix += getStateMutabilityToIcon(astnode.stateMutability); } break; - case 'EventDefinition': + case "EventDefinition": result.symbol = vscode.SymbolKind.Event; break; - case 'FunctionDefinition': + case "FunctionDefinition": if (astnode.isConstructor) { result.symbol = vscode.SymbolKind.Constructor; - result.name = '⚜ __constructor__ ' + (result.name ? result.name : ''); + result.name = "⚜ __constructor__ " + (result.name ? result.name : ""); } else { result.symbol = vscode.SymbolKind.Function; } @@ -174,30 +174,30 @@ function getSymbolKindForDeclaration(node) { } if (settings.extensionConfig().outline.extras) { - (result.suffix += ' ( '), - (result.suffix += ' complex: ' + node.complexity); - result.suffix += ' state: ' + (node.accesses_svar ? '☑' : '☐'); - result.suffix += ' )'; + (result.suffix += " ( "), + (result.suffix += " complex: " + node.complexity); + result.suffix += " state: " + (node.accesses_svar ? "☑" : "☐"); + result.suffix += " )"; } break; - case 'EnumDefinition': + case "EnumDefinition": result.symbol = vscode.SymbolKind.Enum; break; - case 'StructDefinition': + case "StructDefinition": result.symbol = vscode.SymbolKind.Struct; break; - case 'VariableDeclaration': + case "VariableDeclaration": if (settings.extensionConfig().outline.var.storage_annotations) { - if (astnode.storageLocation == 'memory') { - result.prefix += '💾'; + if (astnode.storageLocation == "memory") { + result.prefix += "💾"; result.details += astnode.storageLocation; - } else if (astnode.storageLocation == 'storage') { - result.prefix += '💽'; + } else if (astnode.storageLocation == "storage") { + result.prefix += "💽"; result.details += astnode.storageLocation; } } if (varDecIsArray(astnode)) { - result.name += '[]'; + result.name += "[]"; } if (astnode.isDeclaredConst) { @@ -208,61 +208,61 @@ function getSymbolKindForDeclaration(node) { result.symbol = getVariableDeclarationTypeAsSymbolKind( astnode, - vscode.SymbolKind.Variable + vscode.SymbolKind.Variable, ); break; - case 'Parameter': + case "Parameter": if (settings.extensionConfig().outline.var.storage_annotations) { - if (astnode.storageLocation == 'memory') { - result.prefix += '💾'; + if (astnode.storageLocation == "memory") { + result.prefix += "💾"; result.details += astnode.storageLocation; - } else if (astnode.storageLocation == 'storage') { - result.prefix += '💽'; + } else if (astnode.storageLocation == "storage") { + result.prefix += "💽"; result.details += astnode.storageLocation; } } if (varDecIsArray(astnode)) { - result.name += '[]'; + result.name += "[]"; } result.symbol = vscode.SymbolKind.TypeParameter; // lets misuse this kind for params break; - case 'ContractDefinition': - if (astnode.kind == 'interface') { + case "ContractDefinition": + if (astnode.kind == "interface") { result.symbol = vscode.SymbolKind.Interface; - } else if (astnode.kind == 'library') { + } else if (astnode.kind == "library") { result.symbol = vscode.SymbolKind.Class; - result.prefix += '📚'; + result.prefix += "📚"; } else { result.symbol = vscode.SymbolKind.Class; } break; - case 'AssemblyFunctionDefinition': + case "AssemblyFunctionDefinition": result.symbol = vscode.SymbolKind.Function; break; default: - console.error('<-----'); + console.error("<-----"); } if (result.prefix) { - result.prefix = result.prefix + ' '; //add space + result.prefix = result.prefix + " "; //add space } return result; } function getAstValueForExpression(astnode) { switch (astnode.type) { - case 'NumberLiteral': + case "NumberLiteral": return `${astnode.number}${ - astnode.subdenominator ? astnode.subdenominator : '' + astnode.subdenominator ? astnode.subdenominator : "" }`; - case 'BooleanLiteral': - return astnode.value ? 'true' : 'false'; - case 'StringLiteral': - case 'HexLiteral': - case 'HexNumber': - case 'DecimalNumber': + case "BooleanLiteral": + return astnode.value ? "true" : "false"; + case "StringLiteral": + case "HexLiteral": + case "HexNumber": + case "DecimalNumber": return astnode.value; default: - return ''; + return ""; } } @@ -272,18 +272,17 @@ class SolidityDocumentSymbolProvider { } provideDocumentSymbols(document, token) { - console.log('preparing symbols...'); + console.log("preparing symbols..."); return new Promise((resolve, reject) => { return this.g_workspace .getSourceUnitByPath(document.fileName) .then((insights) => { - var symbols = []; console.log(`✓ inspect ${insights.filePath}`); - console.log('--- preparing symbols for: ' + document.fileName); + console.log("--- preparing symbols for: " + document.fileName); if (token.isCancellationRequested) { reject(token); @@ -295,10 +294,10 @@ class SolidityDocumentSymbolProvider { if (settings.extensionConfig().outline.pragmas.show) { topLevelNode = astNodeAsDocumentSymbol( document, - getFakeNode('pragma', 1), + getFakeNode("pragma", 1), vscode.SymbolKind.Namespace, - 'pragma', - '... (' + insights.pragmas.length + ')' + "pragma", + "... (" + insights.pragmas.length + ")", ); symbols.push(topLevelNode); insights.pragmas.forEach(function (item) { @@ -307,20 +306,20 @@ class SolidityDocumentSymbolProvider { document, item, vscode.SymbolKind.Namespace, - item.name + ' → ' + item.value - ) + item.name + " → " + item.value, + ), ); }); - console.log('✓ pragmas '); + console.log("✓ pragmas "); } if (settings.extensionConfig().outline.imports.show) { topLevelNode = astNodeAsDocumentSymbol( document, - getFakeNode('imports', 1), + getFakeNode("imports", 1), vscode.SymbolKind.Namespace, - 'imports', - '... (' + insights.imports.length + ')' + "imports", + "... (" + insights.imports.length + ")", ); symbols.push(topLevelNode); insights.imports.forEach(function (item) { @@ -329,17 +328,17 @@ class SolidityDocumentSymbolProvider { document, item, vscode.SymbolKind.File, - item.path - ) + item.path, + ), ); }); - console.log('✓ imports '); + console.log("✓ imports "); } for (var contractName in insights.contracts) { let symbolAnnotation = getSymbolKindForDeclaration( - insights.contracts[contractName] + insights.contracts[contractName], ); topLevelNode = astNodeAsDocumentSymbol( document, @@ -347,27 +346,27 @@ class SolidityDocumentSymbolProvider { symbolAnnotation.symbol, symbolAnnotation.prefix + symbolAnnotation.name + - symbolAnnotation.suffix + symbolAnnotation.suffix, ); symbols.push(topLevelNode); /** the document */ - console.log('✓ contracts ' + contractName); + 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 - ) + vscode.SymbolKind.Constructor, + ), ); } - console.log('✓ constructor'); + console.log("✓ constructor"); /** stateVars */ for (var svar in insights.contracts[contractName].stateVars) { let symbolAnnotation = getSymbolKindForDeclaration( - insights.contracts[contractName].stateVars[svar] + insights.contracts[contractName].stateVars[svar], ); topLevelNode.children.push( @@ -378,32 +377,32 @@ class SolidityDocumentSymbolProvider { symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details - ) + symbolAnnotation.details, + ), ); } - console.log('✓ statevars'); + console.log("✓ statevars"); for (let name in insights.contracts[contractName].enums) { topLevelNode.children.push( astNodeAsDocumentSymbol( document, insights.contracts[contractName].enums[name], - vscode.SymbolKind.Enum - ) + vscode.SymbolKind.Enum, + ), ); } - console.log('✓ enums'); + console.log("✓ enums"); for (let name in insights.contracts[contractName].structs) { topLevelNode.children.push( astNodeAsDocumentSymbol( document, insights.contracts[contractName].structs[name], - vscode.SymbolKind.Struct - ) + vscode.SymbolKind.Struct, + ), ); } - console.log('✓ structs'); + console.log("✓ structs"); var functionLevelNode; /** functions - may include constructor / fallback */ for (let funcObj of insights.contracts[contractName].functions) { @@ -415,7 +414,7 @@ class SolidityDocumentSymbolProvider { symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details + symbolAnnotation.details, ); topLevelNode.children.push(functionLevelNode); @@ -425,10 +424,10 @@ class SolidityDocumentSymbolProvider { if (numModifiers !== 0) { let modifiersLevelNode = astNodeAsDocumentSymbol( document, - getFakeNode('modifiers', 1), + getFakeNode("modifiers", 1), vscode.SymbolKind.Namespace, - 'modifiers', - '... (' + numModifiers + ')' + "modifiers", + "... (" + numModifiers + ")", ); functionLevelNode.children.push(modifiersLevelNode); // add modifiers @@ -445,23 +444,23 @@ class SolidityDocumentSymbolProvider { symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details - ) + symbolAnnotation.details, + ), ); } } // add fake assembly functions list to outline let numAssemblyFuncDefs = Object.keys( - funcObj.assemblyFunctions + funcObj.assemblyFunctions, ).length; if (numAssemblyFuncDefs !== 0) { let assemblyLevelNode = astNodeAsDocumentSymbol( document, - getFakeNode('assembly..', 1), + getFakeNode("assembly..", 1), vscode.SymbolKind.Namespace, - 'assembly', - '... (' + numAssemblyFuncDefs + ')' + "assembly", + "... (" + numAssemblyFuncDefs + ")", ); functionLevelNode.children.push(assemblyLevelNode); @@ -479,8 +478,8 @@ class SolidityDocumentSymbolProvider { symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details - ) + symbolAnnotation.details, + ), ); } } @@ -488,7 +487,7 @@ class SolidityDocumentSymbolProvider { for (let declaration in funcObj.declarations) { let vardec = funcObj.declarations[declaration]; - if (declaration == 'null') continue; + if (declaration == "null") continue; let symbolAnnotation = getSymbolKindForDeclaration(vardec); @@ -500,18 +499,18 @@ class SolidityDocumentSymbolProvider { symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details - ) + symbolAnnotation.details, + ), ); } } - console.log('✓ functions'); + console.log("✓ functions"); /** modifiers */ for (let functionName in insights.contracts[contractName] .modifiers) { let symbolAnnotation = getSymbolKindForDeclaration( - insights.contracts[contractName].modifiers[functionName] + insights.contracts[contractName].modifiers[functionName], ); functionLevelNode = astNodeAsDocumentSymbol( document, @@ -520,7 +519,7 @@ class SolidityDocumentSymbolProvider { symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details + symbolAnnotation.details, ); topLevelNode.children.push(functionLevelNode); @@ -530,7 +529,7 @@ class SolidityDocumentSymbolProvider { let vardec = insights.contracts[contractName].modifiers[functionName] .declarations[declaration]; - if (declaration == 'null') continue; + if (declaration == "null") continue; let symbolAnnotation = getSymbolKindForDeclaration(vardec); functionLevelNode.children.push( astNodeAsDocumentSymbol( @@ -540,12 +539,12 @@ class SolidityDocumentSymbolProvider { symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details - ) + symbolAnnotation.details, + ), ); } } - console.log('✓ modifiers'); + console.log("✓ modifiers"); /** events */ for (let eventObj of insights.contracts[contractName].events) { let symbolAnnotation = getSymbolKindForDeclaration(eventObj); @@ -556,7 +555,7 @@ class SolidityDocumentSymbolProvider { symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details + symbolAnnotation.details, ); topLevelNode.children.push(functionLevelNode); @@ -564,7 +563,7 @@ class SolidityDocumentSymbolProvider { //get all declarations in function for (let declaration in eventObj.declarations) { let vardec = eventObj.declarations[declaration]; - if (declaration == 'null') continue; + if (declaration == "null") continue; let symbolAnnotation = getSymbolKindForDeclaration(vardec); functionLevelNode.children.push( astNodeAsDocumentSymbol( @@ -574,18 +573,18 @@ class SolidityDocumentSymbolProvider { symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details - ) + symbolAnnotation.details, + ), ); } } - console.log('✓ events'); + console.log("✓ events"); /** functions - may include constructor / fallback */ if (settings.extensionConfig().outline.inheritance.show) { var inheritedLevelNode = astNodeAsDocumentSymbol( document, - getFakeNode('↖ ...', 1), - vscode.SymbolKind.Namespace + getFakeNode("↖ ...", 1), + vscode.SymbolKind.Namespace, ); topLevelNode.children.push(inheritedLevelNode); @@ -601,7 +600,7 @@ class SolidityDocumentSymbolProvider { //skip functions, modifiers, events of local contract if ( typeof insights.contracts[contractName].names[name] != - 'undefined' + "undefined" ) continue; @@ -609,11 +608,11 @@ class SolidityDocumentSymbolProvider { if (!_contract) { let _contract = this.g_workspace.findContractsByNameSync( - inheritedFromContractName + inheritedFromContractName, ); if (_contract.length == 0) { console.warn( - `symbol/inheritance: contract ${inheritedFromContractName} not found :/. skipping.` + `symbol/inheritance: contract ${inheritedFromContractName} not found :/. skipping.`, ); continue; } @@ -622,14 +621,14 @@ class SolidityDocumentSymbolProvider { } let symbolAnnotation; - if (typeof _contract == 'undefined') { + if (typeof _contract == "undefined") { //contract not found :/ symbolAnnotation = { symbol: vscode.SymbolKind.Class, name: inheritedFromContractName, - prefix: '', - suffix: '', - details: '', + prefix: "", + suffix: "", + details: "", }; } else { symbolAnnotation = getSymbolKindForDeclaration(_contract); @@ -637,16 +636,16 @@ class SolidityDocumentSymbolProvider { let currentContractNode = contractNodes[inheritedFromContractName]; - if (typeof currentContractNode == 'undefined') { + if (typeof currentContractNode == "undefined") { currentContractNode = astNodeAsDocumentSymbol( document, getFakeNode(inheritedFromContractName, 1), symbolAnnotation.symbol, - ' ↖ ' + + " ↖ " + symbolAnnotation.prefix + symbolAnnotation.name + symbolAnnotation.suffix, - symbolAnnotation.details + symbolAnnotation.details, ); contractNodes[inheritedFromContractName] = currentContractNode; @@ -656,38 +655,41 @@ class SolidityDocumentSymbolProvider { let varSymbol; try { varSymbol = getSymbolKindForDeclaration( - _contract.names[name] + _contract.names[name], ); } catch (e) { varSymbol = { symbol: vscode.SymbolKind.Variable, name: name, - prefix: '', - suffix: '', - details: '', + prefix: "", + suffix: "", + details: "", }; } let inheritanceNode = astNodeAsDocumentSymbol( document, getFakeNode(varSymbol.name, 1), varSymbol.symbol, - ' ↖ ' + varSymbol.prefix + varSymbol.name + varSymbol.suffix, - varSymbol.details + " ↖ " + + varSymbol.prefix + + varSymbol.name + + varSymbol.suffix, + varSymbol.details, ); currentContractNode.children.push(inheritanceNode); } } - console.log('✓ inheritance'); + console.log("✓ inheritance"); } if (token.isCancellationRequested) { return reject(token); } - console.log('✓✓✓ done preparing symbols for: ' + document.fileName); + 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}` + `Error adding file or one of its dependencies to workspace (parser error): ${document.fileName}`, ); if (settings.extensionConfig().debug.parser.showExceptions) { console.error(e); 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 903f097..6cc73ce 100644 --- a/src/features/utils.js +++ b/src/features/utils.js @@ -1,4 +1,4 @@ -'use strict'; +"use strict"; /** * @author github.com/tintinweb * @license GPLv3 @@ -9,7 +9,7 @@ const commentRegex = () => new RegExp( `(?:${commentRegex.line().source})|(?:${commentRegex.block().source})`, - 'gm' + "gm", ); commentRegex.line = () => /(?:^|\s)\/\/(.+?)$/gm; commentRegex.block = () => /\/\*([\S\s]*?)\*\//gm; @@ -22,7 +22,7 @@ class CommentMapperRex { } isRangeOffsetInComment(start, end) { - if (typeof this.input !== 'undefined' && this.input !== null) { + if (typeof this.input !== "undefined" && this.input !== null) { this.getComments(this.input); this.input = null; //free space } @@ -49,15 +49,17 @@ class CommentMapperRex { function functionSignatureForASTItem(item) { switch (item._node?.type) { - case 'FunctionDefinition': + case "FunctionDefinition": const res = item.getFunctionSignature(); //call getFunctionSignature from Workspace on function node return [res]; - case 'ContractDefinition': + case "ContractDefinition": return Object.values(item.functions) - .filter((fn) => fn.name && ['external', 'public'].includes(fn.visibility)) + .filter( + (fn) => fn.name && ["external", "public"].includes(fn.visibility), + ) .map((fn) => fn.getFunctionSignature()); default: - throw new Error('Unsupported node type'); + throw new Error("Unsupported node type"); } } 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 + + +
+ + From e7b591b03a67a6311ece0d1d1e02c3029414252c Mon Sep 17 00:00:00 2001 From: Valentin Date: Thu, 5 Oct 2023 15:56:16 +0200 Subject: [PATCH 17/32] =?UTF-8?q?More=20deco=20refactoring=20=F0=9F=99=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/deco.js | 650 ++++++++++++++----------------------------- 1 file changed, 213 insertions(+), 437 deletions(-) diff --git a/src/features/deco.js b/src/features/deco.js index 431e17f..0c52960 100644 --- a/src/features/deco.js +++ b/src/features/deco.js @@ -12,128 +12,6 @@ const mod_parser = require("solidity-workspace"); const { getAstValueForExpression } = require("./symbols"); const settings = require("../settings"); -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, -}; - async function decorateSourceUnit(document, editor, sourceUnit) { const config = settings.extensionConfig(); let decorations = []; @@ -356,83 +234,28 @@ async function decorateWords(editor, words, decoStyle, commentMapper) { editor.setDecorations(decoStyle, smallNumbers); } -function HSLtoRGB(h, s, l) { - let r, g, b; - - const rd = (a) => { - return Math.floor(Math.max(Math.min(a * 256, 255), 0)); - }; - - 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; - }; - - const q = l < 0.5 ? l * (1 + s) : l + s - l * s; - const p = 2 * l - q; - - 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)]; -} - -function RGBtoHex(r, g, b) { - return `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`; -} - -var gutterIcons = {}; - function varDecIsArray(node) { return node && node.typeName && node.typeName.type == "ArrayTypeName"; } -function varDecIsUserDefined(node) { - return node && node.typeName && node.typeName.type == "UserDefinedTypeName"; -} - 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; - } + node = varDecIsArray(node) ? node.typeName.baseTypeName : 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; + 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; } } @@ -441,19 +264,14 @@ function semanticHighlightFunctionParameters(arrIdents, decorations) { return []; } - let index = 0; + let funcNode = arrIdents[0].extra.inFunction; let colorAssign = {}; - let funcNode = arrIdents[0].extra.inFunction; // just take the first items ref to function + 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) || ""; - 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), @@ -462,20 +280,14 @@ function semanticHighlightFunctionParameters(arrIdents, decorations) { ident.loc.end.column + ident.name.length, ), ), - hoverMessage: - "(*" + - typeName + - "*) " + - "**Argument** *" + - funcNode._node.name + - "*.**" + - ident.name + - "**", + hoverMessage: `(*${typeName}*) **Argument** *${funcNode._node.name}*.**${ident.name}**`, decoStyle: colorAssign[ident.name], }); - } - arrIdents.forEach(function (ident) { - let typeName = getVariableDeclarationType(ident.extra.declaration); + }); + + 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), @@ -484,117 +296,14 @@ function semanticHighlightFunctionParameters(arrIdents, decorations) { ident.loc.end.column + ident.name.length, ), ), - hoverMessage: - "(*" + - typeName + - "*) " + - "**Argument** *" + - funcNode._node.name + - "*.**" + - ident.name + - "**", + hoverMessage: `(*${typeName}*) **Argument** *${funcNode._node.name}*.**${ident.name}**`, decoStyle: colorAssign[ident.name], }); }); - console.log("✓ semantic highlight - " + funcNode._node.name); + console.log(`✓ semantic highlight - ${funcNode._node.name}`); } -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, - }, - }); - } - - 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"); - - styles.decoStyleBookmarkRed = vscode.window.createTextEditorDecorationType({ - gutterIconPath: gutterIcons.red, - 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.decoStyleBookmarkGreen = vscode.window.createTextEditorDecorationType({ - gutterIconPath: gutterIcons.green, - light: { - fontWeight: "bold", - }, - dark: { - color: "Chocolate", - }, - }); - styles.decoStyleBookmarkBlue = vscode.window.createTextEditorDecorationType({ - gutterIconPath: gutterIcons.blue, - light: { - fontWeight: "bold", - }, - dark: { - color: "Chocolate", - }, - }); - styles.decoStyleBookmarkIssue = vscode.window.createTextEditorDecorationType({ - gutterIconPath: gutterIcons.issue, - light: { - fontWeight: "bold", - }, - dark: { - color: "Chocolate", - }, - }); -} +//Styles class CreateDecoStyle { static reserved(node) { @@ -611,7 +320,7 @@ class CreateDecoStyle { node.loc.end.column + node.name.length, ), ), - hoverMessage: prefix + "**" + node.name + "**" + " (" + decl_uri + ")", + hoverMessage: `${prefix}**${node.name}** (${decl_uri})`, decoStyle: decoStyle, }; } @@ -634,15 +343,6 @@ class CreateDecoStyle { 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"; @@ -666,18 +366,11 @@ class CreateDecoStyle { node.identifier.loc.end.column + node.identifier.name.length, ), ), - hoverMessage: - prefix + - "(*" + - (node.typeName.type == "ElementaryTypeName" + hoverMessage: `${prefix}(*${ + node.typeName.type == "ElementaryTypeName" ? node.typeName.name - : node.typeName.namePath) + - "*) " + - "StateVar *" + - contract.name + - "*.**" + - node.identifier.name + - "**", + : node.typeName.namePath + }*) StateVar *${contract.name}*.**${node.identifier.name}**`, decoStyle: decoStyle, }; } @@ -686,14 +379,7 @@ class CreateDecoStyle { let knownValue = ""; var decoStyle = "decoStyleStateVar"; - let decl_uri = - "([Declaration: #" + - svar.loc.start.line + - "](" + - document.uri + - "#" + - svar.loc.start.line + - "))"; + let decl_uri = `([Declaration: #${svar.loc.start.line}](${document.uri}#${svar.loc.start.line}))`; if (svar.isDeclaredConst) { prefix = "**CONST** "; @@ -715,21 +401,13 @@ class CreateDecoStyle { node.loc.end.column + node.name.length, ), ), - hoverMessage: - prefix + - "(*" + - (svar.typeName.type == "ElementaryTypeName" + hoverMessage: `${prefix}(*${ + svar.typeName.type == "ElementaryTypeName" ? svar.typeName.name - : svar.typeName.namePath) + - "*) " + - "**StateVar** *" + - contract.name + - "*.**" + - svar.name + - "**" + - knownValue + - " " + - decl_uri, + : svar.typeName.namePath + }*) **StateVar** *${contract.name}*.**${ + svar.name + }**${knownValue} ${decl_uri}`, decoStyle: decoStyle, }; } @@ -753,20 +431,11 @@ class CreateDecoStyle { node.loc.end.column + node.name.length, ), ), - hoverMessage: - prefix + - "(*" + - (declaration.typeName.type == "ElementaryTypeName" + hoverMessage: `${prefix}(*${ + declaration.typeName.type == "ElementaryTypeName" ? declaration.typeName.name - : declaration.typeName.namePath) + - "*) " + - "**StateVar** *" + - contract.name + - "*.**" + - declaration.name + - "**" + - " " + - decl_uri, + : declaration.typeName.namePath + }*) **StateVar** *${contract.name}*.**${declaration.name}** ${decl_uri}`, decoStyle: decoStyle, }; } @@ -774,14 +443,7 @@ class CreateDecoStyle { 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 decl_uri = `([Declaration: #${node.loc.start.line}](${document.uri}#${node.loc.start.line}))`; let knownType = "undef"; let subcontract = contract.inherited_names[node.name]; @@ -789,16 +451,7 @@ class CreateDecoStyle { 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 + - "))"; + decl_uri = `([Declaration: ${subcontract}#${declaration.loc.start.line}](${uri}#${declaration.loc.start.line}))`; knownType = getVariableDeclarationType(declaration); } @@ -810,33 +463,14 @@ class CreateDecoStyle { node.loc.end.column + node.name.length, ), ), - hoverMessage: - prefix + - "(*" + - knownType + - "*) " + - "**StateVar** *" + - subcontract.name + - "*.**" + - node.name + - "**" + - " " + - decl_uri, - decoStyle: decoStyle, + hoverMessage: `${prefix}(*${knownType}*) **StateVar** *${subcontract.name}*.**${node.name}** ${decl_uri}`, }; } 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 decl_uri = `([Declaration: #${declaration.loc.start.line}](${document.uri}#${declaration.loc.start.line}))`; let knownType = getVariableDeclarationType(declaration); let subcontract = contract.inherited_names[node.name]; @@ -847,16 +481,7 @@ class CreateDecoStyle { declaration = declaration.hasOwnProperty("_node") ? declaration._node : declaration; - decl_uri = - "([Declaration: " + - subcontract.name + - "#" + - declaration.loc.start.line + - "](" + - uri + - "#" + - declaration.loc.start.line + - "))"; + decl_uri = `([Declaration: ${subcontract.name}#${declaration.loc.start.line}](${uri}#${declaration.loc.start.line}))`; knownType = getVariableDeclarationType(declaration); } @@ -868,29 +493,180 @@ class CreateDecoStyle { node.loc.end.column + node.name.length, ), ), - hoverMessage: - prefix + - "(*" + - (knownType || "?") + - "*) " + - "**StateVar** *" + - (subcontract ? subcontract.name : "Unknown") + - "*.**" + - node.name + - "**" + - " " + - decl_uri, + hoverMessage: `${prefix}(*${knownType || "?"}*) **StateVar** *${ + subcontract ? subcontract.name : "Unknown" + }*.**${node.name}** ${decl_uri}`, decoStyle: decoStyle, }; } } +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, + }, + }); + } + + 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, + + light: { + fontWeight: "bold", + }, + + dark: { + color: "Chocolate", + }, + }); + }; + + 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.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" }); +} + +//utils + +function HSLtoRGB(h, s, l) { + let r, g, b; + + const rd = (a) => { + return Math.floor(Math.max(Math.min(a * 256, 255), 0)); + }; + + 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; + }; + + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; + const p = 2 * l - q; + + 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)]; +} + +function RGBtoHex(r, g, b) { + return `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`; +} + module.exports = { init: init, - decoStyleStateVar: decoStyleStateVar, decorateSourceUnit: decorateSourceUnit, - styles: styles, - decorateWords: decorateWords, - semanticHighlightFunctionParameters: semanticHighlightFunctionParameters, - CreateDecoStyle: CreateDecoStyle, }; From d4f1b28e4d7287dd1551dc78d4514d3caa816cf0 Mon Sep 17 00:00:00 2001 From: Valentin Date: Mon, 9 Oct 2023 11:41:26 +0200 Subject: [PATCH 18/32] fix cockpit view for overriden functions (#138) --- examples/cockpitFunctionOverride.sol | 37 ++++++++ package.json | 2 +- src/features/cockpit.js | 129 ++++++++++++++------------- src/features/deco.js | 4 +- 4 files changed, 109 insertions(+), 63 deletions(-) create mode 100644 examples/cockpitFunctionOverride.sol 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.json b/package.json index c48c5b8..08798ed 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ }, { "id": "solidity-va-cockpit-publicMethods", - "name": "Context: Public StateChanging Methods" + "name": "Context: Public State-Changing Methods" }, { "id": "solidity-va-cockpit-externalCalls", diff --git a/src/features/cockpit.js b/src/features/cockpit.js index fdd4cfe..69e94cc 100644 --- a/src/features/cockpit.js +++ b/src/features/cockpit.js @@ -67,11 +67,13 @@ class BaseDataProvider { 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; } @@ -525,42 +527,44 @@ class PublicMethodsViewDataProvider extends BaseDataProvider { } 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); + 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 + }`, + tooltip: f.name, + name: f.name, + 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; }, []); } @@ -600,11 +604,11 @@ class PublicMethodsView extends BaseView { return; } - let focusSolidityElement = contractObj.getFunctionAtLocation( + let currentContract = contractObj.getContractAtLocation( focus.line, focus.character, ); - if (!focusSolidityElement) { + if (!currentContract) { console.warn( "cockpit.methods: contract not found: " + documentUri.fsPath, ); @@ -614,7 +618,7 @@ class PublicMethodsView extends BaseView { let filterNotVisibility = ["private", "internal"]; let filterNotStateMutability = ["view", "pure", "constant"]; - let publicFunctions = focusSolidityElement.contract.functions + let publicFunctions = currentContract.functions .filter((f) => { let node = f._node; //filter only for state changing public functions @@ -624,15 +628,19 @@ class PublicMethodsView extends BaseView { ); }) .reduce((obj, func) => { - let newKey = func.name; + let key = func.name; - if (newKey === null || func._node.isConstructor) { - newKey = ""; - } else if (newKey === "" || func._node.isFallback) { - newKey = ""; + if (key === null || func._node.isConstructor) { + key = ""; + } else if (key === "" || func._node.isFallback) { + key = ""; } func.resource = documentUri; - obj[newKey] = func; + 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 @@ -905,17 +913,17 @@ class ExtCallViewDataProvider extends BaseDataProvider { } let first = this.data[key][0]; + const inFunction = first.parent; 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, + range: elemLocToRange(first.parent._node), + label: `${inFunction.name}${ + inFunction._node.stateMutability === "payable" ? " 💰" : "" + }`, + tooltip: inFunction.name, //in function name + name: inFunction.name, iconPath: vscode.ThemeIcon.File, collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, parent: null, @@ -939,7 +947,7 @@ class ExtCallViewDataProvider extends BaseDataProvider { command: "solidity-va.cockpit.jumpToRange", arguments: [ first.resource, - elemLocToFirstLineRange(first.parent.function._node), + elemLocToFirstLineRange(first.parent._node), ], title: "JumpTo", }, @@ -989,24 +997,23 @@ class ExtCallView extends BaseView { focus.character, ); if (!focusSolidityElement) { - console.warn("surya.ftrace: contract not found: " + documentUri.fsPath); + 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) => { - let result = sourceUnit.getFunctionAtLocation( - c._node.loc.start.line, - c._node.loc.start.column, - ); - let key = `${result.function.name}`; - let data = obj[key]; + const functionNode = c.declaration.extra.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: result }); + data.push({ resource: documentUri, call: c, parent: functionNode }); obj[key] = data; return obj; diff --git a/src/features/deco.js b/src/features/deco.js index 0c52960..a832acc 100644 --- a/src/features/deco.js +++ b/src/features/deco.js @@ -253,7 +253,9 @@ function getVariableDeclarationType(node) { case "UserDefinedTypeName": return node.namePath; case "Mapping": - return `mapping( ${getVariableDeclarationType(node.keyType)} => ${getVariableDeclarationType(node.valueType)} )`; + return `mapping( ${getVariableDeclarationType( + node.keyType, + )} => ${getVariableDeclarationType(node.valueType)} )`; default: return null; } From d41d8733f011856784161ad992dc275eef235bb5 Mon Sep 17 00:00:00 2001 From: Valentin Date: Mon, 9 Oct 2023 12:11:13 +0200 Subject: [PATCH 19/32] fix external calls cockpit --- src/features/cockpit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/cockpit.js b/src/features/cockpit.js index 69e94cc..a1ff7e9 100644 --- a/src/features/cockpit.js +++ b/src/features/cockpit.js @@ -1005,7 +1005,7 @@ class ExtCallView extends BaseView { // data format: obj[contract][function][calls]=[target, target]; let extcalls = focusSolidityElement.getExternalCalls().reduce((obj, c) => { - const functionNode = c.declaration.extra.inFunction; + const functionNode = c.inFunction; const key = functionNode.id; let data = obj[key]; //use function id instead of name to handle overriden functions From 24c77d5df9447f59704d2d8fc31ca75c9504ba5c Mon Sep 17 00:00:00 2001 From: tintinweb Date: Tue, 10 Oct 2023 14:50:22 +0200 Subject: [PATCH 20/32] fix markdown alignment --- src/features/commands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/commands.js b/src/features/commands.js index 48f574f..a78dee1 100644 --- a/src/features/commands.js +++ b/src/features/commands.js @@ -770,7 +770,7 @@ ${topLevelContractsText}`; // markdown const header = - "| Function Name | Sighash | Function Signature | \n | ------------ | ------------ | ------------ |\n"; + "| Function Name | Sighash | Function Signature | \n| ------------- | ---------- | ------------------ | \n"; content = header + signatures From 55797ac0012f031c8fab8a74d01534784c44efbb Mon Sep 17 00:00:00 2001 From: tintinweb Date: Tue, 10 Oct 2023 14:51:01 +0200 Subject: [PATCH 21/32] use workspace.add to force analysis (early exit if exists/cache) catch rejected promises to avoid unhandled promises --- src/features/codelens.js | 11 ++++++++++- src/features/symbols.js | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/features/codelens.js b/src/features/codelens.js index a6e0801..312aea1 100644 --- a/src/features/codelens.js +++ b/src/features/codelens.js @@ -113,7 +113,7 @@ class ParserLensProvider { let firstLine = new vscode.Range(0, 0, 0, 0); let config = settings.extensionConfig().codelens; return this.g_workspace - .getSourceUnitByPath(document.fileName) + .add(document.fileName, { content: document.getText() }) .then((parser) => { let codeLens = []; config.uml.enable && @@ -175,6 +175,15 @@ class ParserLensProvider { } } return codeLens; + }) + .catch((e) => { + console.warn( + `Error parsing file ${document.fileName}`, + ); + if (settings.extensionConfig().debug.parser.showExceptions) { + console.error(e); + } + return undefined; }); } diff --git a/src/features/symbols.js b/src/features/symbols.js index 4a7731e..69d742f 100644 --- a/src/features/symbols.js +++ b/src/features/symbols.js @@ -276,7 +276,7 @@ class SolidityDocumentSymbolProvider { return new Promise((resolve, reject) => { return this.g_workspace - .getSourceUnitByPath(document.fileName) + .add(document.fileName, { content: document.getText() }) .then((insights) => { var symbols = []; From 7220d08fcf1f9a77c0c22d6d1222ec3dd7f0ccd1 Mon Sep 17 00:00:00 2001 From: tintinweb Date: Tue, 10 Oct 2023 14:52:10 +0200 Subject: [PATCH 22/32] select content changing events only remove debouncing (selecting the right event reduced times this is being called from 4x to 1x) do nothing if expected content hash is not found after analysis more log messages --- src/extension.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/extension.js b/src/extension.js index 170c0d9..498aec7 100644 --- a/src/extension.js +++ b/src/extension.js @@ -38,7 +38,6 @@ const g_workspace = new mod_parser.Workspace( ); var activeEditor; var g_diagnostics; -var debounceTimer; const currentCancellationTokens = { onDidChange: new CancellationTokenSource(), @@ -87,11 +86,10 @@ function analyzeSourceUnit( console.error("-BUG- cannot analyze empty document!"); return; } - g_workspace .add(document.fileName, { content: document.getText() }) .then((sourceUnit) => { - console.log(`✓ inspect ${sourceUnit.filePath}`); + console.log(`✓ inspect ${sourceUnit.filePath} ${sourceUnit.hash}`); }) .catch((e) => { console.warn( @@ -102,14 +100,16 @@ function analyzeSourceUnit( } }); + 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) => 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 :/ @@ -180,8 +180,7 @@ function refresh(editor, initialLoad = false) { } function onDidChange(editor) { - clearTimeout(debounceTimer); - debounceTimer = setTimeout(() => refresh(editor), 500); //only re-parse every 500ms + refresh(editor); } function onActivate(context) { @@ -564,7 +563,7 @@ function onActivate(context) { (editor) => { activeEditor = editor; if (editor && editor.document && editor.document.languageId == type) { - refresh(editor); + onDidChange(editor); } }, null, @@ -573,7 +572,8 @@ function onActivate(context) { vscode.workspace.onDidChangeTextDocument( (event) => { if ( - activeEditor && + activeEditor && + event.contentChanges.length > 0 && // only redecorate when there are content changes event.document === activeEditor.document && event.document.languageId == type ) { From e74f86e4cdb30c571a3a7d46a96231bbdcfb02a2 Mon Sep 17 00:00:00 2001 From: tintinweb Date: Tue, 10 Oct 2023 21:57:34 +0200 Subject: [PATCH 23/32] fix cockpit: constructor shows up as 'null' --- src/features/cockpit.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/features/cockpit.js b/src/features/cockpit.js index a1ff7e9..f0bd981 100644 --- a/src/features/cockpit.js +++ b/src/features/cockpit.js @@ -536,10 +536,10 @@ class PublicMethodsViewDataProvider extends BaseDataProvider { contextValue: f.resource.fsPath, range: range, label: `${f._node.stateMutability == "payable" ? "💰" : ""} ${ - f.name + f.name || key }`, - tooltip: f.name, - name: f.name, + tooltip: f.name || key, + name: f.name || key, iconPath: vscode.ThemeIcon.File, collapsibleState: modifiers.length > 0 @@ -915,15 +915,22 @@ class ExtCallViewDataProvider extends BaseDataProvider { 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: `${inFunction.name}${ + label: `${redableName}${ inFunction._node.stateMutability === "payable" ? " 💰" : "" }`, - tooltip: inFunction.name, //in function name - name: inFunction.name, + tooltip: redableName, //in function name + name: redableName, iconPath: vscode.ThemeIcon.File, collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, parent: null, From c61986f84387ec3c31447ed669ad186ed2951833 Mon Sep 17 00:00:00 2001 From: tintinweb Date: Tue, 10 Oct 2023 22:11:35 +0200 Subject: [PATCH 24/32] update dependencies --- package-lock.json | 2206 +++++++++++++++++++++++++++------------------ package.json | 4 +- 2 files changed, 1322 insertions(+), 888 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2cab688..f5b1429 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,899 +1,1333 @@ { - "name": "solidity-visual-auditor", - "version": "0.1.5", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "solidity-visual-auditor", - "version": "0.1.5", - "dependencies": { - "solidity-workspace": "file:../../js/solidity-workspace", - "surya": "^0.4.6" - }, - "engines": { - "vscode": "^1.26.2" - } - }, - "../../js/solidity-workspace": { - "version": "0.2.0", - "license": "MIT", - "dependencies": { - "@solidity-parser/parser": "^0.15.0", - "c3-linearization": "^0.3.0", - "keccak": "^3.0.2", - "yargs": "^17.5.1" - }, - "bin": { - "solidity-workspace": "src/cli.js" - } - }, - "../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/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/code-point-at": { - "version": "1.1.0", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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/end-of-stream": { - "version": "1.4.4", - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "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-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/invert-kv": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "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/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/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/pump": { - "version": "3.0.0", - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "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/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": { - "resolved": "../../js/solidity-workspace", - "link": true - }, - "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" + "name": "solidity-visual-auditor", + "version": "0.2.0-dev1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "solidity-visual-auditor", + "version": "0.2.0-dev1", + "dependencies": { + "solidity-workspace": "^0.2.0-dev3", + "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.0-dev3", + "resolved": "https://registry.npmjs.org/solidity-workspace/-/solidity-workspace-0.2.0-dev3.tgz", + "integrity": "sha512-i875hL87Jmv/8EmPOn4buX6bwBa3SD1yRCJFWA1bSrKxsIU247NdKhGdulNuJBq8rjNuUhwKR1E2TvvZqOwbOQ==", + "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" + }, + "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.0-dev3", + "resolved": "https://registry.npmjs.org/solidity-workspace/-/solidity-workspace-0.2.0-dev3.tgz", + "integrity": "sha512-i875hL87Jmv/8EmPOn4buX6bwBa3SD1yRCJFWA1bSrKxsIU247NdKhGdulNuJBq8rjNuUhwKR1E2TvvZqOwbOQ==", + "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.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": "3.0.1" + }, + "cliui": { + "version": "4.1.0", + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3" + }, + "is-fullwidth-code-point": { + "version": "2.0.0" + }, + "string-width": { + "version": "2.1.1", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.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": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "requires": { "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": { + "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" + } }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/surya/node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "3.0.1", - "license": "MIT", - "dependencies": { + "strip-ansi": { + "version": "3.0.1", + "requires": { "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/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/wrappy": { - "version": "1.0.2", - "license": "ISC" + } + } + } + }, + "y18n": { + "version": "3.2.2" + }, + "yargs": { + "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": "9.0.2", + "requires": { + "camelcase": "^4.1.0" + } } + } }, - "dependencies": { - "@solidity-parser/parser": { - "version": "0.14.3", - "requires": { - "antlr4ts": "^0.5.0-alpha.4" - } - }, - "antlr4ts": { - "version": "0.5.0-alpha.4" - }, - "c3-linearization": { - "version": "0.3.0" - }, - "camelcase": { - "version": "4.1.0" - }, - "code-point-at": { - "version": "1.1.0" - }, - "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" - }, - "end-of-stream": { - "version": "1.4.4", - "requires": { - "once": "^1.4.0" - } - }, - "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-stream": { - "version": "4.1.0", - "requires": { - "pump": "^3.0.0" - } - }, - "graphviz": { - "version": "0.0.9", - "requires": { - "temp": "~0.4.0" - } - }, - "invert-kv": { - "version": "2.0.0" - }, - "is-stream": { - "version": "1.1.0" - }, - "isexe": { - "version": "2.0.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" - }, - "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" - }, - "pump": { - "version": "3.0.0", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "require-directory": { - "version": "2.1.1" - }, - "require-main-filename": { - "version": "1.0.1" - }, - "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": "file:../../js/solidity-workspace", - "requires": { - "@solidity-parser/parser": "^0.15.0", - "c3-linearization": "^0.3.0", - "keccak": "^3.0.2", - "yargs": "^17.5.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": "3.0.1" - }, - "cliui": { - "version": "4.1.0", - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "get-caller-file": { - "version": "1.0.3" - }, - "is-fullwidth-code-point": { - "version": "2.0.0" - }, - "string-width": { - "version": "2.1.1", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "wrap-ansi": { - "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" - } - } - } - }, - "y18n": { - "version": "3.2.2" - }, - "yargs": { - "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": "9.0.2", - "requires": { - "camelcase": "^4.1.0" - } - } - } - }, - "temp": { - "version": "0.4.0" - }, - "treeify": { - "version": "1.1.0" - }, - "which": { - "version": "1.3.1", - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0" - }, - "wrappy": { - "version": "1.0.2" - } + "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 08798ed..c759b3b 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "solidity security", "solidity audit" ], - "version": "0.1.5", + "version": "0.2.0-dev1", "publisher": "tintinweb", "icon": "images/icon.png", "engines": { @@ -548,7 +548,7 @@ "format": "prettier --write ." }, "dependencies": { - "solidity-workspace": "^0.1.7", + "solidity-workspace": "^0.2.0-dev3", "surya": "^0.4.6" }, "devDependencies": { From 478df1c0dafd068ecdd93e165c164871c28337bf Mon Sep 17 00:00:00 2001 From: tintinweb Date: Wed, 11 Oct 2023 11:38:51 +0200 Subject: [PATCH 25/32] reintroduce shadowing decostyle fix inherited contract name in shadowing hover --- src/features/deco.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/features/deco.js b/src/features/deco.js index a832acc..c80a545 100644 --- a/src/features/deco.js +++ b/src/features/deco.js @@ -453,7 +453,7 @@ class CreateDecoStyle { 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}))`; + decl_uri = `([Declaration: ${subcontract.name}#${declaration.loc.start.line}](${uri}#${declaration.loc.start.line}))`; knownType = getVariableDeclarationType(declaration); } @@ -466,6 +466,7 @@ class CreateDecoStyle { ), ), hoverMessage: `${prefix}(*${knownType}*) **StateVar** *${subcontract.name}*.**${node.name}** ${decl_uri}`, + decoStyle: decoStyle }; } static inheritedStateVar(node, document, contract, declaration) { From e2ddac0ca71b97302c0b37a75f66d7c5f44b94c7 Mon Sep 17 00:00:00 2001 From: tintinweb Date: Wed, 11 Oct 2023 11:59:29 +0200 Subject: [PATCH 26/32] update changelog --- CHANGELOG.md | 10 +++- src/features/whatsnew/whatsNew.js | 98 +++---------------------------- 2 files changed, 16 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16461af..4c08e6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,16 +2,22 @@ Note: Don't forget to check out `preferences → Settings → Solidity Visual Developer` to customize features, look and feel. -## v0.2.0 - 💖 Happy Valentine's Days, spread some love! 💖 +## v0.2.0 - 🍂🍁🍃 Atumn Is Here! 🎃👻 - fix: includes parser performance optimizations with [solidity-workspace@v0.2.0](https://github.com/tintinweb/solidity-workspace/releases/tag/v0.2.0) (🙏 @vquelque) - update: completely refactored function signature computation - #127 -- fix: performance optimizations (debounce) - #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) ## v0.1.5 - 🏂 diff --git a/src/features/whatsnew/whatsNew.js b/src/features/whatsnew/whatsNew.js index 610cf03..eb08b1f 100644 --- a/src/features/whatsnew/whatsNew.js +++ b/src/features/whatsnew/whatsNew.js @@ -38,104 +38,22 @@ ___ The complete changelog can be found [here](https://github.com/ConsenSys/vscode-solidity-auditor/blob/master/CHANGELOG.md). -## v0.2.0 - 💖 Happy Valentine's Days, spread some love! 💖 +## v0.2.0 - 🍂🍁🍃 Atumn Is Here! 🎃👻 - fix: includes parser performance optimizations with [solidity-workspace@v0.2.0](https://github.com/tintinweb/solidity-workspace/releases/tag/v0.2.0) (🙏 @vquelque) - update: completely refactored function signature computation - #127 -- fix: performance optimizations (debounce) - #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 - -## 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 - -image - -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 - - \`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 -- 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 - -- 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~~ - -![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\`. - -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\` - - ![image](https://user-images.githubusercontent.com/2865694/145625639-a54178d1-5cee-45b6-bf10-44da09875f0e.png) - -- update: support for latest solidity parser (extension + surya) #84 - -## v0.1.0 - with a lot of new features 🥳 - -- new: 🥳 major parser refactoring #67 and we published the parser as standalone lib "[solidity-workspace](https://github.com/tintinweb/solidity-workspace)" -- new: ⚠️ annotations for potential external calls (yellow gutter icon) - - best effort - might miss some external calls depending on whether it is possible to easily resolve them (e.g. accessing addresses in nested structures/mappings). -- new: cockpit view that lists external calls in the currently selected contract (click into a contract in the editor for the view to update) - - ![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) -- new: unit-test stub/template for Hardhat/Ethers #70 (\`preferences → Settings → Solidity Visual Developer: solidity-va.test.defaultUnittestTemplate\`) -- new: (debug) option to enable/disable stacktraces for parser errors (\`preferences → Settings → Solidity Visual Developer: solidity-va.debug\`) -- new: show codelenses (inline actions) for abstract contracts -- new: customize which codelenses to show or hide (\`preferences → Settings → Solidity Visual Developer: solidity-va.codelens.*\`) #76 -- new: expose new command \`solidity-va.surya.graphThis\` #76 -- new: use internal ("dumb" lexical) flattener by default. Optionally allow to select \`truffle-flattener\` (\`preferences → Settings → Solidity Visual Developer: solidity-va.flatten.mode\`) -- update: enable \`draw.io csv export\` codelens by default -- fix: misplaced decoration when document changes -- 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 +- 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) From 029df9a5f197cb5069402539be51810734cbd9ba Mon Sep 17 00:00:00 2001 From: tintinweb Date: Wed, 11 Oct 2023 12:38:18 +0200 Subject: [PATCH 27/32] dedupe files passed to surya --- src/features/cockpit.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/features/cockpit.js b/src/features/cockpit.js index f0bd981..e496976 100644 --- a/src/features/cockpit.js +++ b/src/features/cockpit.js @@ -476,7 +476,7 @@ class FTraceView extends BaseView { }); }); } else { - files = [documentUri.fsPath, ...knownFiles]; //better only add imported files. need to resolve that somehow + files = [... new Set([documentUri.fsPath, ...knownFiles])]; //better only add imported files. need to resolve that somehow } // contract::func, all, files @@ -501,6 +501,7 @@ class FTraceView extends BaseView { "💣💥 - 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; From 1e17524ffd7654fb15d2c2b21566349f9f465c6b Mon Sep 17 00:00:00 2001 From: tintinweb Date: Thu, 12 Oct 2023 14:21:05 +0200 Subject: [PATCH 28/32] reintroduce debouncing for onDidChange events - cancellation tokens don't seem to work nicely because vscode seems to serialize onDidChange events :/ --- package-lock.json | 18 ++++++------ package.json | 4 +-- src/extension.js | 70 +++++++++++++++++++++++++++++++++++------------ 3 files changed, 64 insertions(+), 28 deletions(-) diff --git a/package-lock.json b/package-lock.json index f5b1429..f123df8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,14 @@ { "name": "solidity-visual-auditor", - "version": "0.2.0-dev1", + "version": "0.2.0-dev2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "solidity-visual-auditor", - "version": "0.2.0-dev1", + "version": "0.2.0-dev2", "dependencies": { - "solidity-workspace": "^0.2.0-dev3", + "solidity-workspace": "^0.2.0-dev4", "surya": "^0.4.6" }, "devDependencies": { @@ -529,9 +529,9 @@ "license": "ISC" }, "node_modules/solidity-workspace": { - "version": "0.2.0-dev3", - "resolved": "https://registry.npmjs.org/solidity-workspace/-/solidity-workspace-0.2.0-dev3.tgz", - "integrity": "sha512-i875hL87Jmv/8EmPOn4buX6bwBa3SD1yRCJFWA1bSrKxsIU247NdKhGdulNuJBq8rjNuUhwKR1E2TvvZqOwbOQ==", + "version": "0.2.0-dev4", + "resolved": "https://registry.npmjs.org/solidity-workspace/-/solidity-workspace-0.2.0-dev4.tgz", + "integrity": "sha512-M3jSzknHl7I1YUabs+fic+i6RECI2IWoi8DSFcOtoKp54yhbSA2DB3aijqzEw+rUQ2lcXdcPi7+9koU6JvxcVA==", "dependencies": { "@solidity-parser/parser": "^0.16.1", "c3-linearization": "^0.3.0", @@ -1121,9 +1121,9 @@ "version": "3.0.7" }, "solidity-workspace": { - "version": "0.2.0-dev3", - "resolved": "https://registry.npmjs.org/solidity-workspace/-/solidity-workspace-0.2.0-dev3.tgz", - "integrity": "sha512-i875hL87Jmv/8EmPOn4buX6bwBa3SD1yRCJFWA1bSrKxsIU247NdKhGdulNuJBq8rjNuUhwKR1E2TvvZqOwbOQ==", + "version": "0.2.0-dev4", + "resolved": "https://registry.npmjs.org/solidity-workspace/-/solidity-workspace-0.2.0-dev4.tgz", + "integrity": "sha512-M3jSzknHl7I1YUabs+fic+i6RECI2IWoi8DSFcOtoKp54yhbSA2DB3aijqzEw+rUQ2lcXdcPi7+9koU6JvxcVA==", "requires": { "@solidity-parser/parser": "^0.16.1", "c3-linearization": "^0.3.0", diff --git a/package.json b/package.json index c759b3b..d4786d7 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "solidity security", "solidity audit" ], - "version": "0.2.0-dev1", + "version": "0.2.0-dev2", "publisher": "tintinweb", "icon": "images/icon.png", "engines": { @@ -548,7 +548,7 @@ "format": "prettier --write ." }, "dependencies": { - "solidity-workspace": "^0.2.0-dev3", + "solidity-workspace": "^0.2.0-dev4", "surya": "^0.4.6" }, "devDependencies": { diff --git a/src/extension.js b/src/extension.js index 498aec7..992247d 100644 --- a/src/extension.js +++ b/src/extension.js @@ -14,7 +14,6 @@ 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"); @@ -38,6 +37,11 @@ const g_workspace = new mod_parser.Workspace( ); var activeEditor; var g_diagnostics; +var g_debounce = { + timerId: undefined, + armed: false, + wait: 500 +}; const currentCancellationTokens = { onDidChange: new CancellationTokenSource(), @@ -79,6 +83,7 @@ function analyzeSourceUnit( document, editor, initialLoad = false, + onFinished = () => {}, ) { console.log("inspect ..."); @@ -86,8 +91,10 @@ function analyzeSourceUnit( console.error("-BUG- cannot analyze empty document!"); return; } + g_workspace - .add(document.fileName, { content: document.getText() }) + .add(document.fileName, + { content: document.getText(), cancellationToken: cancellationToken.token }) .then((sourceUnit) => { console.log(`✓ inspect ${sourceUnit.filePath} ${sourceUnit.hash}`); }) @@ -113,6 +120,7 @@ function analyzeSourceUnit( ) ) { //abort - new analysis running already OR our finished task is not in the tasklist :/ + onFinished(); return; } @@ -127,6 +135,7 @@ function analyzeSourceUnit( mod_decorator.decorateSourceUnit(document, editor, this_sourceUnit); //decorate } + onFinished(); console.log("✓ analyzeSourceUnit - done"); }); } @@ -145,6 +154,23 @@ function onDidSave(document) { } } + +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 refresh(editor, initialLoad = false) { let document = editor && editor.document @@ -162,21 +188,31 @@ function refresh(editor, initialLoad = false) { } currentCancellationTokens.onDidChange.cancel(); currentCancellationTokens.onDidChange = new CancellationTokenSource(); - console.log("--- on-did-change"); - try { - analyzeSourceUnit( - currentCancellationTokens.onDidChange.token, - document, - editor, - initialLoad, - ); - } catch (err) { - if (typeof err !== "object") { - //CancellationToken - throw err; + + debounce(() => { + console.log("--- on-did-change"); + try { + 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"); + console.log("✓✓✓ on-did-change - resolved"); + }); + + } function onDidChange(editor) { @@ -577,7 +613,7 @@ function onActivate(context) { event.document === activeEditor.document && event.document.languageId == type ) { - onDidChange(activeEditor); + onDidChange(activeEditor) } }, null, From 42383a0ec72da7bbb82a99efcc1fc4cbe1309640 Mon Sep 17 00:00:00 2001 From: tintinweb Date: Fri, 13 Oct 2023 13:14:18 +0200 Subject: [PATCH 29/32] prep 0.2.0 --- CHANGELOG.md | 5 +++-- package-lock.json | 14 +++++++------- package.json | 2 +- src/features/whatsnew/whatsNew.js | 5 +++-- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c08e6b..df0f80d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,9 @@ Note: Don't forget to check out `preferences → Settings → Solidity Visual Developer` to customize features, look and feel. -## v0.2.0 - 🍂🍁🍃 Atumn Is Here! 🎃👻 +## v0.2.0 - 🍂🍁🍃 Halloween! Booh! 👻🎃🎃🎃🌾👨🏼‍🌾 -- fix: includes parser performance optimizations with [solidity-workspace@v0.2.0](https://github.com/tintinweb/solidity-workspace/releases/tag/v0.2.0) (🙏 @vquelque) +- 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 @@ -18,6 +18,7 @@ Note: Don't forget to check out `preferences → Settings → Solidity Visual De - 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 - 🏂 diff --git a/package-lock.json b/package-lock.json index f123df8..8ebb69a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "solidity-visual-auditor", "version": "0.2.0-dev2", "dependencies": { - "solidity-workspace": "^0.2.0-dev4", + "solidity-workspace": "^0.2.1", "surya": "^0.4.6" }, "devDependencies": { @@ -529,9 +529,9 @@ "license": "ISC" }, "node_modules/solidity-workspace": { - "version": "0.2.0-dev4", - "resolved": "https://registry.npmjs.org/solidity-workspace/-/solidity-workspace-0.2.0-dev4.tgz", - "integrity": "sha512-M3jSzknHl7I1YUabs+fic+i6RECI2IWoi8DSFcOtoKp54yhbSA2DB3aijqzEw+rUQ2lcXdcPi7+9koU6JvxcVA==", + "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", @@ -1121,9 +1121,9 @@ "version": "3.0.7" }, "solidity-workspace": { - "version": "0.2.0-dev4", - "resolved": "https://registry.npmjs.org/solidity-workspace/-/solidity-workspace-0.2.0-dev4.tgz", - "integrity": "sha512-M3jSzknHl7I1YUabs+fic+i6RECI2IWoi8DSFcOtoKp54yhbSA2DB3aijqzEw+rUQ2lcXdcPi7+9koU6JvxcVA==", + "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", diff --git a/package.json b/package.json index d4786d7..844c97e 100644 --- a/package.json +++ b/package.json @@ -548,7 +548,7 @@ "format": "prettier --write ." }, "dependencies": { - "solidity-workspace": "^0.2.0-dev4", + "solidity-workspace": "^0.2.1", "surya": "^0.4.6" }, "devDependencies": { diff --git a/src/features/whatsnew/whatsNew.js b/src/features/whatsnew/whatsNew.js index eb08b1f..2bcf3a2 100644 --- a/src/features/whatsnew/whatsNew.js +++ b/src/features/whatsnew/whatsNew.js @@ -38,9 +38,9 @@ ___ The complete changelog can be found [here](https://github.com/ConsenSys/vscode-solidity-auditor/blob/master/CHANGELOG.md). -## v0.2.0 - 🍂🍁🍃 Atumn Is Here! 🎃👻 +## v0.2.0 - 🍂🍁🍃 Halloween! Booh! 👻🎃🎃🎃🌾👨🏼‍🌾 -- fix: includes parser performance optimizations with [solidity-workspace@v0.2.0](https://github.com/tintinweb/solidity-workspace/releases/tag/v0.2.0) (🙏 @vquelque) +- 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 @@ -54,6 +54,7 @@ The complete changelog can be found [here](https://github.com/ConsenSys/vscode-s - 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) From 93c5db0094aeb32eb485f6bce4aa7e2dfb74b029 Mon Sep 17 00:00:00 2001 From: tintinweb Date: Fri, 13 Oct 2023 13:22:07 +0200 Subject: [PATCH 30/32] update launch.json --- .vscode/launch.json | 1 - 1 file changed, 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 359bccd..63ab3d4 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,7 +7,6 @@ "request": "launch", "runtimeExecutable": "${execPath}", "args": ["--extensionDevelopmentPath=${workspaceRoot}"], - "stopOnEntry": false, "sourceMaps": true, "outFiles": ["${workspaceRoot}/out/**/*.js"], "preLaunchTask": "npm: install" From 35d32d5068e3123cded82328685000f8cdb16c70 Mon Sep 17 00:00:00 2001 From: tintinweb Date: Fri, 13 Oct 2023 13:23:25 +0200 Subject: [PATCH 31/32] prep v0.2.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8ebb69a..ac8b225 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "solidity-visual-auditor", - "version": "0.2.0-dev2", + "version": "0.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "solidity-visual-auditor", - "version": "0.2.0-dev2", + "version": "0.2.0", "dependencies": { "solidity-workspace": "^0.2.1", "surya": "^0.4.6" diff --git a/package.json b/package.json index 844c97e..8a8a436 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "solidity security", "solidity audit" ], - "version": "0.2.0-dev2", + "version": "0.2.0", "publisher": "tintinweb", "icon": "images/icon.png", "engines": { From 92173f4ae629af76703f9c9d64501d62577bfe67 Mon Sep 17 00:00:00 2001 From: tintinweb Date: Fri, 13 Oct 2023 13:29:58 +0200 Subject: [PATCH 32/32] update readme --- CHANGELOG.md | 2 +- src/features/whatsnew/whatsNew.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df0f80d..7959e93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ Note: Don't forget to check out `preferences → Settings → Solidity Visual Developer` to customize features, look and feel. -## v0.2.0 - 🍂🍁🍃 Halloween! Booh! 👻🎃🎃🎃🌾👨🏼‍🌾 +## 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 diff --git a/src/features/whatsnew/whatsNew.js b/src/features/whatsnew/whatsNew.js index 2bcf3a2..8051056 100644 --- a/src/features/whatsnew/whatsNew.js +++ b/src/features/whatsnew/whatsNew.js @@ -38,7 +38,7 @@ ___ The complete changelog can be found [here](https://github.com/ConsenSys/vscode-solidity-auditor/blob/master/CHANGELOG.md). -## v0.2.0 - 🍂🍁🍃 Halloween! Booh! 👻🎃🎃🎃🌾👨🏼‍🌾 +## 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