diff --git a/src/app.js b/src/app.js index 01614597af..b319001302 100644 --- a/src/app.js +++ b/src/app.js @@ -313,6 +313,35 @@ class App { } }) } + importFileCb (url, filecb) { + const self = this + if (url.indexOf('/remix_tests.sol') !== -1) { + return filecb(null, remixTests.assertLibCode) + } + var provider = self._components.fileManager.fileProviderOf(url) + if (provider) { + provider.exists(url, (error, exist) => { + if (error) return filecb(error) + if (exist) { + return provider.get(url, filecb) + } else { + self.importExternal(url, filecb) + } + }) + } else if (self._components.compilerImport.isRelativeImport(url)) { + // try to resolve localhost modules (aka truffle imports) + var splitted = /([^/]+)\/(.*)$/g.exec(url) + async.tryEach([ + (cb) => { self.importFileCb('localhost/installed_contracts/' + url, cb) }, + (cb) => { if (!splitted) { cb('url not parseable' + url) } else { self.importFileCb('localhost/installed_contracts/' + splitted[1] + '/contracts/' + splitted[2], cb) } }, + (cb) => { self.importFileCb('localhost/node_modules/' + url, cb) }, + (cb) => { if (!splitted) { cb('url not parseable' + url) } else { self.importFileCb('localhost/node_modules/' + splitted[1] + '/contracts/' + splitted[2], cb) } }], + (error, result) => { filecb(error, result) } + ) + } else { + self.importExternal(url, filecb) + } + } } module.exports = App @@ -352,37 +381,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org } }) - function importFileCb (url, filecb) { - if (url.indexOf('/remix_tests.sol') !== -1) { - return filecb(null, remixTests.assertLibCode) - } - var provider = fileManager.fileProviderOf(url) - if (provider) { - provider.exists(url, (error, exist) => { - if (error) return filecb(error) - if (exist) { - return provider.get(url, filecb) - } else { - self.importExternal(url, filecb) - } - }) - } else if (self._components.compilerImport.isRelativeImport(url)) { - // try to resolve localhost modules (aka truffle imports) - var splitted = /([^/]+)\/(.*)$/g.exec(url) - async.tryEach([ - (cb) => { importFileCb('localhost/installed_contracts/' + url, cb) }, - (cb) => { if (!splitted) { cb('url not parseable' + url) } else { importFileCb('localhost/installed_contracts/' + splitted[1] + '/contracts/' + splitted[2], cb) } }, - (cb) => { importFileCb('localhost/node_modules/' + url, cb) }, - (cb) => { if (!splitted) { cb('url not parseable' + url) } else { importFileCb('localhost/node_modules/' + splitted[1] + '/contracts/' + splitted[2], cb) } }], - (error, result) => { filecb(error, result) } - ) - } else { - self.importExternal(url, filecb) - } - } - // ----------------- Compiler ----------------- - self._components.compiler = new Compiler(importFileCb) + self._components.compiler = new Compiler((url, cb) => self.importFileCb(url, cb)) var compiler = self._components.compiler registry.put({api: compiler, name: 'compiler'}) @@ -461,7 +461,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org } } }) - registry.put({api: eventsDecoder, name: 'eventsDecoder'}) + registry.put({api: eventsDecoder, name: 'eventsdecoder'}) txlistener.startListening() @@ -569,42 +569,11 @@ Please make a backup of your contracts and start using http://remix.ethereum.org } // ----------------- Renderer ----------------- - var rendererAPI = { - error: (file, error) => { - if (file === config.get('currentFile')) { - editor.addAnnotation(error) - } - }, - errorClick: (errFile, errLine, errCol) => { - if (errFile !== config.get('currentFile')) { - // TODO: refactor with this._components.contextView.jumpTo - var provider = fileManager.fileProviderOf(errFile) - if (provider) { - provider.exists(errFile, (error, exist) => { - if (error) return console.log(error) - fileManager.switchFile(errFile) - editor.gotoLine(errLine, errCol) - }) - } - } else { - editor.gotoLine(errLine, errCol) - } - } - } - var renderer = new Renderer(rendererAPI) + var renderer = new Renderer() registry.put({api: renderer, name: 'renderer'}) // ----------------- StaticAnalysis ----------------- - - var staticAnalysisAPI = { - renderWarning: (label, warningContainer, type) => { - return renderer.error(label, warningContainer, type) - }, - offsetToLineColumn: (location, file) => { - return offsetToLineColumnConverter.offsetToLineColumn(location, file, compiler.lastCompilationResult) - } - } - var staticanalysis = new StaticAnalysis(staticAnalysisAPI, compiler.event) + var staticanalysis = new StaticAnalysis() registry.put({api: staticanalysis, name: 'staticanalysis'}) // ---------------- Righthand-panel -------------------- @@ -671,23 +640,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org self._view.transactionDebugger.addProvider('web3', executionContext.internalWeb3()) self._view.transactionDebugger.switchProvider(executionContext.getProvider()) - var txLogger = new TxLogger({ - api: { - editorpanel: self._components.editorpanel, - resolvedTransaction: function (hash) { - return txlistener.resolvedTransaction(hash) - }, - parseLogs: function (tx, contractName, contracts, cb) { - eventsDecoder.parseLogs(tx, contractName, contracts, cb) - }, - compiledContracts: function () { - return compiledContracts() - } - }, - events: { - txListener: txlistener.event - } - }) + var txLogger = new TxLogger() txLogger.event.register('debugRequested', (hash) => { self.startdebugging(hash) diff --git a/src/app/execution/txLogger.js b/src/app/execution/txLogger.js index 68f0a9b774..73fe26a5df 100644 --- a/src/app/execution/txLogger.js +++ b/src/app/execution/txLogger.js @@ -13,6 +13,7 @@ var helper = require('../../lib/helper') var executionContext = require('../../execution-context') var modalDialog = require('../ui/modal-dialog-custom') var typeConversion = remixLib.execution.typeConversion +var globlalRegistry = require('../../global/registry') var css = csjs` .log { @@ -123,9 +124,8 @@ var css = csjs` * */ class TxLogger { - constructor (opts = {}) { + constructor (localRegistry) { this.event = new EventManager() - this.opts = opts this.seen = {} function filterTx (value, query) { if (value.length) { @@ -134,7 +134,17 @@ class TxLogger { return false } - this.logKnownTX = opts.api.editorpanel.registerCommand('knownTransaction', (args, cmds, append) => { + this._components = {} + this._components.registry = localRegistry || globlalRegistry + // dependencies + this._deps = { + editorPanel: this._components.registry.get('editorpanel').api, + txListener: this._components.registry.get('txlistener').api, + eventsDecoder: this._components.registry.get('eventsdecoder').api, + compiler: this._components.registry.get('compiler').api + } + + this.logKnownTX = this._deps.editorPanel.registerCommand('knownTransaction', (args, cmds, append) => { var data = args[0] var el if (data.tx.isCall) { @@ -146,46 +156,46 @@ class TxLogger { append(el) }, { activate: true, filterFn: filterTx }) - this.logUnknownTX = opts.api.editorpanel.registerCommand('unknownTransaction', (args, cmds, append) => { + this.logUnknownTX = this._deps.editorPanel.registerCommand('unknownTransaction', (args, cmds, append) => { var data = args[0] var el = renderUnknownTransaction(this, data) append(el) }, { activate: false, filterFn: filterTx }) - this.logEmptyBlock = opts.api.editorpanel.registerCommand('emptyBlock', (args, cmds, append) => { + this.logEmptyBlock = this._deps.editorPanel.registerCommand('emptyBlock', (args, cmds, append) => { var data = args[0] var el = renderEmptyBlock(this, data) append(el) }, { activate: true }) - opts.api.editorpanel.event.register('terminalFilterChanged', (type, label) => { + this._deps.editorPanel.event.register('terminalFilterChanged', (type, label) => { if (type === 'deselect') { if (label === 'only remix transactions') { - opts.api.editorpanel.updateTerminalFilter({ type: 'select', value: 'unknownTransaction' }) + this._deps.editorPanel.updateTerminalFilter({ type: 'select', value: 'unknownTransaction' }) } else if (label === 'all transactions') { - opts.api.editorpanel.updateTerminalFilter({ type: 'deselect', value: 'unknownTransaction' }) + this._deps.editorPanel.updateTerminalFilter({ type: 'deselect', value: 'unknownTransaction' }) } } else if (type === 'select') { if (label === 'only remix transactions') { - opts.api.editorpanel.updateTerminalFilter({ type: 'deselect', value: 'unknownTransaction' }) + this._deps.editorPanel.updateTerminalFilter({ type: 'deselect', value: 'unknownTransaction' }) } else if (label === 'all transactions') { - opts.api.editorpanel.updateTerminalFilter({ type: 'select', value: 'unknownTransaction' }) + this._deps.editorPanel.updateTerminalFilter({ type: 'select', value: 'unknownTransaction' }) } } }) - opts.events.txListener.register('newBlock', (block) => { + this._deps.txListener.event.register('newBlock', (block) => { if (!block.transactions.length) { this.logEmptyBlock({ block: block }) } }) - opts.events.txListener.register('newTransaction', (tx, receipt) => { - log(this, tx, receipt, opts.api) + this._deps.txListener.event.register('newTransaction', (tx, receipt) => { + log(this, tx, receipt) }) - opts.events.txListener.register('newCall', (tx) => { - log(this, tx, null, opts.api) + this._deps.txListener.event.register('newCall', (tx) => { + log(this, tx, null) }) } } @@ -199,10 +209,14 @@ function debug (e, data, self) { } } -function log (self, tx, receipt, api) { - var resolvedTransaction = api.resolvedTransaction(tx.hash) +function log (self, tx, receipt) { + var resolvedTransaction = self._deps.txListener.resolvedTransaction(tx.hash) if (resolvedTransaction) { - api.parseLogs(tx, resolvedTransaction.contractName, api.compiledContracts(), (error, logs) => { + var compiledContracts = null + if (self._deps.compiler.lastCompilationResult && self._deps.compiler.lastCompilationResult.data) { + compiledContracts = self._deps.compiler.lastCompilationResult.data.contracts + } + self._deps.eventsDecoder.parseLogs(tx, resolvedTransaction.contractName, compiledContracts, (error, logs) => { if (!error) { self.logKnownTX({ tx: tx, receipt: receipt, resolvedData: resolvedTransaction, logs: logs }) } diff --git a/src/app/panels/righthand-panel.js b/src/app/panels/righthand-panel.js index dbdd6baa71..c93c8902bb 100644 --- a/src/app/panels/righthand-panel.js +++ b/src/app/panels/righthand-panel.js @@ -32,16 +32,18 @@ module.exports = class RighthandPanel { dragbar: null } + self._components.registry.put({api: this, name: 'righthandpanel'}) + self._components = { - pluginManager: new PluginManager(), - tabbedMenu: new TabbedMenu(), - compile: new CompileTab(), - run: new RunTab(), - settings: new SettingsTab(), - analysis: new AnalysisTab(), - debug: new DebuggerTab(), - support: new SupportTab(), - test: new TestTab() + pluginManager: new PluginManager(self._components.registry), + tabbedMenu: new TabbedMenu(self._components.registry), + compile: new CompileTab(self._components.registry), + run: new RunTab(self._components.registry), + settings: new SettingsTab(self._components.registry), + analysis: new AnalysisTab(self._components.registry), + debug: new DebuggerTab(self._components.registry), + support: new SupportTab(self._components.registry), + test: new TestTab(self._components.registry) } self.event.register('plugin-loadRequest', json => { @@ -81,6 +83,11 @@ module.exports = class RighthandPanel { if (self._view.element) return self._view.element return self._view.element } + + focusOn (x) { + if (this._components.tabbedMenu) this._components.tabbedMenu.selectTabByClassName(x) + } + init () { // @TODO: init is for resizable drag bar only and should be refactored in the future const self = this diff --git a/src/app/staticanalysis/staticAnalysisView.js b/src/app/staticanalysis/staticAnalysisView.js index 174c5e37a0..ac2419d5f0 100644 --- a/src/app/staticanalysis/staticAnalysisView.js +++ b/src/app/staticanalysis/staticAnalysisView.js @@ -9,18 +9,27 @@ var styleGuide = require('../ui/styles-guide/theme-chooser') var styles = styleGuide.chooser() var css = require('./styles/staticAnalysisView-styles') +var globlalRegistry = require('../../global/registry') var EventManager = remixLib.EventManager -function staticAnalysisView (appAPI, compilerEvent) { +function staticAnalysisView (localRegistry) { + var self = this this.event = new EventManager() this.view = null - this.appAPI = appAPI this.runner = new StaticAnalysisRunner() this.modulesView = renderModules(this.runner.modules()) this.lastCompilationResult = null - var self = this - compilerEvent.register('compilationFinished', function (success, data, source) { + self._components = {} + self._components.registry = localRegistry || globlalRegistry + // dependencies + self._deps = { + compiler: self._components.registry.get('compiler').api, + renderer: self._components.registry.get('renderer').api, + offsetToLineColumnConverter: self._components.registry.get('offsetToLineColumnConverter').api + } + + self._deps.compiler.event.register('compilationFinished', function (success, data, source) { self.lastCompilationResult = null $('#staticanalysisresult').empty() if (success) { @@ -85,12 +94,12 @@ staticAnalysisView.prototype.run = function () { start: parseInt(split[0]), length: parseInt(split[1]) } - location = self.appAPI.offsetToLineColumn(location, file) + location = self._deps.offsetToLineColumnConverter.offsetToLineColumn(location, file) location = Object.keys(self.lastCompilationResult.contracts)[file] + ':' + (location.start.line + 1) + ':' + (location.start.column + 1) + ':' } warningCount++ var msg = yo`${location} ${item.warning} ${item.more ? yo`
more
` : yo``}
` - self.appAPI.renderWarning(msg, warningContainer, {type: 'staticAnalysisWarning', useSpan: true}) + self._deps.renderer.error(msg, warningContainer, {type: 'staticAnalysisWarning', useSpan: true}) }) }) if (warningContainer.html() === '') { diff --git a/src/app/tabs/compile-tab.js b/src/app/tabs/compile-tab.js index e8d228d781..a888263a51 100644 --- a/src/app/tabs/compile-tab.js +++ b/src/app/tabs/compile-tab.js @@ -40,7 +40,9 @@ module.exports = class CompileTab { compiler: self._components.registry.get('compiler').api, staticAnalysis: self._components.registry.get('staticanalysis').api, renderer: self._components.registry.get('renderer').api, - transactionContextAPI: self._components.registry.get('transactionContextAPI').api + fileManager: self._components.registry.get('filemanager').api, + transactionContextAPI: self._components.registry.get('transactionContextAPI').api, + rightHandPanel: self._components.registry.get('righthandpanel').api } self.data = { hideWarnings: self._deps.config.get('hideWarnings') || false, @@ -148,7 +150,7 @@ module.exports = class CompileTab { self._deps.staticAnalysis.event.register('staticAnaysisWarning', (count) => { if (count) { const msg = `Static Analysis raised ${count} warning(s) that requires your attention. Click here to show the warning(s).` - const settings = { type: 'staticAnalysisWarning', click: () => self._api.switchTab('staticanalysisView'), useSpan: true } + const settings = { type: 'staticAnalysisWarning', click: () => self._deps.rightHandPanel.focusOn('staticanalysisView'), useSpan: true } self._deps.renderer.error(msg, self._view.errorContainer, settings) } }) diff --git a/src/app/tabs/test-tab.js b/src/app/tabs/test-tab.js index 1c4d2f95e0..7e58a52282 100644 --- a/src/app/tabs/test-tab.js +++ b/src/app/tabs/test-tab.js @@ -77,7 +77,7 @@ module.exports = class TestTab { remixTests.runTestSources(runningTest, testCallback, resultsCallback, (error, result) => { updateFinalResult(error, result) callback(error) - }, this._deps.fileManager.importFileCb) + }, (url, cb) => { this._deps.app.importFileCb(url, cb) }) } }) } diff --git a/src/app/ui/renderer.js b/src/app/ui/renderer.js index 628af1114e..f90e756971 100644 --- a/src/app/ui/renderer.js +++ b/src/app/ui/renderer.js @@ -3,19 +3,52 @@ var $ = require('jquery') var yo = require('yo-yo') var css = require('./styles/renderer-styles') +var globlalRegistry = require('../../global/registry') /** * After refactor, the renderer is only used to render error/warning * TODO: This don't need to be an object anymore. Simplify and just export the renderError function. * */ -function Renderer (appAPI) { - this.appAPI = appAPI +function Renderer (localRegistry) { + const self = this + self._components = {} + self._components.registry = localRegistry || globlalRegistry + // dependencies + self._deps = { + editor: self._components.registry.get('editor').api, + fileManager: self._components.registry.get('filemanager').api, + config: self._components.registry.get('config').api + } if (document && document.head) { document.head.appendChild(css) } } +Renderer.prototype._error = function (file, error) { + const self = this + if (file === self._deps.config.get('currentFile')) { + self._deps.editor.addAnnotation(error) + } +} + +Renderer.prototype._errorClick = function (errFile, errLine, errCol) { + const self = this + if (errFile !== self._deps.config.get('currentFile')) { + // TODO: refactor with this._components.contextView.jumpTo + var provider = self._deps.fileManager.fileProviderOf(errFile) + if (provider) { + provider.exists(errFile, (error, exist) => { + if (error) return console.log(error) + self._deps.fileManager.switchFile(errFile) + self._deps.editor.gotoLine(errLine, errCol) + }) + } + } else { + self._deps.editor.gotoLine(errLine, errCol) + } +} + /** * format msg like error or warning, * @@ -45,7 +78,7 @@ Renderer.prototype.error = function (message, container, opt) { } if (!opt.noAnnotations && errLocation) { - this.appAPI.error(errLocation.errFile, { + this._error(errLocation.errFile, { row: errLocation.errLine, column: errLocation.errCol, text: text, @@ -60,7 +93,7 @@ Renderer.prototype.error = function (message, container, opt) { $error.click((ev) => { if (opt.errFile && opt.errLine) { - this.appAPI.errorClick(opt.errFile, opt.errLine, opt.errCol) + this._errorClick(opt.errFile, opt.errLine, opt.errCol) } else if (opt.click) { opt.click(message) }