diff --git a/libs/remix-core-plugin/src/lib/code-parser.ts b/libs/remix-core-plugin/src/lib/code-parser.ts index 64cbdcf8ab..671ba72c1d 100644 --- a/libs/remix-core-plugin/src/lib/code-parser.ts +++ b/libs/remix-core-plugin/src/lib/code-parser.ts @@ -31,6 +31,7 @@ export class CodeParser extends Plugin { currentFile: any _index: any astWalker: any + errorState: boolean = false onAstFinished: (success: any, data: CompilationResult, source: CompilationSource, input: any, version: any) => Promise constructor(astWalker) { @@ -70,6 +71,7 @@ export class CodeParser extends Plugin { this.onAstFinished = async (success, data: CompilationResult, source: CompilationSource, input: any, version) => { console.log('compile success', success, data, this) this.call('editor', 'clearAnnotations') + this.errorState = true let noFatalErrors = true // ie warnings are ok const checkIfFatalError = (error: CompilationError) => { // Ignore warnings and the 'Deferred import' error as those are generated by us as a workaround @@ -111,7 +113,7 @@ export class CodeParser extends Plugin { if (!data.sources) return if (data.sources && Object.keys(data.sources).length === 0) return this.lastCompilationResult = new CompilerAbstract('soljson', data, source, input) - + this.errorState = false this._index = { Declarations: {}, FlatReferences: {} @@ -120,8 +122,8 @@ export class CodeParser extends Plugin { this.emit('astFinished') } - 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.event.register('astFinished', this.onAstFinished) + this.compiler = new Compiler((url, cb) => this.call('contentImport', 'resolveAndSave', url, undefined, true).then((result) => cb(null, result)).catch((error) => cb(error.message))) + this.compiler.event.register('compilationFinished', this.onAstFinished) } // COMPILER @@ -263,6 +265,9 @@ export class CodeParser extends Plugin { } } }, + VariableDeclaration: (node) => { + nodes.push({ ...node, nodeType: node.type }) + }, UserDefinedTypeName: (node) => { nodes.push({ ...node, nodeType: node.type }) }, @@ -278,6 +283,12 @@ export class CodeParser extends Plugin { Identifier: function (node) { nodes.push({ ...node, nodeType: node.type }) }, + EventDefinition: function (node) { + nodes.push({ ...node, nodeType: node.type }) + }, + ModifierDefinition: function (node) { + nodes.push({ ...node, nodeType: node.type }) + }, InvalidNode: function (node) { nodes.push({ ...node, nodeType: node.type }) } @@ -296,7 +307,7 @@ export class CodeParser extends Plugin { const lastCompilationResult = this.lastCompilationResult if (!lastCompilationResult) return false const urlFromPath = await this.call('fileManager', 'getUrlFromPath', this.currentFile) - if (lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0 && lastCompilationResult.data) { + if (lastCompilationResult && lastCompilationResult.languageversion.indexOf('soljson') === 0 && lastCompilationResult.data && lastCompilationResult.data.sources && lastCompilationResult.data.sources[this.currentFile]) { const nodes = sourceMappingDecoder.nodesAtPosition(type, position, lastCompilationResult.data.sources[this.currentFile] || lastCompilationResult.data.sources[urlFromPath.file]) return nodes } @@ -322,7 +333,7 @@ export class CodeParser extends Plugin { * @returns */ async getDeclaration(id: any) { - if(this._index.Declarations && this._index.Declarations[id]) return this._index.Declarations[id] + if (this._index.Declarations && this._index.Declarations[id]) return this._index.Declarations[id] } /** @@ -375,7 +386,7 @@ export class CodeParser extends Plugin { console.log(this._index.FlatReferences) let nodeDefinition: any let node: any - if (nodes && nodes.length) { + if (nodes && nodes.length && !this.errorState) { node = nodes[nodes.length - 1] nodeDefinition = node if (!isNodeDefinition(node)) { @@ -399,11 +410,29 @@ export class CodeParser extends Plugin { if (!nodeDefinition) nodeDefinition = node } } + if (nodeDefinition && nodeDefinition.type && nodeDefinition.type === 'Identifier') { + const nodeForIdentifier = await this.findIdentifier(nodeDefinition) + if (nodeForIdentifier) nodeDefinition = nodeForIdentifier + } return nodeDefinition } } + /** + * + * @param identifierNode + * @returns + */ + async findIdentifier(identifierNode: any) { + let astNodes = await this.listAstNodes() + for (const node of astNodes) { + if (node.name === identifierNode.name && node.nodeType !== 'Identifier') { + return node + } + } + } + /** * * @param node @@ -570,13 +599,18 @@ export class CodeParser extends Plugin { */ async getVariableDeclaration(node: any) { if (node.typeDescriptions && node.typeDescriptions.typeString) { - return `${node.typeDescriptions.typeString}${node.name && node.name.length ? ` ${node.name}` : ''}` - } else + return `${node.typeDescriptions.typeString} ${node.visibility}${node.name && node.name.length ? ` ${node.name}` : ''}` + } else { if (node.typeName && node.typeName.name) { - return `${node.typeName.name}${node.name && node.name.length ? ` ${node.name}` : ''}` - } else { - return `${node.name && node.name.length ? ` ${node.name}` : ''}` + return `${node.typeName.name} ${node.visibility}${node.name && node.name.length ? ` ${node.name}` : ''}` + } + else if (node.typeName && node.typeName.namePath) { + return `${node.typeName.namePath} ${node.visibility}${node.name && node.name.length ? ` ${node.name}` : ''}` } + else { + return `${node.visibility}${node.name && node.name.length ? ` ${node.name}` : ''}` + } + } } /** diff --git a/libs/remix-solidity/src/compiler/compiler.ts b/libs/remix-solidity/src/compiler/compiler.ts index 39cccdfe5f..fda73c88f9 100644 --- a/libs/remix-solidity/src/compiler/compiler.ts +++ b/libs/remix-solidity/src/compiler/compiler.ts @@ -155,7 +155,6 @@ export class Compiler { if (!noFatalErrors) { // There are fatal errors, abort here this.state.lastCompilationResult = null - this.event.trigger('astFinished', [false, data, source, input, version]) 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 @@ -169,7 +168,6 @@ export class Compiler { source: source } } - this.event.trigger('astFinished', [true, data, source, input, version]) this.event.trigger('compilationFinished', [true, data, source, input, version]) } diff --git a/libs/remix-ui/editor/src/lib/providers/completionProvider.ts b/libs/remix-ui/editor/src/lib/providers/completionProvider.ts index 20040b9b67..7e8922f958 100644 --- a/libs/remix-ui/editor/src/lib/providers/completionProvider.ts +++ b/libs/remix-ui/editor/src/lib/providers/completionProvider.ts @@ -281,7 +281,7 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider private getContractCompletions = async (nodes: any[], position: Position) => { const cursorPosition = this.props.editorAPI.getCursorPosition() let nodesAtPosition = await this.props.plugin.call('codeParser', 'nodesAtPosition', cursorPosition) - + console.log('NODES AT POSITION', nodesAtPosition) // if no nodes exits at position, try to get the block of which the position is in if (!nodesAtPosition.length) { const block = await this.props.plugin.call('codeParser', 'getBlockAtPosition', position, null) @@ -291,7 +291,7 @@ export class RemixCompletionProvider implements languages.CompletionItemProvider } // get all children of all nodes at position - if (isArray(nodesAtPosition)) { + if (isArray(nodesAtPosition) && nodesAtPosition.length) { for (const node of nodesAtPosition) { const nodesOfScope = await this.props.plugin.call('codeParser', 'getNodesWithScope', node.id) for (const nodeOfScope of nodesOfScope) { diff --git a/libs/remix-ui/editor/src/lib/providers/hoverProvider.ts b/libs/remix-ui/editor/src/lib/providers/hoverProvider.ts index 1802674a1a..7647039528 100644 --- a/libs/remix-ui/editor/src/lib/providers/hoverProvider.ts +++ b/libs/remix-ui/editor/src/lib/providers/hoverProvider.ts @@ -74,25 +74,19 @@ export class RemixHoverProvider implements languages.HoverProvider { const getlinearizedBaseContracts = async (node: any) => { let params = [] - for (const id of node.linearizedBaseContracts) { - const baseContract = await this.props.plugin.call('codeParser', 'getNodeById', id) - params.push( - baseContract.name - ) + if (node.linearizedBaseContracts) { + for (const id of node.linearizedBaseContracts) { + const baseContract = await this.props.plugin.call('codeParser', 'getNodeById', id) + params.push( + baseContract.name + ) + } + if (params.length) + return `is ${params.join(', ')}` } - if (params.length) - return `is ${params.join(', ')}` return '' } - if (!nodeAtPosition) { - contents.push({ - value: 'Loading...' - }, { - value: 'Compilation errors' - }) - } - if (nodeAtPosition) { if (nodeAtPosition.absolutePath) { const target = await this.props.plugin.call('fileManager', 'getPathFromUrl', nodeAtPosition.absolutePath) @@ -105,23 +99,32 @@ export class RemixHoverProvider implements languages.HoverProvider { value: `${nodeAtPosition.absolutePath}` }) } - if (nodeAtPosition.typeDescriptions && nodeAtPosition.nodeType === 'VariableDeclaration') { + if (nodeAtPosition.nodeType === 'VariableDeclaration') { contents.push({ value: await getVariableDeclaration(nodeAtPosition) }) } - else if (nodeAtPosition.typeDescriptions && nodeAtPosition.nodeType === 'ElementaryTypeName') { + else if (nodeAtPosition.nodeType === 'ElementaryTypeName') { contents.push({ value: `${nodeAtPosition.typeDescriptions.typeString}` }) } else if (nodeAtPosition.nodeType === 'FunctionDefinition') { + if(!nodeAtPosition.name) return + const returns = await getReturnParameters(nodeAtPosition) contents.push({ - value: `function ${nodeAtPosition.name} ${await getParamaters(nodeAtPosition)} ${nodeAtPosition.visibility} ${nodeAtPosition.stateMutability}${await getOverrides(nodeAtPosition)} returns ${await getReturnParameters(nodeAtPosition)}` + value: `function ${nodeAtPosition.name} ${await getParamaters(nodeAtPosition)} ${nodeAtPosition.visibility} ${nodeAtPosition.stateMutability}${await getOverrides(nodeAtPosition)} ${returns? `returns ${returns}`: ''}` }) - + } else if (nodeAtPosition.nodeType === 'ModifierDefinition') { + contents.push({ + value: `modifier ${nodeAtPosition.name} ${await getParamaters(nodeAtPosition)}` + }) + } else if (nodeAtPosition.nodeType === 'EventDefinition') { + contents.push({ + value: `modifier ${nodeAtPosition.name} ${await getParamaters(nodeAtPosition)}` + }) } else if (nodeAtPosition.nodeType === 'ContractDefinition') { contents.push({ value: `${nodeAtPosition.contractKind} ${nodeAtPosition.name} ${await getlinearizedBaseContracts(nodeAtPosition)}` @@ -129,7 +132,7 @@ export class RemixHoverProvider implements languages.HoverProvider { } else if (nodeAtPosition.nodeType === 'InvalidNode') { contents.push({ - value: `Parsing error found!` + value: `There are errors in the code.` }) } else { contents.push({