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,
ASTPointer<Expression> _expression,
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(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<ASTPointer<ASTString>> const& names() const { return m_names; }
std::vector<SourceLocation> const& nameLocations() const { return m_nameLocations; }
FunctionCallAnnotation& annotation() const override;
@ -2127,6 +2133,7 @@ private:
ASTPointer<Expression> m_expression;
std::vector<ASTPointer<Expression>> m_arguments;
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");
}
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)
{
return boost::algorithm::join(_namePath, ".");
@ -843,6 +853,7 @@ bool ASTJsonExporter::visit(FunctionCall const& _node)
std::vector<pair<string, Json::Value>> 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)
};

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.
std::optional<size_t> sourceIndexFromLocation(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 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);
}
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)
{
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!");
names.push_back(make_shared<ASTString>(name.asString()));
}
optional<vector<SourceLocation>> sourceLocations = createSourceLocations(_node);
return createASTNode<FunctionCall>(
_node,
convertJsonToASTNode<Expression>(member(_node, "expression")),
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);
/// @returns the sourceLocation-object created from the string in the JSON 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
/// @returns Pointer to a new created ASTNode
ASTPointer<ASTNode> convertJsonToASTNode(Json::Value const& _ast);

View File

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

View File

@ -77,6 +77,14 @@ private:
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
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();
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();
///@}

View File

@ -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",

View File

@ -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",

View File

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

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",