Display compilation erros

pull/1339/head
ioedeveloper 3 years ago
parent d2ad317b89
commit 6302aed4ea
  1. 227
      apps/remix-ide/src/app/tabs/compile-tab.js
  2. 7
      libs/remix-ui/renderer/src/lib/renderer.tsx
  3. 5
      libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx
  4. 38
      libs/remix-ui/solidity-compiler/src/lib/solidity-compiler.tsx
  5. 4
      libs/remix-ui/solidity-compiler/src/lib/types/index.ts

@ -3,7 +3,6 @@ import React from 'react' // eslint-disable-line
import ReactDOM from 'react-dom'
import { SolidityCompiler, CompileTab as CompileTabLogic } from '@remix-ui/solidity-compiler' // eslint-disable-line
import { ViewPlugin } from '@remixproject/engine-web'
import { Renderer } from '@remix-ui/renderer'
import * as packageJson from '../../../../../package.json'
import publishToStorage from '../../publishToStorage'
import { compile } from '@remix-project/remix-solidity'
@ -11,17 +10,11 @@ import { compile } from '@remix-project/remix-solidity'
const EventEmitter = require('events')
const $ = require('jquery')
const yo = require('yo-yo')
const copy = require('copy-to-clipboard')
var QueryParams = require('../../lib/query-params')
const modalDialogCustom = require('../ui/modal-dialog-custom')
const parseContracts = require('./compileTab/contractParser')
const addTooltip = require('../ui/tooltip')
// const Renderer = require('../ui/renderer')
const globalRegistry = require('../../global/registry')
var css = require('./styles/compile-tab-styles')
// const CompilerContainer = require('./compileTab/compilerContainer.js')
const profile = {
name: 'solidity',
displayName: 'Solidity compiler',
@ -80,12 +73,8 @@ class CompileTab extends ViewPlugin {
}
resetResults () {
if (this._view.errorContainer) {
this._view.errorContainer.innerHTML = ''
}
this.currentFile = ''
this.contractsDetails = {}
yo.update(this._view.contractSelection, this.contractSelection())
this.emit('statusChanged', { key: 'none' })
this.renderComponent()
}
@ -120,9 +109,6 @@ class CompileTab extends ViewPlugin {
this.compiler.event.register('compilerLoaded', this.data.eventHandlers.onCompilerLoaded)
this.data.eventHandlers.onStartingCompilation = () => {
if (this._view.errorContainer) {
this._view.errorContainer.innerHTML = ''
}
this.emit('statusChanged', { key: 'loading', title: 'compiling...', type: 'info' })
}
@ -148,7 +134,7 @@ class CompileTab extends ViewPlugin {
this.fileManager.events.on('noFileSelected', this.data.eventHandlers.onNoFileSelected)
this.data.eventHandlers.onCompilationFinished = (success, data, source) => {
// this._view.errorContainer.appendChild(yo`<span data-id="compilationFinishedWith_${this.getCurrentVersion()}"></span>`)
this.compileErrors = data
if (success) {
// forwarding the event to the appManager infra
this.emit('compilationFinished', source.target, source, 'soljson', data)
@ -175,35 +161,6 @@ class CompileTab extends ViewPlugin {
// Update contract Selection
this.contractMap = {}
if (success) this.compiler.visitContracts((contract) => { this.contractMap[contract.name] = contract })
// const contractSelection = this.contractSelection(contractMap)
// yo.update(this._view.contractSelection, contractSelection)
if (data.error) {
// this.renderer.error(
// data.error.formattedMessage || data.error,
// this._view.errorContainer,
// { type: data.error.severity || 'error', errorType: data.error.type }
// )
if (data.error.mode === 'panic') {
return modalDialogCustom.alert(yo`
<div><i class="fas fa-exclamation-circle ${css.panicError}" aria-hidden="true"></i>
The compiler returned with the following internal error: <br> <b>${data.error.formattedMessage}.<br>
The compiler might be in a non-sane state, please be careful and do not use further compilation data to deploy to mainnet.
It is heavily recommended to use another browser not affected by this issue (Firefox is known to not be affected).</b><br>
Please join <a href="https://gitter.im/ethereum/remix" target="blank" >remix gitter channel</a> for more information.</div>`)
}
}
if (data.errors && data.errors.length) {
data.errors.forEach((err) => {
if (this.config.get('hideWarnings')) {
if (err.severity !== 'warning') {
// this.renderer.error(err.formattedMessage, this._view.errorContainer, { type: err.severity, errorType: err.type })
}
} else {
// this.renderer.error(err.formattedMessage, this._view.errorContainer, { type: err.severity, errorType: err.type })
}
})
}
this.renderComponent()
}
this.compiler.event.register('compilationFinished', this.data.eventHandlers.onCompilationFinished)
@ -259,11 +216,6 @@ class CompileTab extends ViewPlugin {
return res
}
// This function is used for passing the compiler remix-tests
getCurrentVersion () {
return this.compilerContainer.data.selectedVersion
}
// This function is used for passing the compiler configuration to 'remix-tests'
getCurrentCompilerConfig () {
return {
@ -296,82 +248,6 @@ class CompileTab extends ViewPlugin {
})
}
/*********
* SUB-COMPONENTS
*/
/**
* Section to select the compiled contract
* @param {string[]} contractList Names of the compiled contracts
*/
// contractSelection (contractMap) {
// // Return the file name of a path: ex "browser/ballot.sol" -> "ballot.sol"
// const getFileName = (path) => {
// const part = path.split('/')
// return part[part.length - 1]
// }
// const contractList = contractMap ? Object.keys(contractMap).map((key) => ({
// name: key,
// file: getFileName(contractMap[key].file)
// })) : []
// const selectEl = yo`
// <select
// onchange="${e => this.selectContract(e.target.value)}"
// data-id="compiledContracts" id="compiledContracts" class="custom-select"
// >
// ${contractList.map(({ name, file }) => yo`<option value="${name}">${name} (${file})</option>`)}
// </select>
// `
// // define swarm logo
// const result = contractList.length
// ? yo`<section class="${css.compilerSection} pt-3">
// <!-- Select Compiler Version -->
// <div class="mb-3">
// <label class="${css.compilerLabel} form-check-label" for="compiledContracts">Contract</label>
// ${selectEl}
// </div>
// <article class="mt-2 pb-0">
// <button id="publishOnSwarm" class="btn btn-secondary btn-block" title="Publish on Swarm" onclick="${() => { publishToStorage('swarm', this.fileProvider, this.fileManager, this.data.contractsDetails[this.selectedContract]) }}">
// <span>Publish on Swarm</span>
// <img id="swarmLogo" class="${css.storageLogo} ml-2" src="assets/img/swarm.webp">
// </button>
// <button id="publishOnIpfs" class="btn btn-secondary btn-block" title="Publish on Ipfs" onclick="${() => { publishToStorage('ipfs', this.fileProvider, this.fileManager, this.data.contractsDetails[this.selectedContract]) }}">
// <span>Publish on Ipfs</span>
// <img id="ipfsLogo" class="${css.storageLogo} ml-2" src="assets/img/ipfs.webp">
// </button>
// <button data-id="compilation-details" class="btn btn-secondary btn-block" title="Display Contract Details" onclick="${() => { this.details() }}">
// Compilation Details
// </button>
// <!-- Copy to Clipboard -->
// <div class="${css.contractHelperButtons}">
// <div class="input-group">
// <div class="btn-group" role="group" aria-label="Copy to Clipboard">
// <button class="btn ${css.copyButton}" title="Copy ABI to clipboard" onclick="${() => { this.copyABI() }}">
// <i class="${css.copyIcon} far fa-copy" aria-hidden="true"></i>
// <span>ABI</span>
// </button>
// <button class="btn ${css.copyButton}" title="Copy Bytecode to clipboard" onclick="${() => { this.copyBytecode() }}">
// <i class="${css.copyIcon} far fa-copy" aria-hidden="true"></i>
// <span>Bytecode</span>
// </button>
// </div>
// </div>
// </div>
// </div>
// </section>`
// : yo`<section class="${css.container} clearfix"><article class="px-2 mt-2 pb-0 d-flex">
// <span class="mt-2 mx-3 w-100 alert alert-warning" role="alert">No Contract Compiled Yet</span>
// </article></section>`
// if (contractList.length) {
// this.selectedContract = selectEl.value
// } else {
// delete this.selectedContract
// }
// return result
// }
// TODO : Add success alert when compilation succeed
contractCompiledSuccess () {
return yo`<div></div>`
@ -390,105 +266,6 @@ class CompileTab extends ViewPlugin {
this.selectedContract = contractName
}
// details () {
// const help = {
// Assembly: 'Assembly opcodes describing the contract including corresponding solidity source code',
// Opcodes: 'Assembly opcodes describing the contract',
// 'Runtime Bytecode': 'Bytecode storing the state and being executed during normal contract call',
// bytecode: 'Bytecode being executed during contract creation',
// functionHashes: 'List of declared function and their corresponding hash',
// gasEstimates: 'Gas estimation for each function call',
// metadata: 'Contains all informations related to the compilation',
// metadataHash: 'Hash representing all metadata information',
// abi: 'ABI: describing all the functions (input/output params, scope, ...)',
// name: 'Name of the compiled contract',
// swarmLocation: 'Swarm url where all metadata information can be found (contract needs to be published first)',
// web3Deploy: 'Copy/paste this code to any JavaScript/Web3 console to deploy this contract'
// }
// if (!this.selectedContract) throw new Error('No contract compiled yet')
// const contractProperties = this.contractsDetails[this.selectedContract]
// const log = yo`<div class="${css.detailsJSON}"></div>`
// Object.keys(contractProperties).map(propertyName => {
// const copyDetails = yo`<span class="${css.copyDetails}">${copyToClipboard(() => contractProperties[propertyName])}</span>`
// const questionMark = yo`<span class="${css.questionMark}"><i title="${help[propertyName]}" class="fas fa-question-circle" aria-hidden="true"></i></span>`
// log.appendChild(yo`<div class=${css.log}>
// <div class="${css.key}">${propertyName} ${copyDetails} ${questionMark}</div>
// ${this.insertValue(contractProperties, propertyName)}
// </div>`)
// })
// modalDialog(this.selectedContract, log, { label: '' }, { label: 'Close' })
// }
// insertValue (details, propertyName) {
// var node
// if (propertyName === 'web3Deploy' || propertyName === 'name' || propertyName === 'Assembly') {
// node = yo`<pre>${details[propertyName]}</pre>`
// } else if (propertyName === 'abi' || propertyName === 'metadata') {
// const treeView = new TreeView({
// extractData: function (item, parent, key) {
// var ret = {}
// if (item instanceof Array) {
// ret.children = item.map((item, index) => ({ key: index, value: item }))
// ret.self = ''
// } else if (item instanceof Object) {
// ret.children = Object.keys(item).map((key) => ({ key: key, value: item[key] }))
// ret.self = ''
// } else {
// ret.self = item
// ret.children = []
// }
// return ret
// }
// })
// if (details[propertyName] !== '') {
// try {
// node = yo`
// <div>
// ${treeView.render(typeof details[propertyName] === 'object' ? details[propertyName] : JSON.parse(details[propertyName]))}
// </div>` // catch in case the parsing fails.
// } catch (e) {
// node = yo`<div>Unable to display "${propertyName}": ${e.message}</div>`
// }
// } else {
// node = yo`<div> - </div>`
// }
// } else {
// node = yo`<div>${JSON.stringify(details[propertyName], null, 4)}</div>`
// }
// return yo`<pre class="${css.value}">${node || ''}</pre>`
// }
getContractProperty (property) {
if (!this.selectedContract) throw new Error('No contract compiled yet')
const contractProperties = this.contractsDetails[this.selectedContract]
return contractProperties[property] || null
}
copyContractProperty (property) {
let content = this.getContractProperty(property)
if (!content) {
addTooltip('No content available for ' + property)
return
}
try {
if (typeof content !== 'string') {
content = JSON.stringify(content, null, '\t')
}
} catch (e) {}
copy(content)
addTooltip('Copied value to clipboard')
}
copyABI () {
this.copyContractProperty('abi')
}
copyBytecode () {
this.copyContractProperty('bytecode')
}
render () {
this.renderComponent()
return this.el
@ -509,6 +286,7 @@ class CompileTab extends ViewPlugin {
contractsDetails={this.contractsDetails}
setHardHatCompilation={this.setHardHatCompilation}
contractMap={this.contractMap}
compileErrors={this.compileErrors || {}}
/>
, this.el)
}
@ -534,7 +312,6 @@ class CompileTab extends ViewPlugin {
}
onDeactivation () {
this.compilerContainer.deactivate()
this.editor.event.unregister('contentChanged', this.data.eventHandlers.onContentChanged)
this.compiler.event.unregister('loadingCompiler', this.data.eventHandlers.onLoadingCompiler)
this.compiler.event.unregister('compilerLoaded', this.data.eventHandlers.onCompilerLoaded)

@ -3,11 +3,12 @@ import React from 'react' //eslint-disable-line
interface RendererProps {
message: any;
opt: any,
warningErrors: any
editor: any
}
export const Renderer = ({ message, opt, editor }: RendererProps) => {
console.log('message: ', message)
console.log('opt: ', opt)
const getPositionDetails = (msg: any) => {
const result = { } as Record<string, number | string>
@ -50,8 +51,8 @@ export const Renderer = ({ message, opt, editor }: RendererProps) => {
</div>
<span className='d-flex flex-column' onClick={() => handlePointToErrorOnClick(opt.location, opt.fileName)}>
<span className='h6 font-weight-bold'>{opt.name}</span>
{ opt.item.warning }
{opt.item.more
{ opt.item && opt.item.warning }
{ opt.item && opt.item.more
? <span><a href={opt.item.more} target='_blank'>more</a></span>
: <span> </span>
}

@ -7,7 +7,7 @@ import { canUseWorker, baseURLBin, baseURLWasm, urlFromVersion, pathToURL, promi
import './css/style.css'
export const CompilerContainer = (props: CompilerContainerProps) => {
const { editor, config, queryParams, compileTabLogic, tooltip, modal, compiledFileName, setHardHatCompilation } = props // eslint-disable-line
const { editor, config, queryParams, compileTabLogic, tooltip, modal, compiledFileName, setHardHatCompilation, updateCurrentVersion } = props // eslint-disable-line
const [state, setState] = useState({
hideWarnings: false,
autoCompile: false,
@ -40,6 +40,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
setState(prevState => {
return { ...prevState, selectedVersion }
})
updateCurrentVersion(selectedVersion)
_updateVersionSelector()
}
})
@ -279,6 +280,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
setState(prevState => {
return { ...prevState, selectedVersion }
})
updateCurrentVersion(selectedVersion)
}
queryParams.update({ version: selectedVersion })
let url
@ -288,6 +290,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
setState(prevState => {
return { ...prevState, selectedVersion, customVersions: [...state.customVersions, selectedVersion] }
})
updateCurrentVersion(selectedVersion)
url = customUrl
queryParams.update({ version: selectedVersion })
} else if (selectedVersion === 'builtin') {

@ -4,11 +4,12 @@ import { CompilerContainer } from './compiler-container' // eslint-disable-line
import { ContractSelection } from './contract-selection'
import { Toaster } from '@remix-ui/toaster' // eslint-disable-line
import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line
import { Renderer } from '@remix-ui/renderer'
import './css/style.css'
export const SolidityCompiler = (props: SolidityCompilerProps) => {
const { editor, config, queryParams, plugin, compileTabLogic, compiledFileName, fileProvider, fileManager, contractsDetails, setHardHatCompilation, contractMap } = props
const { editor, config, queryParams, plugin, compileTabLogic, compiledFileName, fileProvider, fileManager, contractsDetails, setHardHatCompilation, contractMap, compileErrors } = props
const [state, setState] = useState({
contractsDetails: {},
eventHandlers: {},
@ -27,6 +28,10 @@ export const SolidityCompiler = (props: SolidityCompilerProps) => {
handleHide: null
}
})
useEffect(() => {
console.log('compileErrors: ', compileErrors)
}, [compileErrors])
const [currentVersion, setCurrentVersion] = useState('')
const toast = (message: string) => {
setState(prevState => {
@ -38,6 +43,10 @@ export const SolidityCompiler = (props: SolidityCompilerProps) => {
plugin.call('editor', 'clearAnnotations')
}
const updateCurrentVersion = (value) => {
setCurrentVersion(value)
}
const modal = async (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => {
await setState(prevState => {
return {
@ -62,12 +71,35 @@ export const SolidityCompiler = (props: SolidityCompilerProps) => {
})
}
const panicMessage = (message: string) => (
<div>
<i className="fas fa-exclamation-circle remixui_panicError" aria-hidden="true"></i>
The compiler returned with the following internal error: <br /> <b>{message}.<br />
The compiler might be in a non-sane state, please be careful and do not use further compilation data to deploy to mainnet.
It is heavily recommended to use another browser not affected by this issue (Firefox is known to not be affected).</b><br />
Please join <a href="https://gitter.im/ethereum/remix" target="blank" >remix gitter channel</a> for more information.
</div>
)
return (
<>
<div id="compileTabView">
<CompilerContainer editor={editor} config={config} queryParams={queryParams} compileTabLogic={compileTabLogic} tooltip={toast} modal={modal} compiledFileName={compiledFileName} setHardHatCompilation={setHardHatCompilation} />
<CompilerContainer editor={editor} config={config} queryParams={queryParams} compileTabLogic={compileTabLogic} tooltip={toast} modal={modal} compiledFileName={compiledFileName} setHardHatCompilation={setHardHatCompilation} updateCurrentVersion={updateCurrentVersion} />
<ContractSelection contractMap={contractMap} fileProvider={fileProvider} fileManager={fileManager} contractsDetails={contractsDetails} modal={modal} />
<div className="remixui_errorBlobs p-4" data-id="compiledErrors"></div>
<div className="remixui_errorBlobs p-4" data-id="compiledErrors">
<span data-id={`compilationFinishedWith_${currentVersion}`}></span>
{ compileErrors.error && <Renderer message={compileErrors.error.formattedMessage || compileErrors.error} editor={plugin} opt={{ type: compileErrors.error.severity || 'error', errorType: compileErrors.error.type }} /> }
{ compileErrors.error && (compileErrors.error.mode === 'panic') && modal('Error', panicMessage(compileErrors.error.formattedMessage), 'Close', null) }
{ compileErrors.errors && compileErrors.errors.length && compileErrors.errors.map((err) => {
if (config.get('hideWarnings')) {
if (err.severity !== 'warning') {
return <Renderer message={err.formattedMessage} editor={plugin} opt={{ type: err.severity, errorType: err.type }} />
}
} else {
return <Renderer message={err.formattedMessage} editor={plugin} opt={{ type: err.severity, errorType: err.type }} />
}
}) }
</div>
</div>
<Toaster message={state.toasterMsg} />
<ModalDialog

@ -14,6 +14,7 @@ export interface SolidityCompilerProps {
contractMap: {
file: string
} | Record<string, any>
compileErrors: any
}
export interface CompilerContainerProps {
@ -24,7 +25,8 @@ export interface CompilerContainerProps {
tooltip: (message: string) => void,
modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => void,
compiledFileName: string,
setHardHatCompilation: (value: boolean) => void
setHardHatCompilation: (value: boolean) => void,
updateCurrentVersion: any
}
export interface ContractSelectionProps {
contractMap: {

Loading…
Cancel
Save