|
|
|
@ -2,10 +2,10 @@ |
|
|
|
|
import { CompilerAbstract } from '@remix-project/remix-solidity' |
|
|
|
|
import { Compiler } from '@remix-project/remix-solidity' |
|
|
|
|
|
|
|
|
|
import { AstNode, CompilationError, CompilationResult, CompilationSource } from '@remix-project/remix-solidity' |
|
|
|
|
import { helper } from '@remix-project/remix-solidity' |
|
|
|
|
import { CompilationError, CompilationResult, CompilationSource } from '@remix-project/remix-solidity' |
|
|
|
|
import { CodeParser } from "../code-parser"; |
|
|
|
|
import { fileDecoration, fileDecorationType } from '@remix-ui/file-decorators' |
|
|
|
|
import { sourceMappingDecoder } from '@remix-project/remix-debug' |
|
|
|
|
|
|
|
|
|
export default class CodeParserCompiler { |
|
|
|
|
plugin: CodeParser |
|
|
|
@ -22,7 +22,9 @@ export default class CodeParserCompiler { |
|
|
|
|
init() { |
|
|
|
|
|
|
|
|
|
this.onAstFinished = async (success, data: CompilationResult, source: CompilationSource, input: any, version) => { |
|
|
|
|
console.log('compile success', success, data, this) |
|
|
|
|
|
|
|
|
|
console.log('compile success', success, data) |
|
|
|
|
|
|
|
|
|
this.plugin.call('editor', 'clearAnnotations') |
|
|
|
|
this.errorState = true |
|
|
|
|
const checkIfFatalError = (error: CompilationError) => { |
|
|
|
@ -40,21 +42,102 @@ export default class CodeParserCompiler { |
|
|
|
|
if (data.errors) { |
|
|
|
|
const sources = result.getSourceCode().sources |
|
|
|
|
for (const error of data.errors) { |
|
|
|
|
const pos = helper.getPositionDetails(error.formattedMessage) |
|
|
|
|
const filePosition = Object.keys(sources).findIndex((fileName) => fileName === error.sourceLocation.file) |
|
|
|
|
const lineColumn = await this.plugin.call('offsetToLineColumnConverter', 'offsetToLineColumn', |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(sources[error.sourceLocation.file].content) |
|
|
|
|
const lineColumn = sourceMappingDecoder.convertOffsetToLineColumn({ |
|
|
|
|
start: error.sourceLocation.start, |
|
|
|
|
length: error.sourceLocation.end - error.sourceLocation.start |
|
|
|
|
}, |
|
|
|
|
filePosition, |
|
|
|
|
result.getSourceCode().sources, |
|
|
|
|
null) |
|
|
|
|
}, lineBreaks) |
|
|
|
|
|
|
|
|
|
allErrors.push({ error, lineColumn }) |
|
|
|
|
} |
|
|
|
|
console.log('allErrors', allErrors) |
|
|
|
|
await this.plugin.call('editor', 'addErrorMarker', allErrors) |
|
|
|
|
this.addDecorators(allErrors, sources) |
|
|
|
|
} else { |
|
|
|
|
await this.plugin.call('editor', 'clearErrorMarkers', result.getSourceCode().sources) |
|
|
|
|
await this.clearDecorators(result.getSourceCode().sources) |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!data.sources) return |
|
|
|
|
if (data.sources && Object.keys(data.sources).length === 0) return |
|
|
|
|
this.plugin.lastCompilationResult = new CompilerAbstract('soljson', data, source, input) |
|
|
|
|
|
|
|
|
|
this.errorState = false |
|
|
|
|
this.plugin._index = { |
|
|
|
|
Declarations: {}, |
|
|
|
|
FlatReferences: {}, |
|
|
|
|
NodesPerFile: {}, |
|
|
|
|
} |
|
|
|
|
this.plugin._buildIndex(data, source) |
|
|
|
|
|
|
|
|
|
if (this.gastEstimateTimeOut) { |
|
|
|
|
window.clearTimeout(this.gastEstimateTimeOut) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.gastEstimateTimeOut = window.setTimeout(async () => { |
|
|
|
|
await this.plugin.gasService.showGasEstimates() |
|
|
|
|
}, 1000) |
|
|
|
|
|
|
|
|
|
console.log("INDEX", this.plugin._index) |
|
|
|
|
this.plugin.emit('astFinished') |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.compiler = new Compiler((url, cb) => this.plugin.call('contentImport', 'resolveAndSave', url, undefined, true).then((result) => cb(null, result)).catch((error) => cb(error.message))) |
|
|
|
|
this.compiler.event.register('compilationFinished', this.onAstFinished) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// COMPILER
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
*
|
|
|
|
|
* @returns
|
|
|
|
|
*/ |
|
|
|
|
async compile() { |
|
|
|
|
try { |
|
|
|
|
this.plugin.currentFile = await this.plugin.call('fileManager', 'file') |
|
|
|
|
if (this.plugin.currentFile && this.plugin.currentFile.endsWith('.sol')) { |
|
|
|
|
const state = await this.plugin.call('solidity', 'getCompilerState') |
|
|
|
|
console.log('COMPILER STATE', state) |
|
|
|
|
this.compiler.set('optimize', state.optimize) |
|
|
|
|
this.compiler.set('evmVersion', state.evmVersion) |
|
|
|
|
this.compiler.set('language', state.language) |
|
|
|
|
this.compiler.set('runs', state.runs) |
|
|
|
|
this.compiler.set('useFileConfiguration', true) |
|
|
|
|
|
|
|
|
|
const configFileContent = { |
|
|
|
|
"language": "Solidity", |
|
|
|
|
"settings": { |
|
|
|
|
"optimizer": { |
|
|
|
|
"enabled": false, |
|
|
|
|
"runs": 200 |
|
|
|
|
}, |
|
|
|
|
"outputSelection": { |
|
|
|
|
"*": { |
|
|
|
|
"": ["ast"], |
|
|
|
|
"*": ["evm.gasEstimates"] |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
"evmVersion": state.evmVersion && state.evmVersion.toString() || "byzantium", |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.compiler.set('configFileContent', JSON.stringify(configFileContent)) |
|
|
|
|
|
|
|
|
|
this.plugin.currentFile = await this.plugin.call('fileManager', 'file') |
|
|
|
|
console.log(this.plugin.currentFile) |
|
|
|
|
if (!this.plugin.currentFile) return |
|
|
|
|
const content = await this.plugin.call('fileManager', 'readFile', this.plugin.currentFile) |
|
|
|
|
const sources = { [this.plugin.currentFile]: { content } } |
|
|
|
|
this.compiler.compile(sources, this.plugin.currentFile) |
|
|
|
|
} |
|
|
|
|
} catch (e) { |
|
|
|
|
console.log(e) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async addDecorators(allErrors: any[], sources: any) { |
|
|
|
|
const errorsPerFiles = {} |
|
|
|
|
for (const error of allErrors) { |
|
|
|
|
if (!errorsPerFiles[error.error.sourceLocation.file]) { |
|
|
|
@ -78,11 +161,7 @@ export default class CodeParserCompiler { |
|
|
|
|
) |
|
|
|
|
sortedErrorsPerFiles[fileName] = errors |
|
|
|
|
} |
|
|
|
|
console.log('sortedErrorsPerFiles', sortedErrorsPerFiles) |
|
|
|
|
|
|
|
|
|
const filesWithOutErrors = Object.keys(sources).filter((fileName) => !sortedErrorsPerFiles[fileName]) |
|
|
|
|
|
|
|
|
|
console.log('filesWithOutErrors', filesWithOutErrors) |
|
|
|
|
// add decorators
|
|
|
|
|
const decorators: fileDecoration[] = [] |
|
|
|
|
for (const fileName in sortedErrorsPerFiles) { |
|
|
|
@ -115,13 +194,14 @@ export default class CodeParserCompiler { |
|
|
|
|
} |
|
|
|
|
decorators.push(decorator) |
|
|
|
|
} |
|
|
|
|
console.log(decorators) |
|
|
|
|
await this.plugin.call('fileDecorator', 'setFileDecorators', decorators) |
|
|
|
|
await this.plugin.call('editor', 'clearErrorMarkers', filesWithOutErrors) |
|
|
|
|
} else { |
|
|
|
|
await this.plugin.call('editor', 'clearErrorMarkers', result.getSourceCode().sources) |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async clearDecorators(sources: any) { |
|
|
|
|
const decorators: fileDecoration[] = [] |
|
|
|
|
for (const fileName of Object.keys(result.getSourceCode().sources)) { |
|
|
|
|
for (const fileName of Object.keys(sources)) { |
|
|
|
|
const decorator: fileDecoration = { |
|
|
|
|
path: fileName, |
|
|
|
|
isDirectory: false, |
|
|
|
@ -135,64 +215,9 @@ export default class CodeParserCompiler { |
|
|
|
|
} |
|
|
|
|
decorators.push(decorator) |
|
|
|
|
} |
|
|
|
|
console.log(decorators) |
|
|
|
|
|
|
|
|
|
await this.plugin.call('fileDecorator', 'setFileDecorators', decorators) |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!data.sources) return |
|
|
|
|
if (data.sources && Object.keys(data.sources).length === 0) return |
|
|
|
|
this.plugin.lastCompilationResult = new CompilerAbstract('soljson', data, source, input) |
|
|
|
|
|
|
|
|
|
this.errorState = false |
|
|
|
|
this.plugin._index = { |
|
|
|
|
Declarations: {}, |
|
|
|
|
FlatReferences: {}, |
|
|
|
|
NodesPerFile: {}, |
|
|
|
|
} |
|
|
|
|
this.plugin._buildIndex(data, source) |
|
|
|
|
|
|
|
|
|
if (this.gastEstimateTimeOut) { |
|
|
|
|
window.clearTimeout(this.gastEstimateTimeOut) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.gastEstimateTimeOut = window.setTimeout(async () => { |
|
|
|
|
await this.plugin.gasService.showGasEstimates() |
|
|
|
|
}, 1000) |
|
|
|
|
|
|
|
|
|
console.log("INDEX", this.plugin._index) |
|
|
|
|
this.plugin.emit('astFinished') |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.compiler = new Compiler((url, cb) => this.plugin.call('contentImport', 'resolveAndSave', url, undefined, true).then((result) => cb(null, result)).catch((error) => cb(error.message))) |
|
|
|
|
this.compiler.event.register('compilationFinished', this.onAstFinished) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// COMPILER
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
*
|
|
|
|
|
* @returns
|
|
|
|
|
*/ |
|
|
|
|
async compile() { |
|
|
|
|
try { |
|
|
|
|
const state = await this.plugin.call('solidity', 'getCompilerState') |
|
|
|
|
this.compiler.set('optimize', state.optimize) |
|
|
|
|
this.compiler.set('evmVersion', state.evmVersion) |
|
|
|
|
this.compiler.set('language', state.language) |
|
|
|
|
this.compiler.set('runs', state.runs) |
|
|
|
|
this.compiler.set('useFileConfiguration', state.useFileConfiguration) |
|
|
|
|
this.plugin.currentFile = await this.plugin.call('fileManager', 'file') |
|
|
|
|
console.log(this.plugin.currentFile) |
|
|
|
|
if (!this.plugin.currentFile) return |
|
|
|
|
const content = await this.plugin.call('fileManager', 'readFile', this.plugin.currentFile) |
|
|
|
|
const sources = { [this.plugin.currentFile]: { content } } |
|
|
|
|
this.compiler.compile(sources, this.plugin.currentFile) |
|
|
|
|
} catch (e) { |
|
|
|
|
console.log(e) |
|
|
|
|
} |
|
|
|
|
await this.plugin.call('fileDecorator', 'setFileDecorators', decorators) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |