diff --git a/src/app.js b/src/app.js index 6186455d3c..5737abea32 100644 --- a/src/app.js +++ b/src/app.js @@ -27,8 +27,6 @@ var Config = require('./config') var Renderer = require('./app/ui/renderer') var Compiler = require('remix-solidity').Compiler var executionContext = require('./execution-context') -var Debugger = require('./app/debugger/debugger') -var StaticAnalysis = require('./app/staticanalysis/staticAnalysisView') var FilePanel = require('./app/panels/file-panel') var EditorPanel = require('./app/panels/editor-panel') var RighthandPanel = require('./app/panels/righthand-panel') @@ -43,7 +41,6 @@ var BasicReadOnlyExplorer = require('./app/files/basicReadOnlyExplorer') var NotPersistedExplorer = require('./app/files/NotPersistedExplorer') var toolTip = require('./app/ui/tooltip') var TransactionReceiptResolver = require('./transactionReceiptResolver') -var SourceHighlighter = require('./app/editor/sourceHighlighter') var styleGuide = require('./app/ui/styles-guide/theme-chooser') var styles = styleGuide.chooser() @@ -113,6 +110,7 @@ var css = csjs` class App { constructor (api = {}, events = {}, opts = {}) { var self = this + this.event = new EventManager() self._components = {} registry.put({api: self, name: 'app'}) @@ -230,7 +228,7 @@ class App { } runCompiler () { const self = this - if (self._view.transactionDebugger.isActive) return + if (self._components.righthandpanel.debugger().isActive) return self._components.fileManager.saveCurrentFile() self._components.editorpanel.getEditor().clearAnnotations() @@ -259,7 +257,7 @@ class App { startdebugging (txHash) { const self = this self.event.trigger('debuggingRequested', []) - self._view.transactionDebugger.debug(txHash) + self._components.righthandpanel.debugger().debug(txHash) } loadFromGist (params) { const self = this @@ -388,10 +386,9 @@ Please make a backup of your contracts and start using http://remix.ethereum.org // ----------------- Compiler ----------------- self._components.compiler = new Compiler((url, cb) => self.importFileCb(url, cb)) - var compiler = self._components.compiler - registry.put({api: compiler, name: 'compiler'}) + registry.put({api: self._components.compiler, name: 'compiler'}) - var offsetToLineColumnConverter = new OffsetToLineColumnConverter(compiler.event) + var offsetToLineColumnConverter = new OffsetToLineColumnConverter(self._components.compiler.event) registry.put({api: offsetToLineColumnConverter, name: 'offsettolinecolumnconverter'}) // ----------------- UniversalDApp ----------------- @@ -407,15 +404,14 @@ Please make a backup of your contracts and start using http://remix.ethereum.org // ----------------- Tx listener ----------------- var transactionReceiptResolver = new TransactionReceiptResolver() - var compiledContracts = function () { - if (compiler.lastCompilationResult && compiler.lastCompilationResult.data) { - return compiler.lastCompilationResult.data.contracts - } - return null - } var txlistener = new Txlistener({ api: { - contracts: compiledContracts, + contracts: function () { + if (self._components.compiler.lastCompilationResult && self._components.compiler.lastCompilationResult.data) { + return self._components.compiler.lastCompilationResult.data.contracts + } + return null + }, resolveReceipt: function (tx, cb) { transactionReceiptResolver.resolve(tx, cb) } @@ -452,7 +448,6 @@ Please make a backup of your contracts and start using http://remix.ethereum.org self._components.editorpanel.event.register('resize', direction => self._adjustLayout(direction)) self._view.centerpanel.appendChild(self._components.editorpanel.render()) - var editor = self._components.editorpanel.getEditor() // The event listener needs to be registered as early as possible, because the // parent will send the message upon the "load" event. @@ -465,8 +460,6 @@ Please make a backup of your contracts and start using http://remix.ethereum.org } }, false) - this.event = new EventManager() - // Replace early callback with instant response loadFilesCallback = function (files) { self.loadFiles(files) @@ -478,67 +471,21 @@ Please make a backup of your contracts and start using http://remix.ethereum.org } // ---------------- FilePanel -------------------- - var filePanel = new FilePanel() - self._view.leftpanel.appendChild(filePanel.render()) - filePanel.event.register('resize', delta => self._adjustLayout('left', delta)) + self._components.filePanel = new FilePanel() + self._view.leftpanel.appendChild(self._components.filePanel.render()) + self._components.filePanel.event.register('resize', delta => self._adjustLayout('left', delta)) // ----------------- Renderer ----------------- var renderer = new Renderer() registry.put({api: renderer, name: 'renderer'}) - // ----------------- StaticAnalysis ----------------- - var staticanalysis = new StaticAnalysis() - registry.put({api: staticanalysis, name: 'staticanalysis'}) - // ---------------- Righthand-panel -------------------- self._components.righthandpanel = new RighthandPanel() self._view.rightpanel.appendChild(self._components.righthandpanel.render()) self._components.righthandpanel.init() self._components.righthandpanel.event.register('resize', delta => self._adjustLayout('right', delta)) - var node = document.getElementById('staticanalysisView') - node.insertBefore(staticanalysis.render(), node.childNodes[0]) - - // ----------------- Debugger ----------------- - self._view.transactionDebugger = new Debugger('#debugger', new SourceHighlighter()) - self._view.transactionDebugger.addProvider('vm', executionContext.vm()) - self._view.transactionDebugger.addProvider('injected', executionContext.internalWeb3()) - self._view.transactionDebugger.addProvider('web3', executionContext.internalWeb3()) - self._view.transactionDebugger.switchProvider(executionContext.getProvider()) - - var txLogger = new TxLogger() // eslint-disable-line - - var previousInput = '' - var saveTimeout = null - function editorOnChange () { - var currentFile = self._components.config.get('currentFile') - if (!currentFile) { - return - } - var input = editor.get(currentFile) - if (!input) { - return - } - // if there's no change, don't do anything - if (input === previousInput) { - return - } - previousInput = input - - // fire storage update - // NOTE: save at most once per 5 seconds - if (saveTimeout) { - window.clearTimeout(saveTimeout) - } - saveTimeout = window.setTimeout(() => { - fileManager.saveCurrentFile() - }, 5000) - } - - // auto save the file when content changed - editor.event.register('contentChanged', editorOnChange) - // save the file when switching - editor.event.register('sessionSwitched', editorOnChange) + var txLogger = new TxLogger() // eslint-disable-line executionContext.event.register('contextChanged', this, function (context) { self.runCompiler() @@ -552,8 +499,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org var queryParams = new QueryParams() // check init query parameters from the URL once the compiler is loaded - compiler.event.register('compilerLoaded', this, function (version) { - previousInput = '' + self._components.compiler.event.register('compilerLoaded', this, function (version) { self.runCompiler() if (queryParams.get().context) { diff --git a/src/app/contract/publishOnSwarm.js b/src/app/contract/publishOnSwarm.js index 0c2692a801..239d4344ff 100644 --- a/src/app/contract/publishOnSwarm.js +++ b/src/app/contract/publishOnSwarm.js @@ -3,7 +3,7 @@ var async = require('async') var swarmgw = require('swarmgw') -module.exports = (contract, appAPI, cb, swarmVerifiedPublishCallBack) => { +module.exports = (contract, fileManager, cb, swarmVerifiedPublishCallBack) => { // gather list of files to publish var sources = [] @@ -32,7 +32,7 @@ module.exports = (contract, appAPI, cb, swarmVerifiedPublishCallBack) => { return cb('Metadata inconsistency') } - appAPI.fileProviderOf(fileName).get(fileName, (error, content) => { + fileManager.fileProviderOf(fileName).get(fileName, (error, content) => { if (error) { console.log(error) } else { diff --git a/src/app/debugger/debugger.js b/src/app/debugger/debugger.js index 8d3e39a764..f0bcfd25c0 100644 --- a/src/app/debugger/debugger.js +++ b/src/app/debugger/debugger.js @@ -9,8 +9,7 @@ var globlalRegistry = require('../../global/registry') /** * Manage remix and source highlighting */ -function Debugger (id, sourceHighlighter, localRegistry) { - this.el = document.querySelector(id) +function Debugger (container, sourceHighlighter, localRegistry) { this._components = { sourceHighlighter: sourceHighlighter } @@ -32,7 +31,7 @@ function Debugger (id, sourceHighlighter, localRegistry) { } }) this.sourceMappingDecoder = new remixLib.SourceMappingDecoder() - this.el.appendChild(this.debugger.render()) + container.appendChild(this.debugger.render()) this.isActive = false this.breakPointManager = new remixCore.code.BreakpointManager(this.debugger, (sourceLocation) => { diff --git a/src/app/editor/editor.js b/src/app/editor/editor.js index a67e5dd4de..931e03e47c 100644 --- a/src/app/editor/editor.js +++ b/src/app/editor/editor.js @@ -7,6 +7,8 @@ var ace = require('brace') require('brace/theme/tomorrow_night_blue') +var globalRegistry = require('../../global/registry') + var Range = ace.acequire('ace/range').Range require('brace/ext/language_tools') require('brace/ext/searchbox') @@ -63,13 +65,19 @@ document.head.appendChild(yo` `) -function Editor (opts = {}) { +function Editor (opts = {}, localRegistry) { var self = this var el = yo`
` var editor = ace.edit(el) if (styles.appProperties.aceTheme) { editor.setTheme('ace/theme/' + styles.appProperties.aceTheme) } + self._components = {} + self._components.registry = localRegistry || globalRegistry + self._deps = { + fileManager: self._components.registry.get('filemanager').api, + config: self._components.registry.get('config').api + } ace.acequire('ace/ext/language_tools') editor.setOptions({ @@ -275,11 +283,15 @@ function Editor (opts = {}) { this.find = (string) => editor.find(string) + this.previousInput = '' + this.saveTimeout = null // Do setup on initialisation here editor.on('changeSession', function () { + editorOnChange(self) event.trigger('sessionSwitched', []) editor.getSession().on('change', function () { + editorOnChange(self) event.trigger('contentChanged', []) }) }) @@ -290,4 +302,29 @@ function Editor (opts = {}) { editor.resize(true) } +function editorOnChange (self) { + var currentFile = self._deps.config.get('currentFile') + if (!currentFile) { + return + } + var input = self.get(currentFile) + if (!input) { + return + } + // if there's no change, don't do anything + if (input === self.previousInput) { + return + } + self.previousInput = input + + // fire storage update + // NOTE: save at most once per 5 seconds + if (self.saveTimeout) { + window.clearTimeout(self.saveTimeout) + } + self.saveTimeout = window.setTimeout(() => { + self._deps.fileManager.saveCurrentFile() + }, 5000) +} + module.exports = Editor diff --git a/src/app/panels/righthand-panel.js b/src/app/panels/righthand-panel.js index aca26f259b..00921dcffa 100644 --- a/src/app/panels/righthand-panel.js +++ b/src/app/panels/righthand-panel.js @@ -57,7 +57,13 @@ module.exports = class RighthandPanel { pluginAPI, self._deps.app, self._deps.compiler, - self._deps.txlistener) + self._deps.txlistener + ) + + var analysisTab = new AnalysisTab(self._components.registry) + analysisTab.event.register('newStaticAnaysisWarningMessage', (msg, settings) => { self._components.compile.addWarning(msg, settings) }) + + self._components.debuggerTab = new DebuggerTab(self._components.registry) self._components = { pluginManager: pluginManager, @@ -65,8 +71,8 @@ module.exports = class RighthandPanel { 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), + analysis: analysisTab, + debug: self._components.debuggerTab, support: new SupportTab(self._components.registry), test: new TestTab(self._components.registry) } @@ -126,6 +132,10 @@ module.exports = class RighthandPanel { return self._view.element } + debugger () { + return this._components.debug.debugger() + } + focusOn (x) { if (this._components.tabbedMenu) this._components.tabbedMenu.selectTabByClassName(x) } diff --git a/src/app/tabs/analysis-tab.js b/src/app/tabs/analysis-tab.js index 16a7c06c04..f7a28c60a8 100644 --- a/src/app/tabs/analysis-tab.js +++ b/src/app/tabs/analysis-tab.js @@ -1,6 +1,7 @@ var yo = require('yo-yo') var csjs = require('csjs-inject') var remixLib = require('remix-lib') +var StaticAnalysis = require('../staticanalysis/staticAnalysisView') var globalRegistry = require('../../global/registry') var EventManager = remixLib.EventManager @@ -13,12 +14,25 @@ module.exports = class AnalysisTab { self.data = {} self._components = {} self._components.registry = localRegistry || globalRegistry + self._deps = { + rightHandPanel: self._components.registry.get('righthandpanel').api + } } render () { const self = this + var staticanalysis = new StaticAnalysis() + staticanalysis.event.register('staticAnaysisWarning', (count) => { + if (count > 0) { + 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._deps.rightHandPanel.focusOn('staticanalysisView'), useSpan: true } + self.event.trigger('newStaticAnaysisWarningMessage', [msg, settings]) + } + }) + self._components.registry.put({api: staticanalysis, name: 'staticanalysis'}) if (self._view.el) return self._view.el self._view.el = yo` - ` +