mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #9839 from ethereum/annotations-optional
Make annotations ``SetOnce`` or ``optional`` where feasible
This commit is contained in:
@@ -492,7 +492,7 @@ CallableDeclaration const* Scopable::functionOrModifierDefinition() const
|
||||
|
||||
string Scopable::sourceUnitName() const
|
||||
{
|
||||
return sourceUnit().annotation().path;
|
||||
return *sourceUnit().annotation().path;
|
||||
}
|
||||
|
||||
DeclarationAnnotation& Declaration::annotation() const
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace solidity::frontend
|
||||
|
||||
class Type;
|
||||
using TypePointer = Type const*;
|
||||
using namespace util;
|
||||
|
||||
struct ASTAnnotation
|
||||
{
|
||||
@@ -88,9 +89,9 @@ struct StructurallyDocumentedAnnotation
|
||||
struct SourceUnitAnnotation: ASTAnnotation
|
||||
{
|
||||
/// The "absolute" (in the compiler sense) path of this source unit.
|
||||
std::string path;
|
||||
SetOnce<std::string> path;
|
||||
/// The exported symbols (all global symbols).
|
||||
std::map<ASTString, std::vector<Declaration const*>> exportedSymbols;
|
||||
SetOnce<std::map<ASTString, std::vector<Declaration const*>>> exportedSymbols;
|
||||
/// Experimental features.
|
||||
std::set<ExperimentalFeature> experimentalFeatures;
|
||||
};
|
||||
@@ -122,7 +123,7 @@ struct DeclarationAnnotation: ASTAnnotation, ScopableAnnotation
|
||||
struct ImportAnnotation: DeclarationAnnotation
|
||||
{
|
||||
/// The absolute path of the source unit to import.
|
||||
std::string absolutePath;
|
||||
SetOnce<std::string> absolutePath;
|
||||
/// The actual source unit.
|
||||
SourceUnit const* sourceUnit = nullptr;
|
||||
};
|
||||
@@ -130,7 +131,7 @@ struct ImportAnnotation: DeclarationAnnotation
|
||||
struct TypeDeclarationAnnotation: DeclarationAnnotation
|
||||
{
|
||||
/// The name of this type, prefixed by proper namespaces if globally accessible.
|
||||
std::string canonicalName;
|
||||
SetOnce<std::string> canonicalName;
|
||||
};
|
||||
|
||||
struct StructDeclarationAnnotation: TypeDeclarationAnnotation
|
||||
@@ -149,7 +150,7 @@ struct StructDeclarationAnnotation: TypeDeclarationAnnotation
|
||||
struct ContractDefinitionAnnotation: TypeDeclarationAnnotation, StructurallyDocumentedAnnotation
|
||||
{
|
||||
/// List of functions and modifiers without a body. Can also contain functions from base classes.
|
||||
std::vector<Declaration const*> unimplementedDeclarations;
|
||||
std::optional<std::vector<Declaration const*>> unimplementedDeclarations;
|
||||
/// List of all (direct and indirect) base contracts in order from derived to
|
||||
/// base, including the contract itself.
|
||||
std::vector<ContractDefinition const*> linearizedBaseContracts;
|
||||
@@ -243,16 +244,16 @@ struct ExpressionAnnotation: ASTAnnotation
|
||||
/// Inferred type of the expression.
|
||||
TypePointer type = nullptr;
|
||||
/// Whether the expression is a constant variable
|
||||
bool isConstant = false;
|
||||
SetOnce<bool> isConstant;
|
||||
/// Whether the expression is pure, i.e. compile-time constant.
|
||||
bool isPure = false;
|
||||
SetOnce<bool> isPure;
|
||||
/// Whether it is an LValue (i.e. something that can be assigned to).
|
||||
bool isLValue = false;
|
||||
SetOnce<bool> isLValue;
|
||||
/// Whether the expression is used in a context where the LValue is actually required.
|
||||
bool willBeWrittenTo = false;
|
||||
/// Whether the expression is an lvalue that is only assigned.
|
||||
/// Would be false for --, ++, delete, +=, -=, ....
|
||||
bool lValueOfOrdinaryAssignment = false;
|
||||
SetOnce<bool> lValueOfOrdinaryAssignment;
|
||||
|
||||
/// Types and - if given - names of arguments if the expr. is a function
|
||||
/// that is called, used for overload resolution
|
||||
|
||||
@@ -39,10 +39,33 @@
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::langutil;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template<typename V, template<typename> typename C>
|
||||
void addIfSet(std::vector<pair<string, Json::Value>>& _attributes, string const& _name, C<V> const& _value)
|
||||
{
|
||||
if constexpr (std::is_same_v<C<V>, solidity::util::SetOnce<V>>)
|
||||
{
|
||||
if (!_value.set())
|
||||
return;
|
||||
}
|
||||
else if constexpr (std::is_same_v<C<V>, optional<V>>)
|
||||
{
|
||||
if (!_value.has_value())
|
||||
return;
|
||||
}
|
||||
|
||||
_attributes.emplace_back(_name, *_value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace solidity::frontend
|
||||
{
|
||||
|
||||
@@ -181,12 +204,14 @@ void ASTJsonConverter::appendExpressionAttributes(
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> exprAttributes = {
|
||||
make_pair("typeDescriptions", typePointerToJson(_annotation.type)),
|
||||
make_pair("isConstant", _annotation.isConstant),
|
||||
make_pair("isPure", _annotation.isPure),
|
||||
make_pair("isLValue", _annotation.isLValue),
|
||||
make_pair("lValueRequested", _annotation.willBeWrittenTo),
|
||||
make_pair("argumentTypes", typePointerToJson(_annotation.arguments))
|
||||
};
|
||||
|
||||
addIfSet(exprAttributes, "isLValue", _annotation.isLValue);
|
||||
addIfSet(exprAttributes, "isPure", _annotation.isPure);
|
||||
addIfSet(exprAttributes, "isConstant", _annotation.isConstant);
|
||||
|
||||
_attributes += exprAttributes;
|
||||
}
|
||||
|
||||
@@ -214,23 +239,27 @@ Json::Value ASTJsonConverter::toJson(ASTNode const& _node)
|
||||
|
||||
bool ASTJsonConverter::visit(SourceUnit const& _node)
|
||||
{
|
||||
Json::Value exportedSymbols = Json::objectValue;
|
||||
for (auto const& sym: _node.annotation().exportedSymbols)
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("license", _node.licenseString() ? Json::Value(*_node.licenseString()) : Json::nullValue),
|
||||
make_pair("nodes", toJson(_node.nodes()))
|
||||
};
|
||||
|
||||
if (_node.annotation().exportedSymbols.set())
|
||||
{
|
||||
exportedSymbols[sym.first] = Json::arrayValue;
|
||||
for (Declaration const* overload: sym.second)
|
||||
exportedSymbols[sym.first].append(nodeId(*overload));
|
||||
}
|
||||
setJsonNode(
|
||||
_node,
|
||||
"SourceUnit",
|
||||
Json::Value exportedSymbols = Json::objectValue;
|
||||
for (auto const& sym: *_node.annotation().exportedSymbols)
|
||||
{
|
||||
make_pair("absolutePath", _node.annotation().path),
|
||||
make_pair("exportedSymbols", move(exportedSymbols)),
|
||||
make_pair("license", _node.licenseString() ? Json::Value(*_node.licenseString()) : Json::nullValue),
|
||||
make_pair("nodes", toJson(_node.nodes()))
|
||||
exportedSymbols[sym.first] = Json::arrayValue;
|
||||
for (Declaration const* overload: sym.second)
|
||||
exportedSymbols[sym.first].append(nodeId(*overload));
|
||||
}
|
||||
);
|
||||
|
||||
attributes.emplace_back("exportedSymbols", exportedSymbols);
|
||||
};
|
||||
|
||||
addIfSet(attributes, "absolutePath", _node.annotation().path);
|
||||
|
||||
setJsonNode(_node, "SourceUnit", std::move(attributes));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -249,10 +278,12 @@ bool ASTJsonConverter::visit(ImportDirective const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("file", _node.path()),
|
||||
make_pair("absolutePath", _node.annotation().absolutePath),
|
||||
make_pair(m_legacy ? "SourceUnit" : "sourceUnit", nodeId(*_node.annotation().sourceUnit)),
|
||||
make_pair("scope", idOrNull(_node.scope()))
|
||||
};
|
||||
|
||||
addIfSet(attributes, "absolutePath", _node.annotation().absolutePath);
|
||||
|
||||
attributes.emplace_back("unitAlias", _node.name());
|
||||
Json::Value symbolAliases(Json::arrayValue);
|
||||
for (auto const& symbolAlias: _node.symbolAliases())
|
||||
@@ -270,18 +301,23 @@ bool ASTJsonConverter::visit(ImportDirective const& _node)
|
||||
|
||||
bool ASTJsonConverter::visit(ContractDefinition const& _node)
|
||||
{
|
||||
setJsonNode(_node, "ContractDefinition", {
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("name", _node.name()),
|
||||
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||
make_pair("contractKind", contractKind(_node.contractKind())),
|
||||
make_pair("abstract", _node.abstract()),
|
||||
make_pair("fullyImplemented", _node.annotation().unimplementedDeclarations.empty()),
|
||||
make_pair("linearizedBaseContracts", getContainerIds(_node.annotation().linearizedBaseContracts)),
|
||||
make_pair("baseContracts", toJson(_node.baseContracts())),
|
||||
make_pair("contractDependencies", getContainerIds(_node.annotation().contractDependencies, true)),
|
||||
make_pair("nodes", toJson(_node.subNodes())),
|
||||
make_pair("scope", idOrNull(_node.scope()))
|
||||
});
|
||||
};
|
||||
|
||||
if (_node.annotation().unimplementedDeclarations.has_value())
|
||||
attributes.emplace_back("fullyImplemented", _node.annotation().unimplementedDeclarations->empty());
|
||||
if (!_node.annotation().linearizedBaseContracts.empty())
|
||||
attributes.emplace_back("linearizedBaseContracts", getContainerIds(_node.annotation().linearizedBaseContracts));
|
||||
|
||||
setJsonNode(_node, "ContractDefinition", std::move(attributes));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -305,23 +341,31 @@ bool ASTJsonConverter::visit(UsingForDirective const& _node)
|
||||
|
||||
bool ASTJsonConverter::visit(StructDefinition const& _node)
|
||||
{
|
||||
setJsonNode(_node, "StructDefinition", {
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("name", _node.name()),
|
||||
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
||||
make_pair("canonicalName", _node.annotation().canonicalName),
|
||||
make_pair("members", toJson(_node.members())),
|
||||
make_pair("scope", idOrNull(_node.scope()))
|
||||
});
|
||||
};
|
||||
|
||||
addIfSet(attributes,"canonicalName", _node.annotation().canonicalName);
|
||||
|
||||
setJsonNode(_node, "StructDefinition", std::move(attributes));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ASTJsonConverter::visit(EnumDefinition const& _node)
|
||||
{
|
||||
setJsonNode(_node, "EnumDefinition", {
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("name", _node.name()),
|
||||
make_pair("canonicalName", _node.annotation().canonicalName),
|
||||
make_pair("members", toJson(_node.members()))
|
||||
});
|
||||
};
|
||||
|
||||
addIfSet(attributes,"canonicalName", _node.annotation().canonicalName);
|
||||
|
||||
setJsonNode(_node, "EnumDefinition", std::move(attributes));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -2115,7 +2115,7 @@ string ContractType::toString(bool) const
|
||||
|
||||
string ContractType::canonicalName() const
|
||||
{
|
||||
return m_contract.annotation().canonicalName;
|
||||
return *m_contract.annotation().canonicalName;
|
||||
}
|
||||
|
||||
MemberList::MemberMap ContractType::nativeMembers(ASTNode const*) const
|
||||
@@ -2366,7 +2366,7 @@ bool StructType::containsNestedMapping() const
|
||||
|
||||
string StructType::toString(bool _short) const
|
||||
{
|
||||
string ret = "struct " + m_struct.annotation().canonicalName;
|
||||
string ret = "struct " + *m_struct.annotation().canonicalName;
|
||||
if (!_short)
|
||||
ret += " " + stringForReferencePart();
|
||||
return ret;
|
||||
@@ -2545,7 +2545,7 @@ string StructType::signatureInExternalFunction(bool _structsByName) const
|
||||
|
||||
string StructType::canonicalName() const
|
||||
{
|
||||
return m_struct.annotation().canonicalName;
|
||||
return *m_struct.annotation().canonicalName;
|
||||
}
|
||||
|
||||
FunctionTypePointer StructType::constructorType() const
|
||||
@@ -2652,12 +2652,12 @@ unsigned EnumType::storageBytes() const
|
||||
|
||||
string EnumType::toString(bool) const
|
||||
{
|
||||
return string("enum ") + m_enum.annotation().canonicalName;
|
||||
return string("enum ") + *m_enum.annotation().canonicalName;
|
||||
}
|
||||
|
||||
string EnumType::canonicalName() const
|
||||
{
|
||||
return m_enum.annotation().canonicalName;
|
||||
return *m_enum.annotation().canonicalName;
|
||||
}
|
||||
|
||||
size_t EnumType::numberOfMembers() const
|
||||
@@ -3130,7 +3130,7 @@ string FunctionType::toString(bool _short) const
|
||||
auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(m_declaration);
|
||||
solAssert(functionDefinition, "");
|
||||
if (auto const* contract = dynamic_cast<ContractDefinition const*>(functionDefinition->scope()))
|
||||
name += contract->annotation().canonicalName + ".";
|
||||
name += *contract->annotation().canonicalName + ".";
|
||||
name += functionDefinition->name();
|
||||
}
|
||||
name += '(';
|
||||
@@ -3921,7 +3921,7 @@ bool ModuleType::operator==(Type const& _other) const
|
||||
MemberList::MemberMap ModuleType::nativeMembers(ASTNode const*) const
|
||||
{
|
||||
MemberList::MemberMap symbols;
|
||||
for (auto const& symbolName: m_sourceUnit.annotation().exportedSymbols)
|
||||
for (auto const& symbolName: *m_sourceUnit.annotation().exportedSymbols)
|
||||
for (Declaration const* symbol: symbolName.second)
|
||||
symbols.emplace_back(symbolName.first, symbol->type(), symbol);
|
||||
return symbols;
|
||||
@@ -3929,7 +3929,7 @@ MemberList::MemberMap ModuleType::nativeMembers(ASTNode const*) const
|
||||
|
||||
string ModuleType::toString(bool) const
|
||||
{
|
||||
return string("module \"") + m_sourceUnit.annotation().path + string("\"");
|
||||
return string("module \"") + *m_sourceUnit.annotation().path + string("\"");
|
||||
}
|
||||
|
||||
string MagicType::richIdentifier() const
|
||||
|
||||
Reference in New Issue
Block a user