diff --git a/Changelog.md b/Changelog.md index 6c17c147b..85d2c86ee 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language 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: 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. diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 93a264622..631e93c45 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -737,7 +737,7 @@ private: std::vector> m_members; }; -class EnumDefinition: public Declaration, public ScopeOpener +class EnumDefinition: public Declaration, public StructurallyDocumented, public ScopeOpener { public: EnumDefinition( @@ -745,9 +745,14 @@ public: SourceLocation const& _location, ASTPointer const& _name, SourceLocation _nameLocation, - std::vector> _members + std::vector> _members, + ASTPointer _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(ASTConstVisitor& _visitor) const override; diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index e35d10821..6106bce14 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -384,6 +384,7 @@ bool ASTJsonExporter::visit(EnumDefinition const& _node) std::vector> attributes = { make_pair("name", _node.name()), make_pair("nameLocation", sourceLocationToString(_node.nameLocation())), + make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue), make_pair("members", toJson(_node.members())) }; diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index a1201983f..f63545fac 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -462,7 +462,8 @@ ASTPointer ASTJsonImporter::createEnumDefinition(Json::Value con _node, memberAsASTString(_node, "name"), createNameSourceLocation(_node), - members + members, + _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")) ); } diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index d3bdf549f..f1850fe1c 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -706,6 +706,7 @@ ASTPointer Parser::parseEnumDefinition() { RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); + ASTPointer documentation = parseStructuredDocumentation(); expectToken(Token::Enum); auto [name, nameLocation] = expectIdentifierWithLocation(); vector> members; @@ -725,7 +726,7 @@ ASTPointer Parser::parseEnumDefinition() nodeFactory.markEndPosition(); expectToken(Token::RBrace); - return nodeFactory.createNode(name, nameLocation, members); + return nodeFactory.createNode(name, nameLocation, members, documentation); } ASTPointer Parser::parseVariableDeclaration( diff --git a/test/libsolidity/ASTJSON/enum_natspec.json b/test/libsolidity/ASTJSON/enum_natspec.json new file mode 100644 index 000000000..f3cc7b8df --- /dev/null +++ b/test/libsolidity/ASTJSON/enum_natspec.json @@ -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" +} diff --git a/test/libsolidity/ASTJSON/enum_natspec.sol b/test/libsolidity/ASTJSON/enum_natspec.sol new file mode 100644 index 000000000..b9663fa9e --- /dev/null +++ b/test/libsolidity/ASTJSON/enum_natspec.sol @@ -0,0 +1,10 @@ +/// @title example of title +/// @author example of author +/// @notice example of notice +/// @dev example of dev +enum Color { + Red, + Green +} + +// ---- diff --git a/test/libsolidity/ASTJSON/enum_natspec_parseOnly.json b/test/libsolidity/ASTJSON/enum_natspec_parseOnly.json new file mode 100644 index 000000000..b5a38af6c --- /dev/null +++ b/test/libsolidity/ASTJSON/enum_natspec_parseOnly.json @@ -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" +} diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index 1a2c3af1f..decc489d5 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -1076,6 +1076,40 @@ BOOST_AUTO_TEST_CASE(dev_author_at_function) 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) { char const* sourceCode = R"( diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp index 63b943e97..139e73e31 100644 --- a/test/libsolidity/SolidityTypes.cpp +++ b/test/libsolidity/SolidityTypes.cpp @@ -191,7 +191,7 @@ BOOST_AUTO_TEST_CASE(type_identifiers) s.annotation().recursive = false; BOOST_CHECK_EQUAL(s.type()->identifier(), "t_type$_t_struct$_Struct_$3_storage_ptr_$"); - EnumDefinition e(++id, {}, make_shared("Enum"), {}, {}); + EnumDefinition e(++id, {}, make_shared("Enum"), {}, {}, {}); BOOST_CHECK_EQUAL(e.type()->identifier(), "t_type$_t_enum$_Enum_$4_$"); TupleType t({e.type(), s.type(), stringArray, nullptr}); diff --git a/test/libsolidity/lsp/hover/hover.sol b/test/libsolidity/lsp/hover/hover.sol index 9a1ee034c..154d2326e 100644 --- a/test/libsolidity/lsp/hover/hover.sol +++ b/test/libsolidity/lsp/hover/hover.sol @@ -48,9 +48,18 @@ contract User // <- { // "contents": { // "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 { // "position": @Cursor2 @@ -58,9 +67,18 @@ contract User // <- { // "contents": { // "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 { // "position": @Cursor3 diff --git a/test/libsolidity/syntaxTests/natspec/docstring_enum.sol b/test/libsolidity/syntaxTests/natspec/docstring_enum.sol new file mode 100644 index 000000000..d80484446 --- /dev/null +++ b/test/libsolidity/syntaxTests/natspec/docstring_enum.sol @@ -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 + } +} +// ----