mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #4404 from ethereum/v050-var-keyword-suggest
[WIP] v0.5.0 var keyword type suggestion
This commit is contained in:
commit
08345209e6
@ -254,15 +254,6 @@ bool SyntaxChecker::visit(FunctionTypeName const& _node)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SyntaxChecker::visit(VariableDeclaration const& _declaration)
|
||||
{
|
||||
if (!_declaration.typeName())
|
||||
{
|
||||
m_errorReporter.syntaxError(_declaration.location(), "Use of the \"var\" keyword is disallowed.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SyntaxChecker::visit(StructDefinition const& _struct)
|
||||
{
|
||||
if (_struct.members().empty())
|
||||
|
@ -69,8 +69,6 @@ private:
|
||||
virtual bool visit(FunctionDefinition const& _function) override;
|
||||
virtual bool visit(FunctionTypeName const& _node) override;
|
||||
|
||||
virtual bool visit(VariableDeclaration const& _declaration) override;
|
||||
|
||||
virtual bool visit(StructDefinition const& _struct) override;
|
||||
|
||||
ErrorReporter& m_errorReporter;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <libsolidity/analysis/TypeChecker.h>
|
||||
#include <memory>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <libsolidity/inlineasm/AsmAnalysis.h>
|
||||
@ -1036,6 +1037,47 @@ void TypeChecker::endVisit(EmitStatement const& _emit)
|
||||
m_insideEmitStatement = false;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
/**
|
||||
* @returns a suggested left-hand-side of a multi-variable declaration contairing
|
||||
* the variable declarations given in @a _decls.
|
||||
*/
|
||||
string createTupleDecl(vector<VariableDeclaration const*> const& _decls)
|
||||
{
|
||||
vector<string> components;
|
||||
for (VariableDeclaration const* decl: _decls)
|
||||
if (decl)
|
||||
components.emplace_back(decl->annotation().type->toString(false) + " " + decl->name());
|
||||
else
|
||||
components.emplace_back();
|
||||
|
||||
if (_decls.size() == 1)
|
||||
return components.front();
|
||||
else
|
||||
return "(" + boost::algorithm::join(components, ", ") + ")";
|
||||
}
|
||||
|
||||
bool typeCanBeExpressed(vector<VariableDeclaration const*> const& decls)
|
||||
{
|
||||
for (VariableDeclaration const* decl: decls)
|
||||
{
|
||||
// skip empty tuples (they can be expressed of course)
|
||||
if (!decl)
|
||||
continue;
|
||||
|
||||
if (auto functionType = dynamic_cast<FunctionType const*>(decl->annotation().type.get()))
|
||||
if (
|
||||
functionType->kind() != FunctionType::Kind::Internal &&
|
||||
functionType->kind() != FunctionType::Kind::External
|
||||
)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
|
||||
{
|
||||
bool const v050 = m_scope->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050);
|
||||
@ -1146,6 +1188,8 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
|
||||
else
|
||||
assignments[assignments.size() - i - 1] = variables[variables.size() - i - 1].get();
|
||||
|
||||
bool autoTypeDeductionNeeded = false;
|
||||
|
||||
for (size_t i = 0; i < assignments.size(); ++i)
|
||||
{
|
||||
if (!assignments[i])
|
||||
@ -1156,6 +1200,8 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
|
||||
solAssert(!!valueComponentType, "");
|
||||
if (!var.annotation().type)
|
||||
{
|
||||
autoTypeDeductionNeeded = true;
|
||||
|
||||
// Infer type from value.
|
||||
solAssert(!var.typeName(), "");
|
||||
var.annotation().type = valueComponentType->mobileType();
|
||||
@ -1199,14 +1245,6 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
|
||||
}
|
||||
else
|
||||
solAssert(dynamic_cast<FixedPointType const*>(var.annotation().type.get()), "Unknown type.");
|
||||
|
||||
m_errorReporter.warning(
|
||||
_statement.location(),
|
||||
"The type of this variable was inferred as " +
|
||||
typeName +
|
||||
extension +
|
||||
". This is probably not desired. Use an explicit type to silence this warning."
|
||||
);
|
||||
}
|
||||
|
||||
var.accept(*this);
|
||||
@ -1243,6 +1281,23 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (autoTypeDeductionNeeded)
|
||||
{
|
||||
if (!typeCanBeExpressed(assignments))
|
||||
m_errorReporter.syntaxError(
|
||||
_statement.location(),
|
||||
"Use of the \"var\" keyword is disallowed. "
|
||||
"Type cannot be expressed in syntax."
|
||||
);
|
||||
else
|
||||
m_errorReporter.syntaxError(
|
||||
_statement.location(),
|
||||
"Use of the \"var\" keyword is disallowed. "
|
||||
"Use explicit declaration `" + createTupleDecl(assignments) + " = ...´ instead."
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
23
test/libsolidity/syntaxTests/types/var_type_suggest.sol
Normal file
23
test/libsolidity/syntaxTests/types/var_type_suggest.sol
Normal file
@ -0,0 +1,23 @@
|
||||
contract C {
|
||||
function h() internal pure returns (uint, uint, uint) {
|
||||
return (1, 2, 4);
|
||||
}
|
||||
function g(uint x) internal pure returns (uint) {
|
||||
return x;
|
||||
}
|
||||
function f() internal pure {
|
||||
var i = 31415;
|
||||
var t = "string";
|
||||
var g2 = g;
|
||||
var myblockhash = block.blockhash;
|
||||
var (a, b) = (2, "troi");
|
||||
var (x,, z) = h();
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// SyntaxError: (224-237): Use of the "var" keyword is disallowed. Use explicit declaration `uint16 i = ...´ instead.
|
||||
// SyntaxError: (247-263): Use of the "var" keyword is disallowed. Use explicit declaration `string memory t = ...´ instead.
|
||||
// SyntaxError: (273-283): Use of the "var" keyword is disallowed. Use explicit declaration `function (uint256) pure returns (uint256) g2 = ...´ instead.
|
||||
// SyntaxError: (293-326): Use of the "var" keyword is disallowed. Type cannot be expressed in syntax.
|
||||
// SyntaxError: (336-360): Use of the "var" keyword is disallowed. Use explicit declaration `(uint8 a, string memory b) = ...´ instead.
|
||||
// SyntaxError: (370-387): Use of the "var" keyword is disallowed. Use explicit declaration `(uint256 x, , uint256 z) = ...´ instead.
|
Loading…
Reference in New Issue
Block a user