Adds natspec to AST for enum definition.

This commit is contained in:
Christian Parpart 2022-10-12 15:09:12 +02:00 committed by Nikola Matic
parent 7b634152bd
commit be8752b5d3
12 changed files with 180 additions and 10 deletions

View File

@ -4,6 +4,7 @@ Language Features:
Compiler Features: Compiler Features:
* NatSpec: Add support for NatSpec documentation in ``enum`` definitions.
* SMTChecker: Properties that are proved safe are now reported explicitly at the end of the analysis. By default, only the number of safe properties is shown. The CLI option ``--model-checker-show-proved-safe`` and the JSON option ``settings.modelChecker.showProvedSafe`` can be enabled to show the full list of safe properties. * SMTChecker: Properties that are proved safe are now reported explicitly at the end of the analysis. By default, only the number of safe properties is shown. The CLI option ``--model-checker-show-proved-safe`` and the JSON option ``settings.modelChecker.showProvedSafe`` can be enabled to show the full list of safe properties.
* SMTChecker: Group all messages about unsupported language features in a single warning. The CLI option ``--model-checker-show-unsupported`` and the JSON option ``settings.modelChecker.showUnsupported`` can be enabled to show the full list. * SMTChecker: Group all messages about unsupported language features in a single warning. The CLI option ``--model-checker-show-unsupported`` and the JSON option ``settings.modelChecker.showUnsupported`` can be enabled to show the full list.
* Optimizer: Re-implement simplified version of UnusedAssignEliminator and UnusedStoreEliminator. It can correctly remove some unused assignments in deeply nested loops that were ignored by the old version. * Optimizer: Re-implement simplified version of UnusedAssignEliminator and UnusedStoreEliminator. It can correctly remove some unused assignments in deeply nested loops that were ignored by the old version.

View File

@ -737,7 +737,7 @@ private:
std::vector<ASTPointer<VariableDeclaration>> m_members; std::vector<ASTPointer<VariableDeclaration>> m_members;
}; };
class EnumDefinition: public Declaration, public ScopeOpener class EnumDefinition: public Declaration, public StructurallyDocumented, public ScopeOpener
{ {
public: public:
EnumDefinition( EnumDefinition(
@ -745,9 +745,14 @@ public:
SourceLocation const& _location, SourceLocation const& _location,
ASTPointer<ASTString> const& _name, ASTPointer<ASTString> const& _name,
SourceLocation _nameLocation, SourceLocation _nameLocation,
std::vector<ASTPointer<EnumValue>> _members std::vector<ASTPointer<EnumValue>> _members,
ASTPointer<StructuredDocumentation> _documentation
): ):
Declaration(_id, _location, _name, std::move(_nameLocation)), m_members(std::move(_members)) {} Declaration(_id, _location, _name, std::move(_nameLocation)),
StructurallyDocumented(std::move(_documentation)),
m_members(std::move(_members))
{}
void accept(ASTVisitor& _visitor) override; void accept(ASTVisitor& _visitor) override;
void accept(ASTConstVisitor& _visitor) const override; void accept(ASTConstVisitor& _visitor) const override;

View File

@ -384,6 +384,7 @@ bool ASTJsonExporter::visit(EnumDefinition const& _node)
std::vector<pair<string, Json::Value>> attributes = { std::vector<pair<string, Json::Value>> attributes = {
make_pair("name", _node.name()), make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
make_pair("members", toJson(_node.members())) make_pair("members", toJson(_node.members()))
}; };

View File

@ -462,7 +462,8 @@ ASTPointer<EnumDefinition> ASTJsonImporter::createEnumDefinition(Json::Value con
_node, _node,
memberAsASTString(_node, "name"), memberAsASTString(_node, "name"),
createNameSourceLocation(_node), createNameSourceLocation(_node),
members members,
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation"))
); );
} }

View File

