Make annotations `SetOnce or optional` where feasible

This commit is contained in:
Mathias Baumann
2020-09-22 17:38:21 +02:00
parent d80a81b01b
commit dd81d05559
18 changed files with 194 additions and 105 deletions
+1 -1
View File
@@ -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
+10 -9
View File
@@ -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
+72 -28
View File
@@ -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;
}
+8 -8
View File
@@ -2109,7 +2109,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
@@ -2360,7 +2360,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;
@@ -2539,7 +2539,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
@@ -2646,12 +2646,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
@@ -3124,7 +3124,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 += '(';
@@ -3915,7 +3915,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;
@@ -3923,7 +3923,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