Merge pull request #4063 from ethereum/fixcompiler2

Fixcompiler2
pull/4064/head
Aniket 1 year ago committed by GitHub
commit 573dfa93c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 77
      apps/remix-ide-e2e/src/tests/editorHoverContext.test.ts
  2. 9
      apps/remix-ide/src/app/plugins/parser/services/code-parser-compiler.ts
  3. 5
      apps/remix-ide/src/app/plugins/parser/services/code-parser-gas-service.ts
  4. 21
      libs/remix-solidity/src/compiler/compiler.ts
  5. 2
      libs/remix-solidity/src/compiler/types.ts

@ -17,7 +17,6 @@ module.exports = {
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, 'http://127.0.0.1:8080', false)
},
'Should load the test file': function (browser: NightwatchBrowser) {
browser.openFile('contracts')
.openFile('contracts/3_Ballot.sol')
@ -86,7 +85,47 @@ module.exports = {
const path = "//*[@class='view-line' and contains(.,'Voter') and contains(.,'struct')]//span//span[contains(.,'Voter')]"
const expectedContent = 'StructDefinition'
checkEditorHoverContent(browser, path, expectedContent)
}
},
'Add token file': function (browser: NightwatchBrowser) {
browser.addFile('contracts/mytoken.sol', {
content: myToken
}).useXpath().waitForElementVisible("//*[@class='view-line' and contains(.,'gas')]")
},
// here we change quickly between files to test the files being parsed correctly when switching between them
'Should show ERC20 hover over contract in editor #group1': function (browser: NightwatchBrowser) {
browser.scrollToLine(10)
const path = "//*[@class='view-line' and contains(.,'MyToken') and contains(.,'Pausable')]//span//span[contains(.,'ERC20Burnable')]"
const expectedContent = 'contract ERC20Burnable is ERC20Burnable, ERC20, IERC20Metadata, IERC20, Context'
checkEditorHoverContent(browser, path, expectedContent, 25)
},
'Go back to ballot file': function (browser: NightwatchBrowser) {
browser.openFile('contracts/3_Ballot.sol')
.useXpath().waitForElementVisible("//*[@class='view-line' and contains(.,'gas')]")
},
'Should show hover over function in editor again #group1': function (browser: NightwatchBrowser) {
browser
.scrollToLine(58)
const path: string = "//*[@class='view-line' and contains(.,'giveRightToVote(address') and contains(.,'function') and contains(.,'public')]//span//span[contains(.,'giveRightToVote')]"
let expectedContent = 'Estimated execution cost'
checkEditorHoverContent(browser, path, expectedContent)
expectedContent = 'function giveRightToVote (address internal voter) public nonpayable returns ()'
checkEditorHoverContent(browser, path, expectedContent)
expectedContent = "@dev Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'"
checkEditorHoverContent(browser, path, expectedContent)
},
'Open token file': function (browser: NightwatchBrowser) {
browser.openFile('contracts/mytoken.sol')
.useXpath().waitForElementVisible("//*[@class='view-line' and contains(.,'gas')]")
},
'Should show ERC20 hover over contract in editor again #group1': function (browser: NightwatchBrowser) {
browser.scrollToLine(10)
const path = "//*[@class='view-line' and contains(.,'MyToken') and contains(.,'Pausable')]//span//span[contains(.,'ERC20Burnable')]"
const expectedContent = 'contract ERC20Burnable is ERC20Burnable, ERC20, IERC20Metadata, IERC20, Context'
checkEditorHoverContent(browser, path, expectedContent, 25)
},
}
@ -233,4 +272,38 @@ contract BallotHoverTest {
winnerName_ = proposals[winningProposal()].name;
}
}
`
const myToken = `
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyToken is ERC20, ERC20Burnable, Pausable, Ownable {
constructor() ERC20("MyToken", "MTK") {}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
function _beforeTokenTransfer(address from, address to, uint256 amount)
internal
whenNotPaused
override
{
super._beforeTokenTransfer(from, to, amount);
}
}
`

@ -99,21 +99,24 @@ export default class CodeParserCompiler {
await this.clearDecorators(result.getSourceCode().sources)
}
if (!data.sources) return
if (data.sources && Object.keys(data.sources).length === 0) return
this.plugin.compilerAbstract = new CompilerAbstract('soljson', data, source, input)
this.errorState = false
this.plugin.nodeIndex = {
declarations: {},
flatReferences: {},
nodesPerFile: {},
}
this.plugin._buildIndex(data, source)
// cast from the remix-plugin interface to the solidity one. Should be fixed when remix-plugin move to the remix-project repository
this.plugin.nodeIndex.nodesPerFile[this.plugin.currentFile] = this.plugin._extractFileNodes(this.plugin.currentFile, this.plugin.compilerAbstract as unknown as lastCompilationResult)
const extractedFiledNodes = this.plugin._extractFileNodes(this.plugin.currentFile, this.plugin.compilerAbstract as unknown as lastCompilationResult)
if(extractedFiledNodes) {
this.plugin.nodeIndex.nodesPerFile[this.plugin.currentFile] = extractedFiledNodes
}
await this.plugin.gasService.showGasEstimates()
this.plugin.emit('astFinished')
}

@ -42,7 +42,10 @@ export default class CodeParserGasService {
}
this.plugin.currentFile = await this.plugin.call('fileManager', 'file')
// cast from the remix-plugin interface to the solidity one. Should be fixed when remix-plugin move to the remix-project repository
this.plugin.nodeIndex.nodesPerFile[this.plugin.currentFile] = await this.plugin._extractFileNodes(this.plugin.currentFile, this.plugin.compilerAbstract as unknown as lastCompilationResult)
const extractedFiledNodes = await this.plugin._extractFileNodes(this.plugin.currentFile, this.plugin.compilerAbstract as unknown as lastCompilationResult)
if(extractedFiledNodes) {
this.plugin.nodeIndex.nodesPerFile[this.plugin.currentFile] = extractedFiledNodes
}
const gasEstimates = await this.getGasEstimates(this.plugin.currentFile)

@ -81,12 +81,15 @@ export class Compiler {
* @param missingInputs missing import file path list
*/
internalCompile(files: Source, missingInputs?: string[]): void {
internalCompile(files: Source, missingInputs?: string[], timeStamp?: number): void {
if(timeStamp != this.state.compilationStartTime && this.state.compilerRetriggerMode == CompilerRetriggerMode.retrigger ) {
return
}
this.gatherImports(files, missingInputs, (error, input) => {
if (error) {
this.state.lastCompilationResult = null
this.event.trigger('compilationFinished', [false, { error: { formattedMessage: error, severity: 'error' } }, files, input, this.state.currentVersion])
} else if (this.state.compileJSON && input) { this.state.compileJSON(input) }
} else if (this.state.compileJSON && input) { this.state.compileJSON(input, timeStamp) }
})
}
@ -100,7 +103,7 @@ export class Compiler {
this.state.target = target
this.state.compilationStartTime = new Date().getTime()
this.event.trigger('compilationStarted', [])
this.internalCompile(files)
this.internalCompile(files, null, this.state.compilationStartTime)
}
/**
@ -157,7 +160,7 @@ export class Compiler {
* @param source Source
*/
onCompilationFinished(data: CompilationResult, missingInputs?: string[], source?: SourceWithTarget, input?: string, version?: string): void {
onCompilationFinished(data: CompilationResult, missingInputs?: string[], source?: SourceWithTarget, input?: string, version?: string, timeStamp?: number): void {
let noFatalErrors = true // ie warnings are ok
const checkIfFatalError = (error: CompilationError) => {
@ -173,7 +176,7 @@ export class Compiler {
this.event.trigger('compilationFinished', [false, data, source, input, version])
} else if (missingInputs !== undefined && missingInputs.length > 0 && source && source.sources) {
// try compiling again with the new set of inputs
this.internalCompile(source.sources, missingInputs)
this.internalCompile(source.sources, missingInputs, timeStamp)
} else {
data = this.updateInterface(data)
if (source) {
@ -292,6 +295,7 @@ export class Compiler {
this.state.worker.addEventListener('message', (msg: Record<'data', MessageFromWorker>) => {
const data: MessageFromWorker = msg.data
if (this.state.compilerRetriggerMode == CompilerRetriggerMode.retrigger && data.timestamp !== this.state.compilationStartTime) {
// drop message from previous compilation
return
}
switch (data.cmd) {
@ -312,7 +316,7 @@ export class Compiler {
sources = jobs[data.job].sources
delete jobs[data.job]
}
this.onCompilationFinished(result, data.missingInputs, sources, data.input, this.state.currentVersion)
this.onCompilationFinished(result, data.missingInputs, sources, data.input, this.state.currentVersion, data.timestamp)
}
break
}
@ -325,7 +329,7 @@ export class Compiler {
this.onCompilationFinished({ error: { formattedMessage } })
})
this.state.compileJSON = (source: SourceWithTarget) => {
this.state.compileJSON = (source: SourceWithTarget, timeStamp: number) => {
if (source && source.sources) {
const { optimize, runs, evmVersion, language, useFileConfiguration, configFileContent } = this.state
jobs.push({ sources: source })
@ -342,12 +346,11 @@ export class Compiler {
return
}
this.state.worker.postMessage({
cmd: 'compile',
job: jobs.length - 1,
input: input,
timestamp: this.state.compilationStartTime
timestamp: timeStamp
})
}
}

@ -160,7 +160,7 @@ export enum CompilerRetriggerMode {
}
export interface CompilerState {
compileJSON: ((input: SourceWithTarget) => void) | null,
compileJSON: ((input: SourceWithTarget, timeStamp?: number) => void) | null,
worker: any,
currentVersion: string| null| undefined,
compilerLicense: string| null

Loading…
Cancel
Save