Merge pull request #8741 from ethereum/dot-syntax-upgrade

[BREAKING] solidity-upgrade dot syntax for gas and value
This commit is contained in:
chriseth 2020-04-28 18:29:49 +02:00 committed by GitHub
commit e306fdc251
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 231 additions and 22 deletions

View File

@ -5,6 +5,7 @@ add_executable(solidity-upgrade
solidityUpgrade/UpgradeSuite.h solidityUpgrade/UpgradeSuite.h
solidityUpgrade/Upgrade050.cpp solidityUpgrade/Upgrade050.cpp
solidityUpgrade/Upgrade060.cpp solidityUpgrade/Upgrade060.cpp
solidityUpgrade/Upgrade070.cpp
solidityUpgrade/SourceTransform.h solidityUpgrade/SourceTransform.h
solidityUpgrade/SourceUpgrade.cpp solidityUpgrade/SourceUpgrade.cpp
) )

View File

@ -19,17 +19,39 @@
#include <libsolidity/ast/AST.h> #include <libsolidity/ast/AST.h>
#include <sstream>
#include <regex> #include <regex>
namespace solidity::tools namespace solidity::tools
{ {
/**
* Helper for displaying location during asserts
*/
class LocationHelper
{
std::stringstream m_stream;
public:
template <typename T>
LocationHelper& operator<<(T const& data)
{
m_stream << data;
return *this;
}
operator std::string() { return m_stream.str(); }
};
/** /**
* Helper that provides functions which analyze certain source locations * Helper that provides functions which analyze certain source locations
* on a textual base. They utilize regular expression to search for * on a textual base. They utilize regular expression to search for
* keywords or to determine formatting. * keywords or to determine formatting.
*/ */
class SourceAnalysis { class SourceAnalysis
{
public: public:
static bool isMultilineKeyword( static bool isMultilineKeyword(
langutil::SourceLocation const& _location, langutil::SourceLocation const& _location,
@ -82,6 +104,7 @@ public:
for (auto inheritedContract: _contracts) for (auto inheritedContract: _contracts)
overrideList += inheritedContract->name() + ","; overrideList += inheritedContract->name() + ",";
// Note: Can create incorrect replacements
return "override(" + overrideList.substr(0, overrideList.size() - 1) + ")"; return "override(" + overrideList.substr(0, overrideList.size() - 1) + ")";
} }
}; };
@ -102,11 +125,21 @@ public:
std::string const& _expression std::string const& _expression
) )
{ {
return regex_replace( auto _regex = std::regex{"(\\b" + _keyword + "\\b)"};
_location.text(), if (regex_search(_location.text(), _regex))
std::regex{"(\\b" + _keyword + "\\b)"}, return regex_replace(
_expression + " " + _keyword _location.text(),
); _regex,
_expression + " " + _keyword
);
else
solAssert(
false,
LocationHelper() << "Could not fix: " << _location.text() << " at " << _location <<
"\nNeeds to be fixed manually."
);
return "";
} }
/// Searches for the keyword given and appends the expression. /// Searches for the keyword given and appends the expression.
@ -121,7 +154,17 @@ public:
std::string toAppend = isMultiline ? ("\n " + _expression) : (" " + _expression); std::string toAppend = isMultiline ? ("\n " + _expression) : (" " + _expression);
std::regex keyword{"(\\b" + _keyword + "\\b)"}; std::regex keyword{"(\\b" + _keyword + "\\b)"};
return regex_replace(_location.text(), keyword, _keyword + toAppend); if (regex_search(_location.text(), keyword))
return regex_replace(_location.text(), keyword, _keyword + toAppend);
else
solAssert(
false,
LocationHelper() << "Could not fix: " << _location.text() << " at " << _location <<
"\nNeeds to be fixed manually."
);
return "";
} }
/// Searches for the first right parenthesis and appends the expression /// Searches for the first right parenthesis and appends the expression
@ -132,11 +175,21 @@ public:
std::string const& _expression std::string const& _expression
) )
{ {
return regex_replace( auto _regex = std::regex{"(\\))"};
_location.text(), if (regex_search(_location.text(), _regex))
std::regex{"(\\))"}, return regex_replace(
") " + _expression _location.text(),
); std::regex{"(\\))"},
") " + _expression
);
else
solAssert(
false,
LocationHelper() << "Could not fix: " << _location.text() << " at " << _location <<
"\nNeeds to be fixed manually."
);
return "";
} }
/// Searches for the `function` keyword and its identifier and replaces /// Searches for the `function` keyword and its identifier and replaces
@ -148,11 +201,71 @@ public:
std::string const& _expression std::string const& _expression
) )
{ {
return regex_replace( auto _regex = std::regex{ "(\\bfunction\\s*" + _name + "\\b)"};
_location.text(), if (regex_search(_location.text(), _regex))
std::regex{"(\\bfunction\\s*" + _name + "\\b)"}, return regex_replace(
_expression _location.text(),
); _regex,
_expression
);
else
solAssert(
false,
LocationHelper() << "Could not fix: " << _location.text() << " at " << _location <<
"\nNeeds to be fixed manually."
);
return "";
}
static std::string gasUpdate(langutil::SourceLocation const& _location)
{
// dot, "gas", any number of whitespaces, left bracket
std::regex gasReg{"\\.gas\\s*\\("};
if (regex_search(_location.text(), gasReg))
{
std::string out = regex_replace(
_location.text(),
gasReg,
"{gas: ",
std::regex_constants::format_first_only
);
return regex_replace(out, std::regex{"\\)$"}, "}");
}
else
solAssert(
false,
LocationHelper() << "Could not fix: " << _location.text() << " at " << _location <<
"\nNeeds to be fixed manually."
);
return "";
}
static std::string valueUpdate(langutil::SourceLocation const& _location)
{
// dot, "value", any number of whitespaces, left bracket
std::regex valueReg{"\\.value\\s*\\("};
if (regex_search(_location.text(), valueReg))
{
std::string out = regex_replace(
_location.text(),
valueReg,
"{value: ",
std::regex_constants::format_first_only
);
return regex_replace(out, std::regex{"\\)$"}, "}");
}
else
solAssert(
false,
LocationHelper() << "Could not fix: " << _location.text() << " at " << _location <<
"\nNeeds to be fixed manually."
);
return "";
} }
}; };

