Store compilation details for opened files

pull/5370/head
David Disu 3 years ago
parent a32446186f
commit 02d7a00d76
  1. 7
      apps/remix-ide/src/app/tabs/compile-tab.js
  2. 43
      apps/solidity-compiler/src/app/compiler-api.ts
  3. 15
      libs/remix-lib/src/types/ICompilerApi.ts
  4. 2
      libs/remix-ui/modal-dialog/src/lib/remix-ui-modal-dialog.tsx
  5. 22
      libs/remix-ui/solidity-compiler/src/lib/contract-selection.tsx
  6. 36
      libs/remix-ui/solidity-compiler/src/lib/solidity-compiler.tsx
  7. 16
      libs/remix-ui/solidity-compiler/src/lib/types/index.ts

@ -51,9 +51,9 @@ class CompileTab extends CompilerApiMixin(ViewPlugin) { // implements ICompilerA
this.renderComponent() this.renderComponent()
} }
onResetResults () { // onResetResults () {
this.renderComponent() // this.renderComponent()
} // }
onSetWorkspace () { onSetWorkspace () {
this.renderComponent() this.renderComponent()
@ -86,7 +86,6 @@ class CompileTab extends CompilerApiMixin(ViewPlugin) { // implements ICompilerA
} }
getFileManagerMode () { getFileManagerMode () {
this.emit()
return this.fileManager.mode return this.fileManager.mode
} }

@ -4,21 +4,22 @@ import type { ConfigurationSettings } from '@remix-project/remix-lib-ts'
export const CompilerApiMixin = (Base) => class extends Base { export const CompilerApiMixin = (Base) => class extends Base {
currentFile: string currentFile: string
contractMap: { compilationDetails: {
file: string contractMap: {
} | Record<string, any> file: string
} | Record<string, any>,
contractsDetails: Record<string, any>,
target?: string
}
compileErrors: any compileErrors: any
compileTabLogic: CompileTabLogic compileTabLogic: CompileTabLogic
contractsDetails: Record<string, any>
configurationSettings: ConfigurationSettings configurationSettings: ConfigurationSettings
onCurrentFileChanged: (fileName: string) => void onCurrentFileChanged: (fileName: string) => void
onResetResults: () => void // onResetResults: () => void
onSetWorkspace: (workspace: any) => void onSetWorkspace: (workspace: any) => void
onNoFileSelected: () => void onNoFileSelected: () => void
onCompilationFinished: (contractsDetails: any, contractMap: any) => void onCompilationFinished: (compilationDetails: { contractMap: { file: string } | Record<string, any>, contractsDetails: Record<string, any> }) => void
onSessionSwitched: () => void onSessionSwitched: () => void
onContentChanged: () => void onContentChanged: () => void
onFileClosed: (name: string) => void onFileClosed: (name: string) => void
@ -33,15 +34,15 @@ export const CompilerApiMixin = (Base) => class extends Base {
contractEl: null contractEl: null
} }
this.contractsDetails = {} this.compilationDetails = {
contractsDetails:{},
contractMap: {}
}
this.data = { this.data = {
eventHandlers: {}, eventHandlers: {},
loading: false loading: false
} }
this.contractMap = {}
this.contractsDetails = {}
this.compileErrors = {} this.compileErrors = {}
this.compiledFileName = '' this.compiledFileName = ''
this.currentFile = '' this.currentFile = ''
@ -190,9 +191,12 @@ export const CompilerApiMixin = (Base) => class extends Base {
resetResults () { resetResults () {
this.currentFile = '' this.currentFile = ''
this.contractsDetails = {} this.compilationDetails = {
contractsDetails: {},
contractMap: {}
}
this.statusChanged({ key: 'none' }) this.statusChanged({ key: 'none' })
if (this.onResetResults) this.onResetResults() // if (this.onResetResults) this.onResetResults()
} }
listenToEvents () { listenToEvents () {
@ -270,9 +274,9 @@ export const CompilerApiMixin = (Base) => class extends Base {
}) })
} else this.statusChanged({ key: 'succeed', title: 'compilation successful', type: 'success' }) } else this.statusChanged({ key: 'succeed', title: 'compilation successful', type: 'success' })
// Store the contracts // Store the contracts
this.contractsDetails = {} this.compilationDetails.contractsDetails = {}
this.compiler.visitContracts((contract) => { this.compiler.visitContracts((contract) => {
this.contractsDetails[contract.name] = parseContracts( this.compilationDetails.contractsDetails[contract.name] = parseContracts(
contract.name, contract.name,
contract.object, contract.object,
this.compiler.getSource(contract.file) this.compiler.getSource(contract.file)
@ -283,9 +287,10 @@ export const CompilerApiMixin = (Base) => class extends Base {
this.statusChanged({ key: count, title: `compilation failed with ${count} error${count > 1 ? 's' : ''}`, type: 'error' }) this.statusChanged({ key: count, title: `compilation failed with ${count} error${count > 1 ? 's' : ''}`, type: 'error' })
} }
// Update contract Selection // Update contract Selection
this.contractMap = {} this.compilationDetails.contractMap = {}
if (success) this.compiler.visitContracts((contract) => { this.contractMap[contract.name] = contract }) if (success) this.compiler.visitContracts((contract) => { this.compilationDetails.contractMap[contract.name] = contract })
if (this.onCompilationFinished) this.onCompilationFinished(this.contractsDetails, this.contractMap) this.compilationDetails.target = source.target
if (this.onCompilationFinished) this.onCompilationFinished(this.compilationDetails)
} }
this.compiler.event.register('compilationFinished', this.data.eventHandlers.onCompilationFinished) this.compiler.event.register('compilationFinished', this.data.eventHandlers.onCompilationFinished)

@ -1,11 +1,14 @@
export interface ICompilerApi { export interface ICompilerApi {
currentFile: string currentFile: string
contractMap: { compilationDetails: {
file: string contractMap: {
} | Record<string, any> file: string
} | Record<string, any>,
contractsDetails: Record<string, any>,
target?: string
}
compileErrors: any compileErrors: any
compileTabLogic: any compileTabLogic: any
contractsDetails: Record<string, any>
configurationSettings: ConfigurationSettings configurationSettings: ConfigurationSettings
getCompilerParameters: () => ConfigurationSettings getCompilerParameters: () => ConfigurationSettings
@ -20,7 +23,7 @@ export interface ICompilerApi {
getCompilationResult: () => any getCompilationResult: () => any
onCurrentFileChanged: (fileName: string) => void onCurrentFileChanged: (fileName: string) => void
onResetResults: () => void, // onResetResults: () => void,
onSetWorkspace: (workspace: any) => void onSetWorkspace: (workspace: any) => void
onNoFileSelected: () => void onNoFileSelected: () => void
onCompilationFinished: (contractsDetails: any, contractMap: any) => void onCompilationFinished: (contractsDetails: any, contractMap: any) => void
@ -39,7 +42,7 @@ export interface ICompilerApi {
compileWithHardhat: (configPath: string) => Promise<string> compileWithHardhat: (configPath: string) => Promise<string>
statusChanged: (data: { key: string, title?: string, type?: string }) => void, statusChanged: (data: { key: string, title?: string, type?: string }) => void,
emit: (key: string, ...payload: any) => void emit?: (key: string, ...payload: any) => void
} }
export type terminalLog = { export type terminalLog = {

@ -37,7 +37,7 @@ export const ModalDialog = (props: ModalDialogProps) => {
modal.current.addEventListener('blur', handleBlur) modal.current.addEventListener('blur', handleBlur)
} }
return () => { return () => {
modal.current.removeEventListener('blur', handleBlur) modal.current && modal.current.removeEventListener('blur', handleBlur)
} }
}, [modal.current]) }, [modal.current])

@ -7,32 +7,18 @@ import { CopyToClipboard } from '@remix-ui/clipboard' // eslint-disable-line
import './css/style.css' import './css/style.css'
export const ContractSelection = (props: ContractSelectionProps) => { export const ContractSelection = (props: ContractSelectionProps) => {
const { api, contractMap, contractsDetails, modal } = props const { api, contractsDetails, contractList, modal } = props
const [contractList, setContractList] = useState([])
const [selectedContract, setSelectedContract] = useState('') const [selectedContract, setSelectedContract] = useState('')
const [storage, setStorage] = useState(null) const [storage, setStorage] = useState(null)
useEffect(() => { useEffect(() => {
const contractList = contractMap ? Object.keys(contractMap).map((key) => ({
name: key,
file: getFileName(contractMap[key].file)
})) : []
setContractList(contractList)
if (contractList.length) setSelectedContract(contractList[0].name) if (contractList.length) setSelectedContract(contractList[0].name)
}, [contractMap, contractsDetails]) }, [contractList])
const resetStorage = () => { const resetStorage = () => {
setStorage('') setStorage('')
} }
// 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 handleContractChange = (contractName: string) => { const handleContractChange = (contractName: string) => {
setSelectedContract(contractName) setSelectedContract(contractName)
} }
@ -214,13 +200,13 @@ export const ContractSelection = (props: ContractSelectionProps) => {
<div className="remixui_contractHelperButtons"> <div className="remixui_contractHelperButtons">
<div className="input-group"> <div className="input-group">
<div className="btn-group" role="group" aria-label="Copy to Clipboard"> <div className="btn-group" role="group" aria-label="Copy to Clipboard">
<CopyToClipboard title="Copy ABI to clipboard" content={copyABI()} direction='top'> <CopyToClipboard title="Copy ABI to clipboard" getContent={copyABI} direction='top'>
<button className="btn remixui_copyButton" title="Copy ABI to clipboard"> <button className="btn remixui_copyButton" title="Copy ABI to clipboard">
<i className="remixui_copyIcon far fa-copy" aria-hidden="true"></i> <i className="remixui_copyIcon far fa-copy" aria-hidden="true"></i>
<span>ABI</span> <span>ABI</span>
</button> </button>
</CopyToClipboard> </CopyToClipboard>
<CopyToClipboard title="Copy ABI to clipboard" content={copyBytecode()} direction='top'> <CopyToClipboard title="Copy ABI to clipboard" getContent={copyBytecode} direction='top'>
<button className="btn remixui_copyButton" title="Copy Bytecode to clipboard"> <button className="btn remixui_copyButton" title="Copy Bytecode to clipboard">
<i className="remixui_copyIcon far fa-copy" aria-hidden="true"></i> <i className="remixui_copyIcon far fa-copy" aria-hidden="true"></i>
<span>Bytecode</span> <span>Bytecode</span>

@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react' // eslint-disable-line import React, { useEffect, useState } from 'react' // eslint-disable-line
import { CompileErrors, SolidityCompilerProps } from './types' import { CompileErrors, ContractsFile, SolidityCompilerProps } from './types'
import { CompilerContainer } from './compiler-container' // eslint-disable-line import { CompilerContainer } from './compiler-container' // eslint-disable-line
import { ContractSelection } from './contract-selection' // eslint-disable-line import { ContractSelection } from './contract-selection' // eslint-disable-line
import { Toaster } from '@remix-ui/toaster' // eslint-disable-line import { Toaster } from '@remix-ui/toaster' // eslint-disable-line
@ -9,12 +9,10 @@ import { Renderer } from '@remix-ui/renderer' // eslint-disable-line
import './css/style.css' import './css/style.css'
export const SolidityCompiler = (props: SolidityCompilerProps) => { export const SolidityCompiler = (props: SolidityCompilerProps) => {
const { api, api: { currentFile, compileTabLogic, contractsDetails, contractMap, configurationSettings } } = props const { api, api: { currentFile, compileTabLogic, configurationSettings } } = props
const [state, setState] = useState({ const [state, setState] = useState({
isHardhatProject: false, isHardhatProject: false,
currentFile, currentFile,
contractsDetails: {},
contractMap: {},
loading: false, loading: false,
compileTabLogic: null, compileTabLogic: null,
compiler: null, compiler: null,
@ -34,6 +32,7 @@ export const SolidityCompiler = (props: SolidityCompilerProps) => {
const [hideWarnings, setHideWarnings] = useState<boolean>(false) const [hideWarnings, setHideWarnings] = useState<boolean>(false)
const [compileErrors, setCompileErrors] = useState<Record<string, CompileErrors>>({ [currentFile]: api.compileErrors }) const [compileErrors, setCompileErrors] = useState<Record<string, CompileErrors>>({ [currentFile]: api.compileErrors })
const [badgeStatus, setBadgeStatus] = useState<Record<string, { key: string, title?: string, type?: string }>>({}) const [badgeStatus, setBadgeStatus] = useState<Record<string, { key: string, title?: string, type?: string }>>({})
const [contractsFile, setContractsFile] = useState<ContractsFile>({})
useEffect(() => { useEffect(() => {
(async () => { (async () => {
@ -50,15 +49,16 @@ export const SolidityCompiler = (props: SolidityCompilerProps) => {
} }
}, [badgeStatus[currentFile], currentFile]) }, [badgeStatus[currentFile], currentFile])
api.onCurrentFileChanged = (currentFile: string) => { // Return the file name of a path: ex "browser/ballot.sol" -> "ballot.sol"
setState(prevState => { const getFileName = (path) => {
return { ...prevState, currentFile } const part = path.split('/')
})
return part[part.length - 1]
} }
api.onResetResults = () => { api.onCurrentFileChanged = (currentFile: string) => {
setState(prevState => { setState(prevState => {
return { ...prevState, currentFile: '', contractsDetails: {}, contractMap: {} } return { ...prevState, currentFile }
}) })
} }
@ -76,10 +76,16 @@ export const SolidityCompiler = (props: SolidityCompilerProps) => {
setCompileErrors({} as Record<string, CompileErrors>) setCompileErrors({} as Record<string, CompileErrors>)
} }
api.onCompilationFinished = (contractsDetails: any, contractMap: any) => { api.onCompilationFinished = (compilationDetails: { contractMap: { file: string } | Record<string, any>, contractsDetails: Record<string, any>, target?: string }) => {
setState(prevState => { const { contractMap, contractsDetails, target } = compilationDetails
return { ...prevState, contractsDetails, contractMap } const contractList = contractMap ? Object.keys(contractMap).map((key) => {
}) return {
name: key,
file: getFileName(contractMap[key].file)
}
}) : []
setContractsFile({ ...contractsFile, [target]: { contractList, contractsDetails } })
setCompileErrors({ ...compileErrors, [currentFile]: api.compileErrors }) setCompileErrors({ ...compileErrors, [currentFile]: api.compileErrors })
} }
@ -143,7 +149,7 @@ export const SolidityCompiler = (props: SolidityCompilerProps) => {
<> <>
<div id="compileTabView"> <div id="compileTabView">
<CompilerContainer api={api} isHardhatProject={state.isHardhatProject} compileTabLogic={compileTabLogic} tooltip={toast} modal={modal} compiledFileName={currentFile} updateCurrentVersion={updateCurrentVersion} configurationSettings={configurationSettings} /> <CompilerContainer api={api} isHardhatProject={state.isHardhatProject} compileTabLogic={compileTabLogic} tooltip={toast} modal={modal} compiledFileName={currentFile} updateCurrentVersion={updateCurrentVersion} configurationSettings={configurationSettings} />
<ContractSelection api={api} contractMap={contractMap} contractsDetails={contractsDetails} modal={modal} /> { contractsFile[currentFile] && contractsFile[currentFile].contractsDetails && <ContractSelection api={api} contractsDetails={contractsFile[currentFile].contractsDetails} contractList={contractsFile[currentFile].contractList} modal={modal} /> }
{ compileErrors[currentFile] && { compileErrors[currentFile] &&
<div className="remixui_errorBlobs p-4" data-id="compiledErrors"> <div className="remixui_errorBlobs p-4" data-id="compiledErrors">
<span data-id={`compilationFinishedWith_${currentVersion}`}></span> <span data-id={`compilationFinishedWith_${currentVersion}`}></span>

@ -18,9 +18,7 @@ export interface CompilerContainerProps {
} }
export interface ContractSelectionProps { export interface ContractSelectionProps {
api: ICompilerApi, api: ICompilerApi,
contractMap: { contractList: { file: string, name: string }[],
file: string
} | Record<string, any>,
modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => void, modal: (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => void,
contractsDetails: Record<string, any> contractsDetails: Record<string, any>
} }
@ -31,7 +29,19 @@ interface CompileError {
formattedMessage?: string, formattedMessage?: string,
type?: string type?: string
} }
export interface CompileErrors { export interface CompileErrors {
error: CompileError, error: CompileError,
errors: CompileError[] errors: CompileError[]
} }
export interface CompilationDetails {
contractList: { file: string, name: string }[],
contractsDetails: Record<string, any>,
target?: string
}
export interface ContractsFile {
[currentFile: string]: CompilationDetails
}

Loading…
Cancel
Save