diff --git a/libsolidity/ast/ASTUtils.cpp b/libsolidity/ast/ASTUtils.cpp index 3ed47d6f2..99da7c2b1 100644 --- a/libsolidity/ast/ASTUtils.cpp +++ b/libsolidity/ast/ASTUtils.cpp @@ -17,6 +17,7 @@ // SPDX-License-Identifier: GPL-3.0 #include +#include #include #include @@ -24,6 +25,40 @@ namespace solidity::frontend { +namespace +{ + +class ASTNodeLocator: public ASTConstVisitor +{ +public: + explicit ASTNodeLocator(int _pos): m_offsetInFile{_pos}, m_innermostMatch{nullptr} {} + + bool visitNode(ASTNode const& _node) override + { + // In the AST parent location always covers the whole child location. + // The parent is visited first so to get the innermost node we simply + // take the last one that still contains the offset. + + if (!_node.location().containsOffset(m_offsetInFile)) + return false; + + m_innermostMatch = &_node; + return true; + } + + int const m_offsetInFile; + ASTNode const* m_innermostMatch; +}; + +} + +ASTNode const* locateInnermostASTNode(int _pos, SourceUnit const& _sourceUnit) +{ + ASTNodeLocator locator{_pos}; + _sourceUnit.accept(locator); + return locator.m_innermostMatch; +} + bool isConstantVariableRecursive(VariableDeclaration const& _varDecl) { solAssert(_varDecl.isConstant(), "Constant variable expected"); diff --git a/libsolidity/ast/ASTUtils.h b/libsolidity/ast/ASTUtils.h index 5b1a7d4e5..af3a5176d 100644 --- a/libsolidity/ast/ASTUtils.h +++ b/libsolidity/ast/ASTUtils.h @@ -21,9 +21,11 @@ namespace solidity::frontend { -class VariableDeclaration; +class ASTNode; class Declaration; class Expression; +class SourceUnit; +class VariableDeclaration; /// Find the topmost referenced constant variable declaration when the given variable /// declaration value is an identifier. Works only for constant variable declarations. @@ -33,4 +35,7 @@ VariableDeclaration const* rootConstVariableDeclaration(VariableDeclaration cons /// Returns true if the constant variable declaration is recursive. bool isConstantVariableRecursive(VariableDeclaration const& _varDecl); +/// Teturns the innermost AST node that covers the given location or nullptr if not found. +ASTNode const* locateInnermostASTNode(int _pos, SourceUnit const& _sourceUnit); + }