From 3a5218d3d53cbd0fc2e453edc1bca5466da7182b Mon Sep 17 00:00:00 2001 From: Marenz Date: Thu, 16 Jun 2022 19:21:38 +0200 Subject: [PATCH] Add location for parameter names in FunctionCall ASTNode --- libsolidity/ast/AST.h | 11 +++- libsolidity/ast/ASTJsonExporter.cpp | 11 ++++ libsolidity/ast/ASTJsonExporter.h | 1 + libsolidity/ast/ASTJsonImporter.cpp | 22 +++++++- libsolidity/ast/ASTJsonImporter.h | 1 + libsolidity/parsing/Parser.cpp | 56 ++++++++++++------- libsolidity/parsing/Parser.h | 13 ++++- test/libsolidity/ASTJSON/address_payable.json | 2 + .../ASTJSON/address_payable_parseOnly.json | 2 + .../ASTJSON/fail_after_parsing_parseOnly.json | 1 + test/libsolidity/ASTJSON/non_utf8.json | 2 + .../ASTJSON/non_utf8_parseOnly.json | 2 + test/libsolidity/ASTJSON/used_errors.json | 2 + .../ASTJSON/used_errors_parseOnly.json | 2 + 14 files changed, 103 insertions(+), 25 deletions(-) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 9c4c10b2f..feca6fce1 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -2105,9 +2105,14 @@ public: SourceLocation const& _location, ASTPointer _expression, std::vector> _arguments, - std::vector> _names + std::vector> _names, + std::vector _nameLocations ): - Expression(_id, _location), m_expression(std::move(_expression)), m_arguments(std::move(_arguments)), m_names(std::move(_names)) {} + Expression(_id, _location), m_expression(std::move(_expression)), m_arguments(std::move(_arguments)), m_names(std::move(_names)), m_nameLocations(std::move(_nameLocations)) + { + solAssert(m_nameLocations.size() == m_names.size()); + } + void accept(ASTVisitor& _visitor) override; void accept(ASTConstVisitor& _visitor) const override; @@ -2120,6 +2125,7 @@ public: /// in the order they were written. /// If this is not a named call, this is empty. std::vector> const& names() const { return m_names; } + std::vector const& nameLocations() const { return m_nameLocations; } FunctionCallAnnotation& annotation() const override; @@ -2127,6 +2133,7 @@ private: ASTPointer m_expression; std::vector> m_arguments; std::vector> m_names; + std::vector m_nameLocations; }; /** diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index dfd4a2f93..359752fc7 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -128,6 +128,16 @@ string ASTJsonExporter::sourceLocationToString(SourceLocation const& _location) return to_string(_location.start) + ":" + to_string(length) + ":" + (sourceIndexOpt.has_value() ? to_string(sourceIndexOpt.value()) : "-1"); } +Json::Value ASTJsonExporter::sourceLocationsToJson(vector const& _sourceLocations) const +{ + Json::Value locations = Json::arrayValue; + + for (SourceLocation const& location: _sourceLocations) + locations.append(sourceLocationToString(location)); + + return locations; +} + string ASTJsonExporter::namePathToString(std::vector const& _namePath) { return boost::algorithm::join(_namePath, "."); @@ -843,6 +853,7 @@ bool ASTJsonExporter::visit(FunctionCall const& _node) std::vector> attributes = { make_pair("expression", toJson(_node.expression())), make_pair("names", std::move(names)), + make_pair("nameLocations", sourceLocationsToJson(_node.nameLocations())), make_pair("arguments", toJson(_node.arguments())), make_pair("tryCall", _node.annotation().tryCall) }; diff --git a/libsolidity/ast/ASTJsonExporter.h b/libsolidity/ast/ASTJsonExporter.h index fb3189ece..566f13612 100644 --- a/libsolidity/ast/ASTJsonExporter.h +++ b/libsolidity/ast/ASTJsonExporter.h @@ -144,6 +144,7 @@ private: /// Maps source location to an index, if source is valid and a mapping does exist, otherwise returns std::nullopt. std::optional sourceIndexFromLocation(langutil::SourceLocation const& _location) const; std::string sourceLocationToString(langutil::SourceLocation const& _location) const; + Json::Value sourceLocationsToJson(std::vector const& _sourceLocations) const; static std::string namePathToString(std::vector const& _namePath); static Json::Value idOrNull(ASTNode const* _pt) { diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 0f692376c..4608652aa 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -95,6 +95,20 @@ SourceLocation const ASTJsonImporter::createSourceLocation(Json::Value const& _n return solidity::langutil::parseSourceLocation(_node["src"].asString(), m_sourceNames); } +optional> ASTJsonImporter::createSourceLocations(Json::Value const& _node) const +{ + vector locations; + + if (_node.isMember("nameLocations") && _node["nameLocations"].isArray()) + { + for (auto const& val: _node["nameLocations"]) + locations.emplace_back(langutil::parseSourceLocation(val.asString(), m_sourceNames)); + return locations; + } + + return nullopt; +} + SourceLocation ASTJsonImporter::createNameSourceLocation(Json::Value const& _node) { astAssert(member(_node, "nameLocation").isString(), "'nameLocation' must be a string"); @@ -893,11 +907,17 @@ ASTPointer ASTJsonImporter::createFunctionCall(Json::Value const& astAssert(name.isString(), "Expected 'names' members to be strings!"); names.push_back(make_shared(name.asString())); } + + optional> sourceLocations = createSourceLocations(_node); + return createASTNode( _node, convertJsonToASTNode(member(_node, "expression")), arguments, - names + names, + sourceLocations ? + *sourceLocations : + vector(names.size()) ); } diff --git a/libsolidity/ast/ASTJsonImporter.h b/libsolidity/ast/ASTJsonImporter.h index 4566a58a4..1216d29b1 100644 --- a/libsolidity/ast/ASTJsonImporter.h +++ b/libsolidity/ast/ASTJsonImporter.h @@ -59,6 +59,7 @@ private: ASTPointer createASTNode(Json::Value const& _node, Args&&... _args); /// @returns the sourceLocation-object created from the string in the JSON node langutil::SourceLocation const createSourceLocation(Json::Value const& _node); + std::optional> createSourceLocations(Json::Value const& _node) const; /// Creates an ASTNode for a given JSON-ast of unknown type /// @returns Pointer to a new created ASTNode ASTPointer convertJsonToASTNode(Json::Value const& _ast); diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 15e9f6c53..a9eafd72b 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -38,6 +38,7 @@ #include #include #include +#include using namespace std; using namespace solidity::langutil; @@ -1542,13 +1543,16 @@ ASTPointer Parser::parseEmitStatement(ASTPointer const auto eventName = expressionFromIndexAccessStructure(iap); expectToken(Token::LParen); - vector> arguments; - vector> names; - std::tie(arguments, names) = parseFunctionCallArguments(); + auto functionCallArguments = parseFunctionCallArguments(); eventCallNodeFactory.markEndPosition(); nodeFactory.markEndPosition(); expectToken(Token::RParen); - auto eventCall = eventCallNodeFactory.createNode(eventName, arguments, names); + auto eventCall = eventCallNodeFactory.createNode( + eventName, + functionCallArguments.arguments, + functionCallArguments.parameterNames, + functionCallArguments.parameterNameLocations + ); return nodeFactory.createNode(_docString, eventCall); } @@ -1573,13 +1577,16 @@ ASTPointer Parser::parseRevertStatement(ASTPointer c auto errorName = expressionFromIndexAccessStructure(iap); expectToken(Token::LParen); - vector> arguments; - vector> names; - std::tie(arguments, names) = parseFunctionCallArguments(); + auto functionCallArguments = parseFunctionCallArguments(); errorCallNodeFactory.markEndPosition(); nodeFactory.markEndPosition(); expectToken(Token::RParen); - auto errorCall = errorCallNodeFactory.createNode(errorName, arguments, names); + auto errorCall = errorCallNodeFactory.createNode( + errorName, + functionCallArguments.arguments, + functionCallArguments.parameterNames, + functionCallArguments.parameterNameLocations + ); return nodeFactory.createNode(_docString, errorCall); } @@ -1903,12 +1910,14 @@ ASTPointer Parser::parseLeftHandSideExpression( case Token::LParen: { advance(); - vector> arguments; - vector> names; - std::tie(arguments, names) = parseFunctionCallArguments(); + auto functionCallArguments = parseFunctionCallArguments(); nodeFactory.markEndPosition(); expectToken(Token::RParen); - expression = nodeFactory.createNode(expression, arguments, names); + expression = nodeFactory.createNode( + expression, + functionCallArguments.arguments, + functionCallArguments.parameterNames, + functionCallArguments.parameterNameLocations); break; } case Token::LBrace: @@ -1927,7 +1936,7 @@ ASTPointer Parser::parseLeftHandSideExpression( nodeFactory.markEndPosition(); expectToken(Token::RBrace); - expression = nodeFactory.createNode(expression, optionList.first, optionList.second); + expression = nodeFactory.createNode(expression, optionList.arguments, optionList.parameterNames); break; } default: @@ -2071,10 +2080,11 @@ vector> Parser::parseFunctionCallListArguments() return arguments; } -pair>, vector>> Parser::parseFunctionCallArguments() +Parser::FunctionCallArguments Parser::parseFunctionCallArguments() { RecursionGuard recursionGuard(*this); - pair>, vector>> ret; + FunctionCallArguments ret; + Token token = m_scanner->currentToken(); if (token == Token::LBrace) { @@ -2084,13 +2094,13 @@ pair>, vector>> Parser::pars expectToken(Token::RBrace); } else - ret.first = parseFunctionCallListArguments(); + ret.arguments = parseFunctionCallListArguments(); return ret; } -pair>, vector>> Parser::parseNamedArguments() +Parser::FunctionCallArguments Parser::parseNamedArguments() { - pair>, vector>> ret; + FunctionCallArguments ret; bool first = true; while (m_scanner->currentToken() != Token::RBrace) @@ -2098,9 +2108,15 @@ pair>, vector>> Parser::pars if (!first) expectToken(Token::Comma); - ret.second.push_back(expectIdentifierToken()); + auto identifierWithLocation = expectIdentifierWithLocation(); + + // Add name + ret.parameterNames.emplace_back(std::move(identifierWithLocation.first)); + // Add location + ret.parameterNameLocations.emplace_back(std::move(identifierWithLocation.second)); + expectToken(Token::Colon); - ret.first.push_back(parseExpression()); + ret.arguments.emplace_back(parseExpression()); if ( m_scanner->currentToken() == Token::Comma && diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index e656c936d..7a9b41318 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -77,6 +77,14 @@ private: std::vector> modifiers; }; + /// Struct to share parsed function call arguments. + struct FunctionCallArguments + { + std::vector> arguments; + std::vector> parameterNames; + std::vector parameterNameLocations; + }; + ///@{ ///@name Parsing functions for the AST nodes void parsePragmaVersion(langutil::SourceLocation const& _location, std::vector const& _tokens, std::vector const& _literals); @@ -153,8 +161,9 @@ private: ); ASTPointer parsePrimaryExpression(); std::vector> parseFunctionCallListArguments(); - std::pair>, std::vector>> parseFunctionCallArguments(); - std::pair>, std::vector>> parseNamedArguments(); + + FunctionCallArguments parseFunctionCallArguments(); + FunctionCallArguments parseNamedArguments(); std::pair, langutil::SourceLocation> expectIdentifierWithLocation(); ///@} diff --git a/test/libsolidity/ASTJSON/address_payable.json b/test/libsolidity/ASTJSON/address_payable.json index 9aec1e510..cc87fc3b9 100644 --- a/test/libsolidity/ASTJSON/address_payable.json +++ b/test/libsolidity/ASTJSON/address_payable.json @@ -320,6 +320,7 @@ "isPure": false, "kind": "typeConversion", "lValueRequested": false, + "nameLocations": [], "names": [], "nodeType": "FunctionCall", "src": "209:13:1", @@ -445,6 +446,7 @@ "isPure": true, "kind": "typeConversion", "lValueRequested": false, + "nameLocations": [], "names": [], "nodeType": "FunctionCall", "src": "239:10:1", diff --git a/test/libsolidity/ASTJSON/address_payable_parseOnly.json b/test/libsolidity/ASTJSON/address_payable_parseOnly.json index 39e91de1c..fd7f772f6 100644 --- a/test/libsolidity/ASTJSON/address_payable_parseOnly.json +++ b/test/libsolidity/ASTJSON/address_payable_parseOnly.json @@ -210,6 +210,7 @@ } }, "id": 26, + "nameLocations": [], "names": [], "nodeType": "FunctionCall", "src": "209:13:1", @@ -281,6 +282,7 @@ } }, "id": 34, + "nameLocations": [], "names": [], "nodeType": "FunctionCall", "src": "239:10:1", diff --git a/test/libsolidity/ASTJSON/fail_after_parsing_parseOnly.json b/test/libsolidity/ASTJSON/fail_after_parsing_parseOnly.json index e13cd2bff..5368d5862 100644 --- a/test/libsolidity/ASTJSON/fail_after_parsing_parseOnly.json +++ b/test/libsolidity/ASTJSON/fail_after_parsing_parseOnly.json @@ -149,6 +149,7 @@ "typeDescriptions": {} }, "id": 18, + "nameLocations": [], "names": [], "nodeType": "FunctionCall", "src": "117:3:1", diff --git a/test/libsolidity/ASTJSON/non_utf8.json b/test/libsolidity/ASTJSON/non_utf8.json index 0e2a56f84..926f858b5 100644 --- a/test/libsolidity/ASTJSON/non_utf8.json +++ b/test/libsolidity/ASTJSON/non_utf8.json @@ -135,6 +135,7 @@ "isPure": true, "kind": "typeConversion", "lValueRequested": false, + "nameLocations": [], "names": [], "nodeType": "FunctionCall", "src": "60:14:1", @@ -182,6 +183,7 @@ "isPure": true, "kind": "typeConversion", "lValueRequested": false, + "nameLocations": [], "names": [], "nodeType": "FunctionCall", "src": "53:22:1", diff --git a/test/libsolidity/ASTJSON/non_utf8_parseOnly.json b/test/libsolidity/ASTJSON/non_utf8_parseOnly.json index df358ae36..ef265cbe4 100644 --- a/test/libsolidity/ASTJSON/non_utf8_parseOnly.json +++ b/test/libsolidity/ASTJSON/non_utf8_parseOnly.json @@ -85,6 +85,7 @@ } }, "id": 10, + "nameLocations": [], "names": [], "nodeType": "FunctionCall", "src": "60:14:1", @@ -108,6 +109,7 @@ } }, "id": 11, + "nameLocations": [], "names": [], "nodeType": "FunctionCall", "src": "53:22:1", diff --git a/test/libsolidity/ASTJSON/used_errors.json b/test/libsolidity/ASTJSON/used_errors.json index f00336d20..c59b4f530 100644 --- a/test/libsolidity/ASTJSON/used_errors.json +++ b/test/libsolidity/ASTJSON/used_errors.json @@ -67,6 +67,7 @@ "isPure": false, "kind": "functionCall", "lValueRequested": false, + "nameLocations": [], "names": [], "nodeType": "FunctionCall", "src": "38:3:1", @@ -175,6 +176,7 @@ "isPure": false, "kind": "functionCall", "lValueRequested": false, + "nameLocations": [], "names": [], "nodeType": "FunctionCall", "src": "99:3:1", diff --git a/test/libsolidity/ASTJSON/used_errors_parseOnly.json b/test/libsolidity/ASTJSON/used_errors_parseOnly.json index b7500b445..7a4b24b3c 100644 --- a/test/libsolidity/ASTJSON/used_errors_parseOnly.json +++ b/test/libsolidity/ASTJSON/used_errors_parseOnly.json @@ -40,6 +40,7 @@ "typeDescriptions": {} }, "id": 6, + "nameLocations": [], "names": [], "nodeType": "FunctionCall", "src": "38:3:1", @@ -125,6 +126,7 @@ "typeDescriptions": {} }, "id": 15, + "nameLocations": [], "names": [], "nodeType": "FunctionCall", "src": "99:3:1",