|
|
@ -477,42 +477,65 @@ export class CodeParser extends Plugin { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
async definitionAtPosition(position: number) { |
|
|
|
async definitionAtPosition(position: number) { |
|
|
|
const nodes = await this.nodesAtPosition(position) |
|
|
|
const nodes = await this.nodesAtPosition(position) |
|
|
|
let nodeDefinition: any |
|
|
|
let nodeDefinition = { |
|
|
|
|
|
|
|
'ast': null, |
|
|
|
|
|
|
|
'parser': null |
|
|
|
|
|
|
|
} |
|
|
|
let node: genericASTNode |
|
|
|
let node: genericASTNode |
|
|
|
if (nodes && nodes.length && !this.errorState) { |
|
|
|
if (nodes && nodes.length && !this.errorState) { |
|
|
|
node = nodes[nodes.length - 1] |
|
|
|
node = nodes[nodes.length - 1] |
|
|
|
nodeDefinition = node |
|
|
|
let astNodeDefinition = node |
|
|
|
if (!isNodeDefinition(node)) { |
|
|
|
if (!isNodeDefinition(node)) { |
|
|
|
nodeDefinition = (await this.declarationOf(node)) || node |
|
|
|
astNodeDefinition = (await this.declarationOf(node)) || node |
|
|
|
} |
|
|
|
} |
|
|
|
if (node.nodeType === 'ImportDirective') { |
|
|
|
if (node.nodeType === 'ImportDirective') { |
|
|
|
for (const key in this.nodeIndex.flatReferences) { |
|
|
|
for (const key in this.nodeIndex.flatReferences) { |
|
|
|
if (this.nodeIndex.flatReferences[key].id === node.sourceUnit) { |
|
|
|
if (this.nodeIndex.flatReferences[key].id === node.sourceUnit) { |
|
|
|
nodeDefinition = this.nodeIndex.flatReferences[key] |
|
|
|
astNodeDefinition = this.nodeIndex.flatReferences[key] |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return nodeDefinition |
|
|
|
|
|
|
|
} else { |
|
|
|
nodeDefinition.ast = astNodeDefinition |
|
|
|
|
|
|
|
} |
|
|
|
const astNodes = await this.antlrService.listAstNodes() |
|
|
|
const astNodes = await this.antlrService.listAstNodes() |
|
|
|
|
|
|
|
let parserNodeDefinition = null |
|
|
|
if (astNodes && astNodes.length) { |
|
|
|
if (astNodes && astNodes.length) { |
|
|
|
for (const node of astNodes) { |
|
|
|
for (const node of astNodes) { |
|
|
|
if (node.range[0] <= position && node.range[1] >= position) { |
|
|
|
if (node.range[0] <= position && node.range[1] >= position) { |
|
|
|
if (nodeDefinition && nodeDefinition.range[0] < node.range[0]) { |
|
|
|
if (parserNodeDefinition && parserNodeDefinition.range[0] < node.range[0]) { |
|
|
|
nodeDefinition = node |
|
|
|
parserNodeDefinition = node |
|
|
|
} |
|
|
|
} |
|
|
|
if (!nodeDefinition) nodeDefinition = node |
|
|
|
if (!parserNodeDefinition) parserNodeDefinition = node |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (nodeDefinition && nodeDefinition.type && nodeDefinition.type === 'Identifier') { |
|
|
|
if (parserNodeDefinition && parserNodeDefinition.type && parserNodeDefinition.type === 'Identifier') { |
|
|
|
const nodeForIdentifier = await this.findIdentifier(nodeDefinition) |
|
|
|
const nodeForIdentifier = await this.findIdentifier(parserNodeDefinition) |
|
|
|
if (nodeForIdentifier) nodeDefinition = nodeForIdentifier |
|
|
|
if (nodeForIdentifier) parserNodeDefinition = nodeForIdentifier |
|
|
|
} |
|
|
|
} |
|
|
|
return nodeDefinition |
|
|
|
nodeDefinition.parser = parserNodeDefinition |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if the AST node name & type is the same as the parser node name & type, |
|
|
|
|
|
|
|
/ then we can assume that the AST node is the definition, |
|
|
|
|
|
|
|
/ because the parser will always return most nodes it can find even with an error in the code |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (nodeDefinition.ast && nodeDefinition.parser) { |
|
|
|
|
|
|
|
if (nodeDefinition.ast.name === nodeDefinition.parser.name && nodeDefinition.ast.nodeType === nodeDefinition.parser.type) { |
|
|
|
|
|
|
|
return nodeDefinition.ast |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (nodeDefinition.ast && !nodeDefinition.parser) { |
|
|
|
|
|
|
|
return nodeDefinition.ast |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return nodeDefinition.parser |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async getContractNodes(contractName: string) { |
|
|
|
async getContractNodes(contractName: string) { |
|
|
|
if ( |
|
|
|
if ( |
|
|
|
this.nodeIndex.nodesPerFile && |
|
|
|
this.nodeIndex.nodesPerFile && |
|
|
|