pull/5370/head
filip mertens 3 years ago
parent 3acfccd805
commit 5422aa7e99
  1. 6
      apps/solidity-compiler/src/app/compiler-api.ts
  2. 43
      libs/remix-core-plugin/src/lib/editor-context-listener.ts
  3. 4
      libs/remix-solidity/src/compiler/compiler-input.ts
  4. 2
      libs/remix-ui/editor-context-view/src/lib/remix-ui-editor-context-view.tsx
  5. 87
      libs/remix-ui/editor/src/lib/providers/completionProvider.ts
  6. 2
      libs/remix-ui/editor/src/lib/providers/hoverProvider.ts

@ -222,6 +222,7 @@ export const CompilerApiMixin = (Base) => class extends Base {
this.data.loading = true
this.data.loadingUrl = url
this.statusChanged({ key: 'loading', title: 'loading compiler...', type: 'info' })
this.emit('loadingCompiler', url)
}
this.compiler.event.register('loadingCompiler', this.data.eventHandlers.onLoadingCompiler)
@ -321,12 +322,9 @@ export const CompilerApiMixin = (Base) => class extends Base {
}
}
this.data.eventHandlers.onAstFinished = async (success, data, source, input, version) => {
this.emit('astFinished', source.target, source, 'soljson', data, input, version)
}
this.compiler.event.register('compilationFinished', this.data.eventHandlers.onCompilationFinished)
this.compiler.event.register('astFinished', this.data.eventHandlers.onAstFinished)
this.data.eventHandlers.onThemeChanged = (theme) => {
const invert = theme.quality === 'dark' ? 1 : 0

@ -43,6 +43,7 @@ export class EditorContextListener extends Plugin {
lastAST: any
compiler: any
onAstFinished: (success: any, data: any, source: any, input: any, version: any) => Promise<void>
constructor(astWalker) {
super(profile)
@ -56,20 +57,26 @@ export class EditorContextListener extends Plugin {
this.astWalker = astWalker
}
onActivation() {
async onActivation() {
this.on('editor', 'contentChanged', async () => {
await this.getAST()
this._stopHighlighting()
})
this.on('solidity', 'loadingCompiler', async(url) => {
console.log('loading compiler', url)
this.compiler.loadVersion(true, url)
})
this.compiler = new Compiler((url, cb) => this.call('contentImport', 'resolveAndSave', url, undefined, false).then((result) => cb(null, result)).catch((error) => cb(error.message)))
this.compiler.loadVersion(true, 'https://binaries.soliditylang.org/wasm/soljson-v0.8.7+commit.e28d00a7.js')
this.on('solidity', 'astFinished', async (file, source, languageVersion, data, input, version) => {
// console.log('compilation result', Object.keys(data.sources))
if (languageVersion.indexOf('soljson') !== 0 || !data.sources) return
this.onAstFinished = async (success, data, source, input, version) => {
if (!data.sources) return
if (data.sources && Object.keys(data.sources).length === 0) return
this.lastCompilationResult = new CompilerAbstract(languageVersion, data, source, input)
this.lastCompilationResult = new CompilerAbstract('soljson', data, source, input)
this._stopHighlighting()
this._index = {
@ -78,13 +85,15 @@ export class EditorContextListener extends Plugin {
}
this._buildIndex(data, source)
this.emit('astFinished')
})
}
this.compiler.event.register('astFinished', this.onAstFinished)
setInterval(async () => {
await this.compile()
}, 5000)
setInterval(async () => {
const compilationResult = this.lastCompilationResult // await this.call('compilerArtefacts', 'getLastCompilationResult')
if (compilationResult && compilationResult.languageversion.indexOf('soljson') === 0) {
@ -110,6 +119,12 @@ export class EditorContextListener extends Plugin {
async compile() {
try {
const state = await this.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.currentFile = await this.call('fileManager', 'file')
if (!this.currentFile) return
const content = await this.call('fileManager', 'readFile', this.currentFile)
@ -119,8 +134,8 @@ export class EditorContextListener extends Plugin {
}
}
async getBlockName(position: any) {
await this.getAST()
async getBlockName(position: any, text: string = null) {
await this.getAST(text)
const allowedTypes = ['SourceUnit', 'ContractDefinition', 'FunctionDefinition']
const walkAst = (node) => {
@ -137,19 +152,19 @@ export class EditorContextListener extends Plugin {
}
return null
}
if(!this.lastAST) return
return walkAst(this.lastAST)
}
async getAST() {
async getAST(text: string = null) {
this.currentFile = await this.call('fileManager', 'file')
if (!this.currentFile) return
let fileContent = await this.call('fileManager', 'readFile', this.currentFile)
let fileContent = text || await this.call('fileManager', 'readFile', this.currentFile)
try {
const ast = (SolidityParser as any).parse(fileContent, { loc: true, range: true, tolerant: true })
this.lastAST = ast
} catch (e) {
console.log(e)
}
console.log('LAST AST', this.lastAST)
return this.lastAST

@ -16,9 +16,9 @@ export default (sources: Source, opts: CompilerInputOptions): string => {
outputSelection: {
'*': {
'': ['ast'],
//'*': []
'*': []
//'*' : ['abi', 'metadata']
'*': ['abi', 'metadata', 'devdoc', 'userdoc', 'storageLayout', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates', 'evm.assembly']
//'*': ['abi', 'metadata', 'devdoc', 'userdoc', 'storageLayout', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates', 'evm.assembly']
}
}
}

@ -115,7 +115,7 @@ export function RemixUiEditorContextView (props: RemixUiEditorContextViewProps)
* show gas estimation
*/
const gasEstimation = (node) => {
if (node.nodeType === 'FunctionDefinition') {
if (node.nodeType === 'FunctionDefinition' && state && state.gasEstimation) {
const result: gasEstimationType = state.gasEstimation
const executionCost = ' Execution cost: ' + result.executionCost + ' gas'
const codeDepositCost = 'Code deposit cost: ' + result.codeDepositCost + ' gas'

@ -40,6 +40,9 @@ export class RemixCompletionProvider {
endColumn: position.column
});
const word = model.getWordUntilPosition(position);
const wordAt = model.getWordAtPosition(position);
const range = {
@ -69,16 +72,57 @@ export class RemixCompletionProvider {
const cursorPosition = this.props.editorAPI.getCursorPosition()
console.log('cursor', cursorPosition)
if (context.triggerCharacter === '.') {
console.log('TEXT', line)
const splits = line.split('.')
const textBeforeCursor = line.substring(0, position.column - 1)
const textAfterCursor = line.substring(position.column - 1)
console.log(textBeforeCursor, textAfterCursor)
const splits = textBeforeCursor.split('.')
console.log('splits', splits)
if (splits.length > 1) {
const last = splits[splits.length - 2].trim()
let last = splits[splits.length - 2].trim()
const lastParentheses = last.lastIndexOf('(')
const lastBracket = last.lastIndexOf('{')
const lastSemiColon = last.lastIndexOf(';')
let textBefore = null
let lastWord = null
let lineWithoutEdits = null
// find largest
const lastIndex = Math.max(lastParentheses, lastBracket, lastSemiColon)
if (lastIndex > -1) {
lastWord = last.substring(lastIndex + 1)
textBefore = last.substring(0, lastIndex + 1)
console.log('textBefore', textBefore)
console.log('text without edits', textBefore, textAfterCursor)
lineWithoutEdits = `${textBefore}${textAfterCursor}`
}
last = lastWord || last
console.log('last', last)
const cursorPosition = this.props.editorAPI.getCursorPosition()
const nodesAtPosition = await this.props.plugin.call('contextualListener', 'nodesAtEditorPosition', cursorPosition)
const lines = model.getLinesContent()
lines[position.lineNumber - 1] = lineWithoutEdits
const textWithoutEdits = lines.join('\n')
console.log('textWithoutEdits', textWithoutEdits)
let nodesAtPosition = await this.props.plugin.call('contextualListener', 'nodesAtEditorPosition', cursorPosition)
console.log('NODES AT POSITION', nodesAtPosition)
if (!nodesAtPosition.length) {
const block = await this.props.plugin.call('contextualListener', 'getBlockName', position, textWithoutEdits)
console.log('BLOCK', block)
if (block) {
nodesAtPosition = await this.props.plugin.call('contextualListener', 'nodesAtEditorPosition', block.range[0])
console.log('NODES AT POSITION', nodesAtPosition)
}
}
if (nodesAtPosition) {
for (const node of nodesAtPosition) {
const nodesOfScope = await this.props.plugin.call('contextualListener', 'nodesWithScope', node.id)
console.log('NODES OF SCOPE ', node.name, node.id, nodesOfScope)
@ -89,38 +133,29 @@ export class RemixCompletionProvider {
const declarationOf = await this.props.plugin.call('contextualListener', 'declarationOf', nodeOfScope.typeName)
console.log('HAS DECLARATION OF', declarationOf)
nodes = declarationOf.nodes
const baseContracts = await getlinearizedBaseContracts(declarationOf)
for (const baseContract of baseContracts) {
nodes = [...nodes, ...baseContract.nodes]
}
}
}
}
}
/*
console.log('TEXT', line)
const splits = line.split('.')
console.log('splits', splits)
if(splits.length > 1) {
const last = splits[splits.length - 2].trim()
console.log('last', last)
for(const node of Object.values(nodes) as any[]){
if(node.name === last) {
console.log('FOUND', node)
const cursorPosition = this.props.editorAPI.getCursorPosition()
const nodeAtPosition = await this.props.plugin.call('contextualListener', 'definitionAtPosition', cursorPosition)
console.log('NODE AT POSITION', nodeAtPosition)
if(nodeAtPosition && nodeAtPosition.nodeType === 'Block'){
if(node.scope && node.scope === nodeAtPosition.id) {
console.log('NODE IN SCOPE', node)
}
}
}
}
}
*/
} else {
const cursorPosition = this.props.editorAPI.getCursorPosition()
const nodesAtPosition = await this.props.plugin.call('contextualListener', 'nodesAtEditorPosition', cursorPosition)
let nodesAtPosition = await this.props.plugin.call('contextualListener', 'nodesAtEditorPosition', cursorPosition)
nodes = []
console.log('NODES AT POSITION', nodesAtPosition)
if (!nodesAtPosition.length) {
const block = await this.props.plugin.call('contextualListener', 'getBlockName', position, null)
console.log('BLOCK', block)
if (block) {
nodesAtPosition = await this.props.plugin.call('contextualListener', 'nodesAtEditorPosition', block.range[0])
console.log('NODES AT POSITION', nodesAtPosition)
}
}
for (const node of nodesAtPosition) {
const nodesOfScope = await this.props.plugin.call('contextualListener', 'nodesWithScope', node.id)
@ -198,7 +233,7 @@ export class RemixCompletionProvider {
const suggestions = []
for (const node of Object.values(nodes) as any[]) {
if(!node.name) continue
if (!node.name) continue
if (node.nodeType === 'VariableDeclaration') {
const completion = {
label: { label: `"${node.name}"`, description: await getLinks(node), detail: ` ${await getVariableDeclaration(node)}` },

@ -119,7 +119,7 @@ export class RemixHoverProvider {
if (!nodeAtPosition) {
contents.push({
value: 'No definition found. Please compile the source code.'
value: 'Loading...'
})
}

Loading…
Cancel
Save