Skip to content

Commit

Permalink
Merge pull request #2876 from ethereum/compilerAPI
Browse files Browse the repository at this point in the history
improve compiler api
  • Loading branch information
yann300 authored Jun 17, 2020
2 parents 73a20b8 + 30243b3 commit 64b5a09
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 11 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@
"nightwatch_local_fileExplorer": "nightwatch ./test-browser/tests/fileExplorer.test.js --config nightwatch.js --env chrome ",
"nightwatch_local_debugger": "nightwatch ./test-browser/tests/debugger.test.js --config nightwatch.js --env chrome ",
"nightwatch_local_editor": "nightwatch ./test-browser/tests/editor.test.js --config nightwatch.js --env chrome ",
"nightwatch_local_compiler": "nightwatch ./test-browser/tests/compiler_api.test.js --config nightwatch.js --env chrome ",
"nightwatch_local_runAndDeploy": "nightwatch ./test-browser/tests/runAndDeploy.js --config nightwatch.js --env chrome-runAndDeploy ",
"onchange": "onchange build/app.js -- npm-run-all lint",
"prepublish": "mkdirp build; npm-run-all -ls downloadsolc_root build",
Expand Down
4 changes: 4 additions & 0 deletions src/app/compiler/compiler-artefacts.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ module.exports = class CompilerArtefacts extends Plugin {
this.on('lexon', 'compilationFinished', (file, source, languageVersion, data) => {
this.compilersArtefacts['__last'] = new CompilerAbstract(languageVersion, data, source)
})

this.on('yulp', 'compilationFinished', (file, source, languageVersion, data) => {
this.compilersArtefacts['__last'] = new CompilerAbstract(languageVersion, data, source)
})
}

addResolvedContract (address, compilerData) {
Expand Down
1 change: 1 addition & 0 deletions src/app/compiler/compiler-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const compile = async (compilationTargets, settings) => {
const compiler = new Compiler(() => {})
compiler.set('evmVersion', settings.evmVersion)
compiler.set('optimize', settings.optimize)
compiler.set('language', settings.language)
compiler.loadVersion(canUseWorker(settings.version), urlFromVersion(settings.version))
compiler.event.register('compilationFinished', (success, compilationData, source) => {
if (!success) return reject(compilationData)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export default class FetchAndCompile extends Plugin {
// compile
const settings = {
version: data.metadata.compiler.version,
languageName: data.metadata.language,
language: data.metadata.language,
evmVersion: data.metadata.settings.evmVersion,
optimize: data.metadata.settings.optimizer.enabled
}
Expand Down
51 changes: 47 additions & 4 deletions src/app/tabs/compile-tab.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const CompilerContainer = require('./compileTab/compilerContainer.js')
import { ViewPlugin } from '@remixproject/engine'
import * as packageJson from '../../../package.json'
import publishToStorage from '../../publishToStorage'
import { compile } from '../compiler/compiler-helpers'

const profile = {
name: 'solidity',
Expand All @@ -31,7 +32,7 @@ const profile = {
location: 'sidePanel',
documentation: 'https://remix-ide.readthedocs.io/en/latest/solidity_editor.html',
version: packageJson.version,
methods: ['getCompilationResult', 'compile']
methods: ['getCompilationResult', 'compile', 'compileWithParameters', 'setCompilerConfig']

}

Expand Down Expand Up @@ -60,7 +61,8 @@ class CompileTab extends ViewPlugin {

this.data = {
contractsDetails: {},
eventHandlers: {}
eventHandlers: {},
loading: false
}
}

Expand Down Expand Up @@ -88,11 +90,13 @@ class CompileTab extends ViewPlugin {
this.editor.event.register('contentChanged', this.data.eventHandlers.onContentChanged)

this.data.eventHandlers.onLoadingCompiler = () => {
this.data.loading = true
this.emit('statusChanged', {key: 'loading', title: 'loading compiler...', type: 'info'})
}
this.compiler.event.register('loadingCompiler', this.data.eventHandlers.onLoadingCompiler)

this.data.eventHandlers.onCompilerLoaded = () => {
this.data.loading = false
this.emit('statusChanged', {key: 'none'})
}
this.compiler.event.register('compilerLoaded', this.data.eventHandlers.onCompilerLoaded)
Expand Down Expand Up @@ -198,11 +202,28 @@ class CompileTab extends ViewPlugin {
return this.compileTabLogic.compiler.state.lastCompilationResult
}

// This function is used by remix-plugin
/**
* compile using @arg fileName.
* The module UI will be updated accordingly to the new compilation result.
* This function is used by remix-plugin compiler API.
* @param {string} fileName to compile
*/
compile (fileName) {
addTooltip(yo`<div><b>${this.currentRequest.from}</b> is requiring to compile <b>${fileName}</b></div>`)
return this.compileTabLogic.compileFile(fileName)
}

/**
* compile using @arg compilationTargets and @arg settings
* The module UI will *not* be updated, the compilation result is returned
* This function is used by remix-plugin compiler API.
* @param {object} map of source files.
* @param {object} settings {evmVersion, optimize, compilerUrl, version, language}
*/
async compileWithParameters (compilationTargets, settings) {
return await compile(compilationTargets, settings)
}

// This function is used for passing the compiler remix-tests
getCurrentVersion () {
return this.compilerContainer.data.selectedVersion
Expand All @@ -217,6 +238,28 @@ class CompileTab extends ViewPlugin {
}
}

/**
* set the compiler configuration
* This function is used by remix-plugin compiler API.
* @param {object} settings {evmVersion, optimize, compilerUrl, version, language}
*/
setCompilerConfig (settings) {
return new Promise((resolve, reject) => {
addTooltip(yo`<div><b>${this.currentRequest.from}</b> is updating the <b>Solidity compiler configuration</b>.<pre class="text-left">${JSON.stringify(settings, null, '\t')}</pre></div>`)
this.compilerContainer.setConfiguration(settings)
// @todo(#2875) should use loading compiler return value to check whether the compiler is loaded instead of "setInterval"
let timeout = 0
const id = setInterval(() => {
timeout++
console.log(this.data.loading)
if (!this.data.loading || timeout > 10) {
resolve()
clearInterval(id)
}
}, 200)
})
}

/*********
* SUB-COMPONENTS
*/
Expand Down Expand Up @@ -261,7 +304,7 @@ class CompileTab extends ViewPlugin {
<span>Publish on Ipfs</span>
<img id="ipfsLogo" class="${css.storageLogo} ml-2" src="assets/img/ipfs.webp">
</button>
<button class="btn btn-secondary btn-block" title="Display Contract Details" onclick="${() => { this.details() }}">
<button data-id="compilation-details" class="btn btn-secondary btn-block" title="Display Contract Details" onclick="${() => { this.details() }}">
Compilation Details
</button>
<!-- Copy to Clipboard -->
Expand Down
2 changes: 1 addition & 1 deletion src/app/tabs/compileTab/compileTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class CompileTab {
const sources = { [target]: { content } }
this.event.emit('startingCompilation')
// setTimeout fix the animation on chrome... (animation triggered by 'staringCompilation')
setTimeout(() => this.compiler.compile(sources, target), 100)
setTimeout(() => { this.compiler.compile(sources, target); resolve() }, 100)
})
})
}
Expand Down
44 changes: 40 additions & 4 deletions src/app/tabs/compileTab/compilerContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -318,17 +318,21 @@ class CompilerContainer {
this.compileIfAutoCompileOn()
}

/*
The following functions are handlers for internal events.
*/

onchangeOptimize () {
this.compileTabLogic.setOptimize(!!this._view.optimize.checked)
this.compileIfAutoCompileOn()
}

onchangeLanguage (event) {
this.compileTabLogic.setLanguage(event.target.value)
onchangeLanguage () {
this.compileTabLogic.setLanguage(this._view.languageSelector.value)
this.compileIfAutoCompileOn()
}

onchangeEvmVersion (_) {
onchangeEvmVersion () {
let s = this._view.evmVersionSelector
let v = s.value
if (v === 'default') {
Expand All @@ -338,12 +342,44 @@ class CompilerContainer {
this.compileIfAutoCompileOn()
}

onchangeLoadVersion (event) {
onchangeLoadVersion () {
this.data.selectedVersion = this._view.versionSelector.value
this._updateVersionSelector()
this._updateLanguageSelector()
}

/*
The following functions map with the above event handlers.
They are an external API for modifying the compiler configuration.
*/

setConfiguration (settings) {
this.setLanguage(settings.language)
this.setEvmVersion(settings.evmVersion)
this.setOptimize(settings.optimize)
this.setVersion(settings.version)
}

setOptimize (enabled) {
this._view.optimize.checked = enabled
this.onchangeOptimize()
}

setLanguage (lang) {
this._view.languageSelector.value = lang
this.onchangeLanguage()
}

setEvmVersion (version) {
this._view.evmVersionSelector.value = version || 'default'
this.onchangeEvmVersion()
}

setVersion (version) {
this._view.versionSelector.value = `soljson-v${version}.js`
this.onchangeLoadVersion()
}

_shouldBeAdded (version) {
return !version.includes('nightly') ||
(version.includes('nightly') && this._view.includeNightlies.checked)
Expand Down
3 changes: 3 additions & 0 deletions src/app/tabs/runTab/model/dropdownlogic.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ class DropdownLogic {
this.runView.on('lexon', 'compilationFinished', (file, source, languageVersion, data) =>
broadcastCompilationResult(file, source, languageVersion, data)
)
this.runView.on('yulp', 'compilationFinished', (file, source, languageVersion, data) =>
broadcastCompilationResult(file, source, languageVersion, data)
)
}

loadContractFromAddress (address, confirmCb, cb) {
Expand Down
14 changes: 13 additions & 1 deletion test-browser/commands/verifyContracts.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const EventEmitter = require('events')

class VerifyContracts extends EventEmitter {
command (compiledContractNames, opts = { wait: 1000 }) {
command (compiledContractNames, opts = { wait: 1000, version: null }) {
this.api.perform((done) => {
verifyContracts(this.api, compiledContractNames, opts, () => {
done()
Expand All @@ -17,6 +17,18 @@ function getCompiledContracts (browser, opts, callback) {
.clickLaunchIcon('solidity')
.pause(opts.wait)
.waitForElementPresent('*[data-id="compiledContracts"] option')
.perform((done) => {
if (opts.version) {
browser
.click('*[data-id="compilation-details"]')
.waitForElementVisible('*[data-id="treeViewDivcompiler"]')
.pause(2000)
.click('*[data-id="treeViewDivcompiler"]')
.waitForElementVisible('*[data-id="treeViewLicompiler/version"]')
.assert.containsText('*[data-id="treeViewLicompiler/version"]', `version: ${opts.version}`)
.perform(done)
} else done()
})
.execute(function () {
var contracts = document.querySelectorAll('*[data-id="compiledContracts"] option')
if (!contracts) {
Expand Down
101 changes: 101 additions & 0 deletions test-browser/tests/compiler_api.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
'use strict'
var examples = require('../../src/app/editor/example-contracts')
var init = require('../helpers/init')
var sauce = require('./sauce')

var sources = [
{'browser/Untitled.sol': {content: examples.ballot.content}}
]

module.exports = {
before: function (browser, done) {
init(browser, done)
},
'@sources': function () {
return sources
},

'Should compile using "compileWithParamaters" API': function (browser) {
browser
.addFile('test_jsCompile.js', { content: jsCompile })
.executeScript('remix.exeCurrent()')
.pause(5000)
.journalChildIncludes('"languageversion": "0.6.8+commit.0bbfe453"')
},

'Should update the compiler configuration with "setCompilerConfig" API': function (browser) {
browser
.addFile('test_updateConfiguration.js', { content: updateConfiguration })
.executeScript('remix.exeCurrent()')
.pause(5000)
.addFile('test_updateConfiguration.sol', { content: simpleContract })
.verifyContracts(['StorageTestUpdateConfiguration'], {wait: 5000, version: '0.6.8+commit.0bbfe453'})
.end()
},

tearDown: sauce
}

const simpleContract = `pragma solidity >=0.4.22 <0.7.0;
/**
* @title Storage
* @dev Store & retreive value in a variable
*/
contract StorageTestUpdateConfiguration {
uint256 number;
/**
* @dev Store value in variable
* @param num value to store
*/
function store(uint256 num) public {
number = num;
}
/**
* @dev Return value
* @return value of 'number'
*/
function retreive() public view returns (uint256){
return number;
}
}
`

const jsCompile = `(async () => {
try {
const contract = {
"storage.sol": {content : \`${simpleContract}\` }
}
console.log('compile')
const params = {
optimize: false,
evmVersion: null,
language: 'Solidity',
version: '0.6.8+commit.0bbfe453',
compilerUrl: 'https://solc-bin.ethereum.org/bin/soljson-v0.6.8+commit.0bbfe453.js'
}
const result = await remix.call('solidity', 'compileWithParameters', contract, params)
console.log('result ', result)
} catch (e) {
console.log(e.message)
}
})()`

const updateConfiguration = `(async () => {
try {
const params = {
optimize: false,
evmVersion: null,
language: 'Solidity',
version: '0.6.8+commit.0bbfe453'
}
await remix.call('solidity', 'setCompilerConfig', params)
} catch (e) {
console.log(e.message)
}
})()`

0 comments on commit 64b5a09

Please sign in to comment.