|
|
@ -1,25 +1,24 @@ |
|
|
|
'use strict' |
|
|
|
'use strict' |
|
|
|
var remixLib = require('remix-lib') |
|
|
|
const remixLib = require('remix-lib') |
|
|
|
var SourceMappingDecoder = remixLib.SourceMappingDecoder |
|
|
|
const SourceMappingDecoder = remixLib.SourceMappingDecoder |
|
|
|
var AstWalker = remixLib.AstWalker |
|
|
|
const AstWalker = remixLib.AstWalker |
|
|
|
var EventManager = require('../../lib/events') |
|
|
|
const EventManager = require('../../lib/events') |
|
|
|
var globalRegistry = require('../../global/registry') |
|
|
|
const globalRegistry = require('../../global/registry') |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
/* |
|
|
|
trigger contextChanged(nodes) |
|
|
|
trigger contextChanged(nodes) |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
class ContextualListener { |
|
|
|
class ContextualListener { |
|
|
|
constructor (opts, localRegistry) { |
|
|
|
constructor (opts, localRegistry) { |
|
|
|
var self = this |
|
|
|
|
|
|
|
this.event = new EventManager() |
|
|
|
this.event = new EventManager() |
|
|
|
self._components = {} |
|
|
|
this._components = {} |
|
|
|
self._components.registry = localRegistry || globalRegistry |
|
|
|
this._components.registry = localRegistry || globalRegistry |
|
|
|
self.editor = opts.editor |
|
|
|
this.editor = opts.editor |
|
|
|
self.pluginManager = opts.pluginManager |
|
|
|
this.pluginManager = opts.pluginManager |
|
|
|
self._deps = { |
|
|
|
this._deps = { |
|
|
|
compilersArtefacts: self._components.registry.get('compilersartefacts').api, |
|
|
|
compilersArtefacts: this._components.registry.get('compilersartefacts').api, |
|
|
|
config: self._components.registry.get('config').api, |
|
|
|
config: this._components.registry.get('config').api, |
|
|
|
offsetToLineColumnConverter: self._components.registry.get('offsettolinecolumnconverter').api |
|
|
|
offsetToLineColumnConverter: this._components.registry.get('offsettolinecolumnconverter').api |
|
|
|
} |
|
|
|
} |
|
|
|
this._index = { |
|
|
|
this._index = { |
|
|
|
Declarations: {}, |
|
|
|
Declarations: {}, |
|
|
@ -27,7 +26,7 @@ class ContextualListener { |
|
|
|
} |
|
|
|
} |
|
|
|
this._activeHighlights = [] |
|
|
|
this._activeHighlights = [] |
|
|
|
|
|
|
|
|
|
|
|
self.pluginManager.event.register('sendCompilationResult', (file, source, languageVersion, data) => { |
|
|
|
this.pluginManager.event.register('sendCompilationResult', (file, source, languageVersion, data) => { |
|
|
|
this._stopHighlighting() |
|
|
|
this._stopHighlighting() |
|
|
|
this._index = { |
|
|
|
this._index = { |
|
|
|
Declarations: {}, |
|
|
|
Declarations: {}, |
|
|
@ -36,13 +35,13 @@ class ContextualListener { |
|
|
|
this._buildIndex(data, source) |
|
|
|
this._buildIndex(data, source) |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
self.editor.event.register('contentChanged', () => { this._stopHighlighting() }) |
|
|
|
this.editor.event.register('contentChanged', () => { this._stopHighlighting() }) |
|
|
|
|
|
|
|
|
|
|
|
this.sourceMappingDecoder = new SourceMappingDecoder() |
|
|
|
this.sourceMappingDecoder = new SourceMappingDecoder() |
|
|
|
this.astWalker = new AstWalker() |
|
|
|
this.astWalker = new AstWalker() |
|
|
|
setInterval(() => { |
|
|
|
setInterval(() => { |
|
|
|
if (self._deps.compilersArtefacts['__last']) { |
|
|
|
if (this._deps.compilersArtefacts['__last']) { |
|
|
|
this._highlightItems(self.editor.getCursorPosition(), self._deps.compilersArtefacts['__last'], self._deps.config.get('currentFile')) |
|
|
|
this._highlightItems(this.editor.getCursorPosition(), this._deps.compilersArtefacts['__last'], this._deps.config.get('currentFile')) |
|
|
|
} |
|
|
|
} |
|
|
|
}, 1000) |
|
|
|
}, 1000) |
|
|
|
} |
|
|
|
} |
|
|
@ -73,7 +72,7 @@ class ContextualListener { |
|
|
|
this.currentPosition = cursorPosition |
|
|
|
this.currentPosition = cursorPosition |
|
|
|
this.currentFile = file |
|
|
|
this.currentFile = file |
|
|
|
if (compilationResult && compilationResult.data && compilationResult.data.sources[file]) { |
|
|
|
if (compilationResult && compilationResult.data && compilationResult.data.sources[file]) { |
|
|
|
var nodes = this.sourceMappingDecoder.nodesAtPosition(null, cursorPosition, compilationResult.data.sources[file]) |
|
|
|
const nodes = this.sourceMappingDecoder.nodesAtPosition(null, cursorPosition, compilationResult.data.sources[file]) |
|
|
|
this.nodes = nodes |
|
|
|
this.nodes = nodes |
|
|
|
if (nodes && nodes.length && nodes[nodes.length - 1]) { |
|
|
|
if (nodes && nodes.length && nodes[nodes.length - 1]) { |
|
|
|
this._highlightExpressions(nodes[nodes.length - 1], compilationResult) |
|
|
|
this._highlightExpressions(nodes[nodes.length - 1], compilationResult) |
|
|
@ -84,19 +83,18 @@ class ContextualListener { |
|
|
|
|
|
|
|
|
|
|
|
_buildIndex (compilationResult, source) { |
|
|
|
_buildIndex (compilationResult, source) { |
|
|
|
if (compilationResult && compilationResult.sources) { |
|
|
|
if (compilationResult && compilationResult.sources) { |
|
|
|
var self = this |
|
|
|
const callback = {} |
|
|
|
var callback = {} |
|
|
|
callback['*'] = (node) => { |
|
|
|
callback['*'] = function (node) { |
|
|
|
|
|
|
|
if (node && node.attributes && node.attributes.referencedDeclaration) { |
|
|
|
if (node && node.attributes && node.attributes.referencedDeclaration) { |
|
|
|
if (!self._index['Declarations'][node.attributes.referencedDeclaration]) { |
|
|
|
if (!this._index['Declarations'][node.attributes.referencedDeclaration]) { |
|
|
|
self._index['Declarations'][node.attributes.referencedDeclaration] = [] |
|
|
|
this._index['Declarations'][node.attributes.referencedDeclaration] = [] |
|
|
|
} |
|
|
|
} |
|
|
|
self._index['Declarations'][node.attributes.referencedDeclaration].push(node) |
|
|
|
this._index['Declarations'][node.attributes.referencedDeclaration].push(node) |
|
|
|
} |
|
|
|
} |
|
|
|
self._index['FlatReferences'][node.id] = node |
|
|
|
this._index['FlatReferences'][node.id] = node |
|
|
|
return true |
|
|
|
return true |
|
|
|
} |
|
|
|
} |
|
|
|
for (var s in compilationResult.sources) { |
|
|
|
for (const s in compilationResult.sources) { |
|
|
|
this.astWalker.walk(compilationResult.sources[s].legacyAST, callback) |
|
|
|
this.astWalker.walk(compilationResult.sources[s].legacyAST, callback) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -104,21 +102,19 @@ class ContextualListener { |
|
|
|
|
|
|
|
|
|
|
|
_highlight (node, compilationResult) { |
|
|
|
_highlight (node, compilationResult) { |
|
|
|
if (!node) return |
|
|
|
if (!node) return |
|
|
|
var self = this |
|
|
|
const position = this.sourceMappingDecoder.decode(node.src) |
|
|
|
var position = this.sourceMappingDecoder.decode(node.src) |
|
|
|
const eventId = this._highlightInternal(position, node) |
|
|
|
var eventId = this._highlightInternal(position, node) |
|
|
|
let lastCompilationResult = this._deps.compilersArtefacts['__last'] |
|
|
|
let lastCompilationResult = self._deps.compilersArtefacts['__last'] |
|
|
|
|
|
|
|
if (eventId && lastCompilationResult) { |
|
|
|
if (eventId && lastCompilationResult) { |
|
|
|
this._activeHighlights.push({ eventId, position, fileTarget: lastCompilationResult.getSourceName(position.file), nodeId: node.id }) |
|
|
|
this._activeHighlights.push({ eventId, position, fileTarget: lastCompilationResult.getSourceName(position.file), nodeId: node.id }) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_highlightInternal (position, node) { |
|
|
|
_highlightInternal (position, node) { |
|
|
|
var self = this |
|
|
|
let lastCompilationResult = this._deps.compilersArtefacts['__last'] |
|
|
|
let lastCompilationResult = self._deps.compilersArtefacts['__last'] |
|
|
|
|
|
|
|
if (lastCompilationResult) { |
|
|
|
if (lastCompilationResult) { |
|
|
|
var lineColumn = self._deps.offsetToLineColumnConverter.offsetToLineColumn(position, position.file, lastCompilationResult.getSourceCode().sources, lastCompilationResult.getAsts()) |
|
|
|
let lineColumn = this._deps.offsetToLineColumnConverter.offsetToLineColumn(position, position.file, lastCompilationResult.getSourceCode().sources, lastCompilationResult.getAsts()) |
|
|
|
var css = 'highlightreference' |
|
|
|
let css = 'highlightreference' |
|
|
|
if (node.children && node.children.length) { |
|
|
|
if (node.children && node.children.length) { |
|
|
|
// If node has children, highlight the entire line. if not, just highlight the current source position of the node.
|
|
|
|
// If node has children, highlight the entire line. if not, just highlight the current source position of the node.
|
|
|
|
css = 'highlightreference' |
|
|
|
css = 'highlightreference' |
|
|
@ -133,28 +129,27 @@ class ContextualListener { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
var fileName = lastCompilationResult.getSourceName(position.file) |
|
|
|
const fileName = lastCompilationResult.getSourceName(position.file) |
|
|
|
if (fileName) { |
|
|
|
if (fileName) { |
|
|
|
return self.editor.addMarker(lineColumn, fileName, css) |
|
|
|
return this.editor.addMarker(lineColumn, fileName, css) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return null |
|
|
|
return null |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_highlightExpressions (node, compilationResult) { |
|
|
|
_highlightExpressions (node, compilationResult) { |
|
|
|
var self = this |
|
|
|
const highlights = (id) => { |
|
|
|
function highlights (id) { |
|
|
|
if (this._index['Declarations'] && this._index['Declarations'][id]) { |
|
|
|
if (self._index['Declarations'] && self._index['Declarations'][id]) { |
|
|
|
const refs = this._index['Declarations'][id] |
|
|
|
var refs = self._index['Declarations'][id] |
|
|
|
for (const ref in refs) { |
|
|
|
for (var ref in refs) { |
|
|
|
const node = refs[ref] |
|
|
|
var node = refs[ref] |
|
|
|
this._highlight(node, compilationResult) |
|
|
|
self._highlight(node, compilationResult) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (node.attributes && node.attributes.referencedDeclaration) { |
|
|
|
if (node.attributes && node.attributes.referencedDeclaration) { |
|
|
|
highlights(node.attributes.referencedDeclaration) |
|
|
|
highlights(node.attributes.referencedDeclaration) |
|
|
|
var current = this._index['FlatReferences'][node.attributes.referencedDeclaration] |
|
|
|
const current = this._index['FlatReferences'][node.attributes.referencedDeclaration] |
|
|
|
this._highlight(current, compilationResult) |
|
|
|
this._highlight(current, compilationResult) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
highlights(node.id) |
|
|
|
highlights(node.id) |
|
|
@ -164,23 +159,21 @@ class ContextualListener { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_stopHighlighting () { |
|
|
|
_stopHighlighting () { |
|
|
|
var self = this |
|
|
|
for (const eventKey in this._activeHighlights) { |
|
|
|
for (var eventKey in this._activeHighlights) { |
|
|
|
const event = this._activeHighlights[eventKey] |
|
|
|
var event = this._activeHighlights[eventKey] |
|
|
|
this.editor.removeMarker(event.eventId, event.fileTarget) |
|
|
|
self.editor.removeMarker(event.eventId, event.fileTarget) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
this._activeHighlights = [] |
|
|
|
this._activeHighlights = [] |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
gasEstimation (node) { |
|
|
|
gasEstimation (node) { |
|
|
|
this._loadContractInfos(node) |
|
|
|
this._loadContractInfos(node) |
|
|
|
var executionCost |
|
|
|
let executionCost, codeDepositCost |
|
|
|
var codeDepositCost |
|
|
|
|
|
|
|
if (node.name === 'FunctionDefinition') { |
|
|
|
if (node.name === 'FunctionDefinition') { |
|
|
|
var visibility = node.attributes.visibility |
|
|
|
const visibility = node.attributes.visibility |
|
|
|
if (!node.attributes.isConstructor) { |
|
|
|
if (!node.attributes.isConstructor) { |
|
|
|
var fnName = node.attributes.name |
|
|
|
const fnName = node.attributes.name |
|
|
|
var fn = fnName + this._getInputParams(node) |
|
|
|
const fn = fnName + this._getInputParams(node) |
|
|
|
if (visibility === 'public' || visibility === 'external') { |
|
|
|
if (visibility === 'public' || visibility === 'external') { |
|
|
|
executionCost = this.estimationObj.external[fn] |
|
|
|
executionCost = this.estimationObj.external[fn] |
|
|
|
} else if (visibility === 'private' || visibility === 'internal') { |
|
|
|
} else if (visibility === 'private' || visibility === 'internal') { |
|
|
@ -197,9 +190,9 @@ class ContextualListener { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_loadContractInfos (node) { |
|
|
|
_loadContractInfos (node) { |
|
|
|
for (var i in this.nodes) { |
|
|
|
for (const i in this.nodes) { |
|
|
|
if (this.nodes[i].id === node.attributes.scope) { |
|
|
|
if (this.nodes[i].id === node.attributes.scope) { |
|
|
|
var contract = this.nodes[i] |
|
|
|
const contract = this.nodes[i] |
|
|
|
this.contract = this.results.data.contracts[this.results.source.target][contract.attributes.name] |
|
|
|
this.contract = this.results.data.contracts[this.results.source.target][contract.attributes.name] |
|
|
|
this.estimationObj = this.contract.evm.gasEstimates |
|
|
|
this.estimationObj = this.contract.evm.gasEstimates |
|
|
|
this.creationCost = this.estimationObj.creation.totalCost |
|
|
|
this.creationCost = this.estimationObj.creation.totalCost |
|
|
@ -209,16 +202,17 @@ class ContextualListener { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_getInputParams (node) { |
|
|
|
_getInputParams (node) { |
|
|
|
var params = [] |
|
|
|
const params = [] |
|
|
|
for (var i in node.children) { |
|
|
|
let target |
|
|
|
|
|
|
|
for (const i in node.children) { |
|
|
|
if (node.children[i].name === 'ParameterList') { |
|
|
|
if (node.children[i].name === 'ParameterList') { |
|
|
|
var target = node.children[i] |
|
|
|
target = node.children[i] |
|
|
|
break |
|
|
|
break |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (target) { |
|
|
|
if (target) { |
|
|
|
var children = target.children |
|
|
|
const children = target.children |
|
|
|
for (var j in children) { |
|
|
|
for (const j in children) { |
|
|
|
if (children[j].name === 'VariableDeclaration') { |
|
|
|
if (children[j].name === 'VariableDeclaration') { |
|
|
|
params.push(children[j].attributes.type) |
|
|
|
params.push(children[j].attributes.type) |
|
|
|
} |
|
|
|
} |
|
|
|