Add location for parameter names in FunctionCall ASTNode

This commit is contained in:
Marenz 2022-06-16 19:21:38 +02:00
parent 4d8a14b653
commit 3a5218d3d5
14 changed files with 103 additions and 25 deletions

View File

@ -2105,9 +2105,14 @@ public:
SourceLocation const& _location, SourceLocation const& _location,
ASTPointer<Expression> _expression, ASTPointer<Expression> _expression,
std::vector<ASTPointer<Expression>> _arguments, std::vector<ASTPointer<Expression>> _arguments,
std::vector<ASTPointer<ASTString>> _names std::vector<ASTPointer<ASTString>> _names,
std::vector<SourceLocation> _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(ASTVisitor& _visitor) override;
void accept(ASTConstVisitor& _visitor) const override; void accept(ASTConstVisitor& _visitor) const override;
@ -2120,6 +2125,7 @@ public:
/// in the order they were written. /// in the order they were written.
/// If this is not a named call, this is empty. /// If this is not a named call, this is empty.
std::vector<ASTPointer<ASTString>> const& names() const { return m_names; } std::vector<ASTPointer<ASTString>> const& names() const { return m_names; }
std::vector<SourceLocation> const& nameLocations() const { return m_nameLocations; }
FunctionCallAnnotation& annotation() const override; FunctionCallAnnotation& annotation() const override;
@ -2127,6 +2133,7 @@ private:
ASTPointer<Expression> m_expression; ASTPointer<Expression> m_expression;
std::vector<ASTPointer<Expression>> m_arguments; std::vector<ASTPointer<Expression>> m_arguments;
std::vector<ASTPointer<ASTString>> m_names; std::vector<ASTPointer<ASTString>> m_names;
std::vector<SourceLocation> m_nameLocations;
}; };
/** /**

View File

@ -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"); return to_string(_location.start) + ":" + to_string(length) + ":" + (sourceIndexOpt.has_value() ? to_string(sourceIndexOpt.value()) : "-1");
} }
Json::Value ASTJsonExporter::sourceLocationsToJson(vector<SourceLocation> const& _sourceLocations) const
{
Json::Value locations = Json::arrayValue;
for (SourceLocation const& location: _sourceLocations)
locations.append(sourceLocationToString(location));
return locations;
}
string ASTJsonExporter::namePathToString(std::vector<ASTString> const& _namePath) string ASTJsonExporter::namePathToString(std::vector<ASTString> const& _namePath)
{ {
return boost::algorithm::join(_namePath, "."); return boost::algorithm::join(_namePath, ".");
@ -843,6 +853,7 @@ bool ASTJsonExporter::visit(FunctionCall const& _node)
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json::Value>> attributes = {
make_pair("expression", toJson(_node.expression())), make_pair("expression", toJson(_node.expression())),
make_pair("names", std::move(names)), make_pair("names", std::move(names)),
make_pair("nameLocations", sourceLocationsToJson(_node.nameLocations())),
make_pair("arguments", toJson(_node.arguments())), make_pair("arguments", toJson(_node.arguments())),
make_pair("tryCall", _node.annotation().tryCall) make_pair("tryCall", _node.annotation().tryCall)
}; };

View File

@ -144,6 +144,7 @@ private:
/// Maps source location to an index, if source is valid and a mapping does exist, otherwise returns std::nullopt. /// Maps source location to an index, if source is valid and a mapping does exist, otherwise returns std::nullopt.
std::optional<size_t> sourceIndexFromLocation(langutil::SourceLocation const& _location) const; std::optional<size_t> sourceIndexFromLocation(langutil::SourceLocation const& _location) const;
std::string sourceLocationToString(langutil::SourceLocation const& _location) const; std::string sourceLocationToString(langutil::SourceLocation const& _location) const;
Json::Value sourceLocationsToJson(std::vector<langutil::SourceLocation> const& _sourceLocations) const;
static std::string namePathToString(std::vector<ASTString> const& _namePath); static std::string namePathToString(std::vector<ASTString> const& _namePath);
static Json::Value idOrNull(ASTNode const* _pt) static Json::Value idOrNull(ASTNode const* _pt)
{ {

View File

@ -95,6 +95,20 @@ SourceLocation const ASTJsonImporter::createSourceLocation(Json::Value const& _n
return solidity::langutil::parseSourceLocation(_node["src"].asString(), m_sourceNames); return solidity::langutil::parseSourceLocation(_node["src"].asString(), m_sourceNames);
} }
optional<vector<SourceLocation>> ASTJsonImporter::createSourceLocations(Json::Value const& _node) const
{
vector<SourceLocation> 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) SourceLocation ASTJsonImporter::createNameSourceLocation(Json::Value const& _node)
{ {
astAssert(member(_node, "nameLocation").isString(), "'nameLocation' must be a string"); astAssert(member(_node, "nameLocation").isString(), "'nameLocation' must be a string");
@ -893,11 +907,17 @@ ASTPointer<FunctionCall> ASTJsonImporter::createFunctionCall(Json::Value const&
astAssert(name.isString(), "Expected 'names' members to be strings!"); astAssert(name.isString(), "Expected 'names' members to be strings!");
names.push_back(make_shared<ASTString>(name.asString())); names.push_back(make_shared<ASTString>(name.asString()));
} }
optional<vector<SourceLocation>> sourceLocations = createSourceLocations(_node);
return createASTNode<FunctionCall>( return createASTNode<FunctionCall>(
_node, _node,
convertJsonToASTNode<Expression>(member(_node, "expression")), convertJsonToASTNode<Expression>(member(_node, "expression")),
arguments, arguments,
names names,
sourceLocations ?
*sourceLocations :
vector<SourceLocation>(names.size())
); );
} }

View File

@ -59,6 +59,7 @@ private:
ASTPointer<T> createASTNode(Json::Value const& _node, Args&&... _args); ASTPointer<T> createASTNode(Json::Value const& _node, Args&&... _args);
/// @returns the sourceLocation-object created from the string in the JSON node /// @returns the sourceLocation-object created from the string in the JSON node
langutil::SourceLocation const createSourceLocation(Json::Value const& _node); langutil::SourceLocation const createSourceLocation(Json::Value const& _node);
std::optional<std::vector<langutil::SourceLocation>> createSourceLocations(Json::Value const& _node) const;
/// Creates an ASTNode for a given JSON-ast of unknown type /// Creates an ASTNode for a given JSON-ast of unknown type
/// @returns Pointer to a new created ASTNode /// @returns Pointer to a new created ASTNode
ASTPointer<ASTNode> convertJsonToASTNode(Json::Value const& _ast); ASTPointer<ASTNode> convertJsonToASTNode(Json::Value const& _ast);

View File

@ -38,6 +38,7 @@
#include <cctype> #include <cctype>
#include <vector> #include <vector>
#include <regex> #include <regex>
#include <tuple>
using namespace std; using namespace std;
using namespace solidity::langutil; using namespace solidity::langutil;
@ -1542,13 +1543,16 @@ ASTPointer<EmitStatement> Parser::parseEmitStatement(ASTPointer<ASTString> const
auto eventName = expressionFromIndexAccessStructure(iap); auto eventName = expressionFromIndexAccessStructure(iap);
expectToken(Token::LParen); expectToken(Token::LParen);
vector<ASTPointer<Expression>> arguments; auto functionCallArguments = parseFunctionCallArguments();
vector<ASTPointer<ASTString>> names;
std::tie(arguments, names) = parseFunctionCallArguments();
eventCallNodeFactory.markEndPosition(); eventCallNodeFactory.markEndPosition();
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();
expectToken(Token::RParen); expectToken(Token::RParen);
auto eventCall = eventCallNodeFactory.createNode<FunctionCall>(eventName, arguments, names); auto eventCall = eventCallNodeFactory.createNode<FunctionCall>(
eventName,
functionCallArguments.arguments,
functionCallArguments.parameterNames,
functionCallArguments.parameterNameLocations
);
return nodeFactory.createNode<EmitStatement>(_docString, eventCall); return nodeFactory.createNode<EmitStatement>(_docString, eventCall);
} }
@ -1573,13 +1577,16 @@ ASTPointer<RevertStatement> Parser::parseRevertStatement(ASTPointer<ASTString> c
auto errorName = expressionFromIndexAccessStructure(iap); auto errorName = expressionFromIndexAccessStructure(iap);
expectToken(Token::LParen); expectToken(Token::LParen);
vector<ASTPointer<Expression>> arguments; auto functionCallArguments = parseFunctionCallArguments();
vector<ASTPointer<ASTString>> names;
std::tie(arguments, names) = parseFunctionCallArguments();
errorCallNodeFactory.markEndPosition(); errorCallNodeFactory.markEndPosition();
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();
expectToken(Token::RParen); expectToken(Token::RParen);
auto errorCall = errorCallNodeFactory.createNode<FunctionCall>(errorName, arguments, names); auto errorCall = errorCallNodeFactory.createNode<FunctionCall>(
errorName,
functionCallArguments.arguments,
functionCallArguments.parameterNames,
functionCallArguments.parameterNameLocations
);
return nodeFactory.createNode<RevertStatement>(_docString, errorCall); return nodeFactory.createNode<RevertStatement>(_docString, errorCall);
} }
@ -1903,12 +1910,14 @@ ASTPointer<Expression> Parser::parseLeftHandSideExpression(
case Token::LParen: case Token::LParen:
{ {
advance(); advance();
vector<ASTPointer<Expression>> arguments; auto functionCallArguments = parseFunctionCallArguments();
vector<ASTPointer<ASTString>> names;
std::tie(arguments, names) = parseFunctionCallArguments();
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();
expectToken(Token::RParen); expectToken(Token::RParen);
expression = nodeFactory.createNode<FunctionCall>(expression, arguments, names); expression = nodeFactory.createNode<FunctionCall>(
expression,
functionCallArguments.arguments,
functionCallArguments.parameterNames,
functionCallArguments.parameterNameLocations);
break; break;
} }
case Token::LBrace: case Token::LBrace:
@ -1927,7 +1936,7 @@ ASTPointer<Expression> Parser::parseLeftHandSideExpression(
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();
expectToken(Token::RBrace); expectToken(Token::RBrace);
expression = nodeFactory.createNode<FunctionCallOptions>(expression, optionList.first, optionList.second); expression = nodeFactory.createNode<FunctionCallOptions>(expression, optionList.arguments, optionList.parameterNames);
break; break;
} }
default: default:
@ -2071,10 +2080,11 @@ vector<ASTPointer<Expression>> Parser::parseFunctionCallListArguments()
return arguments; return arguments;
} }
pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> Parser::parseFunctionCallArguments() Parser::FunctionCallArguments Parser::parseFunctionCallArguments()
{ {
RecursionGuard recursionGuard(*this); RecursionGuard recursionGuard(*this);
pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> ret; FunctionCallArguments ret;
Token token = m_scanner->currentToken(); Token token = m_scanner->currentToken();
if (token == Token::LBrace) if (token == Token::LBrace)
{ {
@ -2084,13 +2094,13 @@ pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> Parser::pars
expectToken(Token::RBrace); expectToken(Token::RBrace);
} }
else else
ret.first = parseFunctionCallListArguments(); ret.arguments = parseFunctionCallListArguments();
return ret; return ret;
} }
pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> Parser::parseNamedArguments() Parser::FunctionCallArguments Parser::parseNamedArguments()
{ {
pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> ret; FunctionCallArguments ret;
bool first = true; bool first = true;
while (m_scanner->currentToken() != Token::RBrace) while (m_scanner->currentToken() != Token::RBrace)
@ -2098,9 +2108,15 @@ pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> Parser::pars
if (!first) if (!first)
expectToken(Token::Comma); 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); expectToken(Token::Colon);
ret.first.push_back(parseExpression()); ret.arguments.emplace_back(parseExpression());
if ( if (
m_scanner->currentToken() == Token::Comma && m_scanner->currentToken() == Token::Comma &&

View File

@ -77,6 +77,14 @@ private:
std::vector<ASTPointer<ModifierInvocation>> modifiers; std::vector<ASTPointer<ModifierInvocation>> modifiers;
}; };
/// Struct to share parsed function call arguments.
struct FunctionCallArguments
{
std::vector<ASTPointer<Expression>> arguments;
std::vector<ASTPointer<ASTString>> parameterNames;
std::vector<langutil::SourceLocation> parameterNameLocations;
};
///@{ ///@{
///@name Parsing functions for the AST nodes ///@name Parsing functions for the AST nodes
void parsePragmaVersion(langutil::SourceLocation const& _location, std::vector<Token> const& _tokens, std::vector<std::string> const& _literals); void parsePragmaVersion(langutil::SourceLocation const& _location, std::vector<Token> const& _tokens, std::vector<std::string> const& _literals);
@ -153,8 +161,9 @@ private:
); );
ASTPointer<Expression> parsePrimaryExpression(); ASTPointer<Expression> parsePrimaryExpression();
std::vector<ASTPointer<Expression>> parseFunctionCallListArguments(); std::vector<ASTPointer<Expression>> parseFunctionCallListArguments();
std::pair<std::vector<ASTPointer<Expression>>, std::vector<ASTPointer<ASTString>>> parseFunctionCallArguments();
std::pair<std::vector<ASTPointer<Expression>>, std::vector<ASTPointer<ASTString>>> parseNamedArguments(); FunctionCallArguments parseFunctionCallArguments();
FunctionCallArguments parseNamedArguments();
std::pair<ASTPointer<ASTString>, langutil::SourceLocation> expectIdentifierWithLocation(); std::pair<ASTPointer<ASTString>, langutil::SourceLocation> expectIdentifierWithLocation();
///@} ///@}

View File

@ -320,6 +320,7 @@
"isPure": false, "isPure": false,
"kind": "typeConversion", "kind": "typeConversion",
"lValueRequested": false, "lValueRequested": false,
"nameLocations": [],
"names": [], "names": [],
"nodeType": "FunctionCall", "nodeType": "FunctionCall",
"src": "209:13:1", "src": "209:13:1",
@ -445,6 +446,7 @@
"isPure": true, "isPure": true,
"kind": "typeConversion", "kind": "typeConversion",
"lValueRequested": false, "lValueRequested": false,
"nameLocations": [],
"names": [], "names": [],
"nodeType": "FunctionCall", "nodeType": "FunctionCall",
"src": "239:10:1", "src": "239:10:1",

View File

@ -210,6 +210,7 @@
} }
}, },
"id": 26, "id": 26,
"nameLocations": [],
"names": [], "names": [],
"nodeType": "FunctionCall", "nodeType": "FunctionCall",
"src": "209:13:1", "src": "209:13:1",
@ -281,6 +282,7 @@
} }
}, },
"id": 34, "id": 34,
"nameLocations": [],
"names": [], "names": [],
"nodeType": "FunctionCall", "nodeType": "FunctionCall",
"src": "239:10:1", "src": "239:10:1",

View File

@ -149,6 +149,7 @@
"typeDescriptions": {} "typeDescriptions": {}
}, },
"id": 18, "id": 18,
"nameLocations": [],
"names": [], "names": [],
"nodeType": "FunctionCall", "nodeType": "FunctionCall",
"src": "117:3:1", "src": "117:3:1",

View File

@ -135,6 +135,7 @@
"isPure": true, "isPure": true,
"kind": "typeConversion", "kind": "typeConversion",
"lValueRequested": false, "lValueRequested": false,
"nameLocations": [],
"names": [], "names": [],
"nodeType": "FunctionCall", "nodeType": "FunctionCall",
"src": "60:14:1", "src": "60:14:1",
@ -182,6 +183,7 @@
"isPure": true, "isPure": true,
"kind": "typeConversion", "kind": "typeConversion",
"lValueRequested": false, "lValueRequested": false,
"nameLocations": [],
"names": [], "names": [],
"nodeType": "FunctionCall", "nodeType": "FunctionCall",
"src": "53:22:1", "src": "53:22:1",

View File

@ -85,6 +85,7 @@
} }
}, },
"id": 10, "id": 10,
"nameLocations": [],
"names": [], "names": [],
"nodeType": "FunctionCall", "nodeType": "FunctionCall",
"src": "60:14:1", "src": "60:14:1",
@ -108,6 +109,7 @@
} }
}, },
"id": 11, "id": 11,
"nameLocations": [],
"names": [], "names": [],
"nodeType": "FunctionCall", "nodeType": "FunctionCall",
"src": "53:22:1", "src": "53:22:1",

View File

@ -67,6 +67,7 @@
"isPure": false, "isPure": false,
"kind": "functionCall", "kind": "functionCall",
"lValueRequested": false, "lValueRequested": false,
"nameLocations": [],
"names": [], "names": [],
"nodeType": "FunctionCall", "nodeType": "FunctionCall",
"src": "38:3:1", "src": "38:3:1",
@ -175,6 +176,7 @@
"isPure": false, "isPure": false,
"kind": "functionCall", "kind": "functionCall",
"lValueRequested": false, "lValueRequested": false,
"nameLocations": [],
"names": [], "names": [],
"nodeType": "FunctionCall", "nodeType": "FunctionCall",
"src": "99:3:1", "src": "99:3:1",

View File

@ -40,6 +40,7 @@
"typeDescriptions": {} "typeDescriptions": {}
}, },
"id": 6, "id": 6,
"nameLocations": [],
"names": [], "names": [],
"nodeType": "FunctionCall", "nodeType": "FunctionCall",
"src": "38:3:1", "src": "38:3:1",
@ -125,6 +126,7 @@
"typeDescriptions": {} "typeDescriptions": {}
}, },
"id": 15, "id": 15,
"nameLocations": [],
"names": [], "names": [],
"nodeType": "FunctionCall", "nodeType": "FunctionCall",
"src": "99:3:1", "src": "99:3:1",