diff options
author | Christian Parpart <christian@parpart.family> | 2018-07-11 22:33:09 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-11 22:33:09 +0800 |
commit | 08345209e6f68c509ec5af820596a2172b886568 (patch) | |
tree | 871e6013da5ab0870b4838bc8f31c369062f6722 /libsolidity/analysis | |
parent | f3abfa81ad3cdf3cfd0b9e1acf11329a617466a2 (diff) | |
parent | 458a4c8aa5dc88aed46ad1ab1494fa035af09e31 (diff) | |
download | dexon-solidity-08345209e6f68c509ec5af820596a2172b886568.tar.gz dexon-solidity-08345209e6f68c509ec5af820596a2172b886568.tar.zst dexon-solidity-08345209e6f68c509ec5af820596a2172b886568.zip |
Merge pull request #4404 from ethereum/v050-var-keyword-suggest
[WIP] v0.5.0 var keyword type suggestion
Diffstat (limited to 'libsolidity/analysis')
-rw-r--r-- | libsolidity/analysis/SyntaxChecker.cpp | 9 | ||||
-rw-r--r-- | libsolidity/analysis/SyntaxChecker.h | 2 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 71 |
3 files changed, 63 insertions, 19 deletions
diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 63f8fac3..4311e77d 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -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()) diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h index 1579df57..8ee3df37 100644 --- a/libsolidity/analysis/SyntaxChecker.h +++ b/libsolidity/analysis/SyntaxChecker.h @@ -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; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index da04ee96..8ea0a4d7 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -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; } |