@ -706,6 +706,7 @@ ASTPointer<EnumDefinition> Parser::parseEnumDefinition()
{ {
RecursionGuard recursionGuard(*this); RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory(*this); ASTNodeFactory nodeFactory(*this);
ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
expectToken(Token::Enum); expectToken(Token::Enum);
auto [name, nameLocation] = expectIdentifierWithLocation(); auto [name, nameLocation] = expectIdentifierWithLocation();
vector<ASTPointer<EnumValue>> members; vector<ASTPointer<EnumValue>> members;
@ -725,7 +726,7 @@ ASTPointer<EnumDefinition> Parser::parseEnumDefinition()
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();
expectToken(Token::RBrace); expectToken(Token::RBrace);
return nodeFactory.createNode<EnumDefinition>(name, nameLocation, members); return nodeFactory.createNode<EnumDefinition>(name, nameLocation, members, documentation);
} }
ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration( ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(

View File

@ -0,0 +1,48 @@
{
"absolutePath": "a",
"exportedSymbols":
{
"Color":
[
4
]
},
"id": 5,
"nodeType": "SourceUnit",
"nodes":
[
{
"canonicalName": "Color",
"documentation":
{
"id": 1,
"nodeType": "StructuredDocumentation",
"src": "0:112:1",
"text": "@title example of title\n @author example of author\n @notice example of notice\n @dev example of dev"
},
"id": 4,
"members":
[
{
"id": 2,
"name": "Red",
"nameLocation": "129:3:1",
"nodeType": "EnumValue",
"src": "129:3:1"
},
{
"id": 3,
"name": "Green",
"nameLocation": "138:5:1",
"nodeType": "EnumValue",
"src": "138:5:1"
}
],
"name": "Color",
"nameLocation": "117:5:1",
"nodeType": "EnumDefinition",
"src": "112:33:1"
}
],
"src": "112:34:1"
}

View File

@ -0,0 +1,10 @@
/// @title example of title
/// @author example of author
/// @notice example of notice
/// @dev example of dev
enum Color {
Red,
Green
}
// ----

View File

@ -0,0 +1,40 @@
{
"absolutePath": "a",
"id": 5,
"nodeType": "SourceUnit",
"nodes":
[
{
"documentation":
{
"id": 1,
"nodeType": "StructuredDocumentation",
"src": "0:112:1",
"text": "@title example of title\n @author example of author\n @notice example of notice\n @dev example of dev"
},
"id": 4,
"members":
[
{
"id": 2,
"name": "Red",
"nameLocation": "129:3:1",
"nodeType": "EnumValue",
"src": "129:3:1"
},
{
"id": 3,
"name": "Green",
"nameLocation": "138:5:1",
"nodeType": "EnumValue",
"src": "138:5:1"
}
],
"name": "Color",
"nameLocation": "117:5:1",
"nodeType": "EnumDefinition",
"src": "112:33:1"
}
],
"src": "112:34:1"
}

View File

@ -1076,6 +1076,40 @@ BOOST_AUTO_TEST_CASE(dev_author_at_function)
expectNatspecError(sourceCode); expectNatspecError(sourceCode);
} }
BOOST_AUTO_TEST_CASE(enum_no_docs)
{
char const* sourceCode = R"(
contract C {
/// @title example of title
/// @author example of author
/// @notice example of notice
/// @dev example of dev
enum Color {
Red,
Green
}
}
)";
char const* devDoc = R"ABCDEF(
{
"kind": "dev",
"methods": {},
"version": 1
})ABCDEF";
checkNatspec(sourceCode, "C", devDoc, false);
char const* userDoc = R"ABCDEF(
{
"kind": "user",
"methods": {},
"version": 1
})ABCDEF";
checkNatspec(sourceCode, "C", userDoc, true);
}
BOOST_AUTO_TEST_CASE(natspec_notice_without_tag) BOOST_AUTO_TEST_CASE(natspec_notice_without_tag)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(

View File

@ -191,7 +191,7 @@ BOOST_AUTO_TEST_CASE(type_identifiers)
s.annotation().recursive = false; s.annotation().recursive = false;
BOOST_CHECK_EQUAL(s.type()->identifier(), "t_type$_t_struct$_Struct_$3_storage_ptr_$"); BOOST_CHECK_EQUAL(s.type()->identifier(), "t_type$_t_struct$_Struct_$3_storage_ptr_$");
EnumDefinition e(++id, {}, make_shared<string>("Enum"), {}, {}); EnumDefinition e(++id, {}, make_shared<string>("Enum"), {}, {}, {});
BOOST_CHECK_EQUAL(e.type()->identifier(), "t_type$_t_enum$_Enum_$4_$"); BOOST_CHECK_EQUAL(e.type()->identifier(), "t_type$_t_enum$_Enum_$4_$");
TupleType t({e.type(), s.type(), stringArray, nullptr}); TupleType t({e.type(), s.type(), stringArray, nullptr});

View File

@ -48,9 +48,18 @@ contract User
// <- { // <- {
// "contents": { // "contents": {
// "kind": "markdown", // "kind": "markdown",
// "value": "```solidity\ntype(enum User.SomeEnum)\n```\n\n" // "value": "```solidity\ntype(enum User.SomeEnum)\n```\n\nSome enum value.\n\n"
// }, // },
// "range": @Cursor1Range // "range": {
// "end": {
// "character": 12,
// "line": 17
// },
// "start": {
// "character": 4,
// "line": 17
// }
// }
// } // }
// -> textDocument/hover { // -> textDocument/hover {
// "position": @Cursor2 // "position": @Cursor2
@ -58,9 +67,18 @@ contract User
// <- { // <- {
// "contents": { // "contents": {
// "kind": "markdown", // "kind": "markdown",
// "value": "```solidity\ntype(enum User.SomeEnum)\n```\n\n" // "value": "```solidity\ntype(enum User.SomeEnum)\n```\n\nSome enum value.\n\n"
// }, // },
// "range": @Cursor2Range // "range": {
// "end": {
// "character": 32,
// "line": 22
// },
// "start": {
// "character": 24,
// "line": 22
// }
// }
// } // }
// -> textDocument/hover { // -> textDocument/hover {
// "position": @Cursor3 // "position": @Cursor3

View File

@ -0,0 +1,11 @@
contract C {
/// @title example of title
/// @author example of author
/// @notice example of notice
/// @dev example of dev
enum Color {
Red,
Green
}
}
// ----