View File

@ -194,6 +194,8 @@ Allowed options)",
m_suite.activateModule(Module::OverridingFunction); m_suite.activateModule(Module::OverridingFunction);
else if (module == "virtual") else if (module == "virtual")
m_suite.activateModule(Module::VirtualFunction); m_suite.activateModule(Module::VirtualFunction);
else if (module == "dotsyntax")
m_suite.activateModule(Module::DotSyntax);
else else
{ {
error() << "Unknown upgrade module \"" + module + "\"" << endl; error() << "Unknown upgrade module \"" + module + "\"" << endl;

View File

@ -1,4 +1,4 @@
/* /*
This file is part of solidity. This file is part of solidity.
solidity is free software: you can redistribute it and/or modify solidity is free software: you can redistribute it and/or modify
@ -19,6 +19,7 @@
#include <tools/solidityUpgrade/UpgradeChange.h> #include <tools/solidityUpgrade/UpgradeChange.h>
#include <tools/solidityUpgrade/Upgrade050.h> #include <tools/solidityUpgrade/Upgrade050.h>
#include <tools/solidityUpgrade/Upgrade060.h> #include <tools/solidityUpgrade/Upgrade060.h>
#include <tools/solidityUpgrade/Upgrade070.h>
#include <libsolidity/interface/CompilerStack.h> #include <libsolidity/interface/CompilerStack.h>
#include <libsolidity/interface/DebugSettings.h> #include <libsolidity/interface/DebugSettings.h>
@ -56,7 +57,8 @@ private:
VisibilitySpecifier, VisibilitySpecifier,
AbstractContract, AbstractContract,
OverridingFunction, OverridingFunction,
VirtualFunction VirtualFunction,
DotSyntax
}; };
/// Upgrade suite that hosts all available modules. /// Upgrade suite that hosts all available modules.
@ -78,6 +80,10 @@ private:
OverridingFunction{m_changes}.analyze(_sourceUnit); OverridingFunction{m_changes}.analyze(_sourceUnit);
if (isActivated(Module::VirtualFunction)) if (isActivated(Module::VirtualFunction))
VirtualFunction{m_changes}.analyze(_sourceUnit); VirtualFunction{m_changes}.analyze(_sourceUnit);
/// Solidity 0.7.0
if (isActivated(Module::DotSyntax))
DotSyntax{m_changes}.analyze(_sourceUnit);
} }
void activateModule(Module _module) { m_modules.insert(_module); } void activateModule(Module _module) { m_modules.insert(_module); }
@ -96,7 +102,8 @@ private:
Module::VisibilitySpecifier, Module::VisibilitySpecifier,
Module::AbstractContract, Module::AbstractContract,
Module::OverridingFunction, Module::OverridingFunction,
Module::VirtualFunction Module::VirtualFunction,
Module::DotSyntax
}; };
}; };

View File

@ -0,0 +1,42 @@
/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
n You should have received a copy of the GNU General Public License
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
#include <tools/solidityUpgrade/Upgrade070.h>
#include <tools/solidityUpgrade/SourceTransform.h>
using namespace solidity::frontend;
using namespace solidity::tools;
void DotSyntax::endVisit(FunctionCall const& _functionCall)
{
TypePointer type = _functionCall.annotation().type;
if (auto const funcType = dynamic_cast<FunctionType const*>(type))
{
if (funcType->valueSet())
m_changes.emplace_back(
UpgradeChange::Level::Safe,
_functionCall.location(),
SourceTransform::valueUpdate(_functionCall.location())
);
if (funcType->gasSet())
m_changes.emplace_back(
UpgradeChange::Level::Safe,
_functionCall.location(),
SourceTransform::gasUpdate(_functionCall.location())
);
}
}

View File

@ -0,0 +1,35 @@
/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <tools/solidityUpgrade/UpgradeSuite.h>
#include <libsolidity/ast/AST.h>
namespace solidity::tools
{
class DotSyntax: public AnalysisUpgrade
{
public:
using AnalysisUpgrade::AnalysisUpgrade;
void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); }
private:
void endVisit(frontend::FunctionCall const& _expression) override;
};
}

View File

@ -23,6 +23,7 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
#include <boost/exception/all.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
@ -74,8 +75,16 @@ int main(int argc, char** argv)
if (!upgrade.parseArguments(argc, argv)) if (!upgrade.parseArguments(argc, argv))
return 1; return 1;
upgrade.printPrologue(); upgrade.printPrologue();
if (!upgrade.processInput())
return 1; try
{
if (!upgrade.processInput())
return 1;
}
catch (boost::exception const& _exception)
{
cerr << "Exception while processing input: " << boost::diagnostic_information(_exception) << endl;
}
return 0; return 0;
} }