Skip to content

Commit 306b55e

Browse files
committed
Adds NatSpec to AST for struct definitions.
1 parent f0c0df2 commit 306b55e

11 files changed

+288
-6
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Language Features:
2929

3030

3131
Compiler Features:
32+
* NatSpec: Add support for NatSpec documentation in ``struct`` definition.
3233
* SMTChecker: New trusted mode that assumes that any compile-time available code is the actual used code even in external calls. This can be used via the CLI option ``--model-checker-ext-calls trusted`` or the JSON field ``settings.modelChecker.extCalls: "trusted"``.
3334

3435

libsolidity/ast/AST.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -709,17 +709,21 @@ class UsingForDirective: public ASTNode
709709
bool m_global = false;
710710
};
711711

712-
class StructDefinition: public Declaration, public ScopeOpener
712+
class StructDefinition: public Declaration, public StructurallyDocumented, public ScopeOpener
713713
{
714714
public:
715715
StructDefinition(
716716
int64_t _id,
717717
SourceLocation const& _location,
718718
ASTPointer<ASTString> const& _name,
719719
SourceLocation _nameLocation,
720-
std::vector<ASTPointer<VariableDeclaration>> _members
720+
std::vector<ASTPointer<VariableDeclaration>> _members,
721+
ASTPointer<StructuredDocumentation> _documentation
721722
):
722-
Declaration(_id, _location, _name, std::move(_nameLocation)), m_members(std::move(_members)) {}
723+
Declaration(_id, _location, _name, std::move(_nameLocation)),
724+
StructurallyDocumented(std::move(_documentation)),
725+
m_members(std::move(_members))
726+
{}
723727

724728
void accept(ASTVisitor& _visitor) override;
725729
void accept(ASTConstVisitor& _visitor) const override;

libsolidity/ast/ASTJsonExporter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ bool ASTJsonExporter::visit(StructDefinition const& _node)
367367
std::vector<pair<string, Json::Value>> attributes = {
368368
make_pair("name", _node.name()),
369369
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
370+
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
370371
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
371372
make_pair("members", toJson(_node.members())),
372373
make_pair("scope", idOrNull(_node.scope()))

libsolidity/ast/ASTJsonImporter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,8 @@ ASTPointer<ASTNode> ASTJsonImporter::createStructDefinition(Json::Value const& _
449449
_node,
450450
memberAsASTString(_node, "name"),
451451
createNameSourceLocation(_node),
452-
members
452+
members,
453+
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation"))
453454
);
454455
}
455456

libsolidity/parsing/Parser.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ ASTPointer<StructDefinition> Parser::parseStructDefinition()
682682
{
683683
RecursionGuard recursionGuard(*this);
684684
ASTNodeFactory nodeFactory(*this);
685+
ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
685686
expectToken(Token::Struct);
686687
auto [name, nameLocation] = expectIdentifierWithLocation();
687688
vector<ASTPointer<VariableDeclaration>> members;
@@ -693,7 +694,7 @@ ASTPointer<StructDefinition> Parser::parseStructDefinition()
693694
}
694695
nodeFactory.markEndPosition();
695696
expectToken(Token::RBrace);
696-
return nodeFactory.createNode<StructDefinition>(std::move(name), std::move(nameLocation), std::move(members));
697+
return nodeFactory.createNode<StructDefinition>(std::move(name), std::move(nameLocation), std::move(members), std::move(documentation));
697698
}
698699

699700
ASTPointer<EnumValue> Parser::parseEnumValue()
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
{
2+
"absolutePath": "a",
3+
"exportedSymbols":
4+
{
5+
"Example":
6+
[
7+
8
8+
]
9+
},
10+
"id": 9,
11+
"nodeType": "SourceUnit",
12+
"nodes":
13+
[
14+
{
15+
"canonicalName": "Example",
16+
"documentation":
17+
{
18+
"id": 1,
19+
"nodeType": "StructuredDocumentation",
20+
"src": "0:112:1",
21+
"text": "@title example of title\n @author example of author\n @notice example of notice\n @dev example of dev"
22+
},
23+
"id": 8,
24+
"members":
25+
[
26+
{
27+
"constant": false,
28+
"id": 3,
29+
"mutability": "mutable",
30+
"name": "text",
31+
"nameLocation": "140:4:1",
32+
"nodeType": "VariableDeclaration",
33+
"scope": 8,
34+
"src": "133:11:1",
35+
"stateVariable": false,
36+
"storageLocation": "default",
37+
"typeDescriptions":
38+
{
39+
"typeIdentifier": "t_string_storage_ptr",
40+
"typeString": "string"
41+
},
42+
"typeName":
43+
{
44+
"id": 2,
45+
"name": "string",
46+
"nodeType": "ElementaryTypeName",
47+
"src": "133:6:1",
48+
"typeDescriptions":
49+
{
50+
"typeIdentifier": "t_string_storage_ptr",
51+
"typeString": "string"
52+
}
53+
},
54+
"visibility": "internal"
55+
},
56+
{
57+
"constant": false,
58+
"id": 5,
59+
"mutability": "mutable",
60+
"name": "valid",
61+
"nameLocation": "155:5:1",
62+
"nodeType": "VariableDeclaration",
63+
"scope": 8,
64+
"src": "150:10:1",
65+
"stateVariable": false,
66+
"storageLocation": "default",
67+
"typeDescriptions":
68+
{
69+
"typeIdentifier": "t_bool",
70+
"typeString": "bool"
71+
},
72+
"typeName":
73+
{
74+
"id": 4,
75+
"name": "bool",
76+
"nodeType": "ElementaryTypeName",
77+
"src": "150:4:1",
78+
"typeDescriptions":
79+
{
80+
"typeIdentifier": "t_bool",
81+
"typeString": "bool"
82+
}
83+
},
84+
"visibility": "internal"
85+
},
86+
{
87+
"constant": false,
88+
"id": 7,
89+
"mutability": "mutable",
90+
"name": "value",
91+
"nameLocation": "174:5:1",
92+
"nodeType": "VariableDeclaration",
93+
"scope": 8,
94+
"src": "166:13:1",
95+
"stateVariable": false,
96+
"storageLocation": "default",
97+
"typeDescriptions":
98+
{
99+
"typeIdentifier": "t_uint256",
100+
"typeString": "uint256"
101+
},
102+
"typeName":
103+
{
104+
"id": 6,
105+
"name": "uint256",
106+
"nodeType": "ElementaryTypeName",
107+
"src": "166:7:1",
108+
"typeDescriptions":
109+
{
110+
"typeIdentifier": "t_uint256",
111+
"typeString": "uint256"
112+
}
113+
},
114+
"visibility": "internal"
115+
}
116+
],
117+
"name": "Example",
118+
"nameLocation": "119:7:1",
119+
"nodeType": "StructDefinition",
120+
"scope": 9,
121+
"src": "112:70:1",
122+
"visibility": "public"
123+
}
124+
],
125+
"src": "112:71:1"
126+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// @title example of title
2+
/// @author example of author
3+
/// @notice example of notice
4+
/// @dev example of dev
5+
struct Example {
6+
string text;
7+
bool valid;
8+
uint256 value;
9+
}
10+
11+
// ----
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
{
2+
"absolutePath": "a",
3+
"id": 9,
4+
"nodeType": "SourceUnit",
5+
"nodes":
6+
[
7+
{
8+
"documentation":
9+
{
10+
"id": 1,
11+
"nodeType": "StructuredDocumentation",
12+
"src": "0:112:1",
13+
"text": "@title example of title\n @author example of author\n @notice example of notice\n @dev example of dev"
14+
},
15+
"id": 8,
16+
"members":
17+
[
18+
{
19+
"constant": false,
20+
"id": 3,
21+
"mutability": "mutable",
22+
"name": "text",
23+
"nameLocation": "140:4:1",
24+
"nodeType": "VariableDeclaration",
25+
"src": "133:11:1",
26+
"stateVariable": false,
27+
"storageLocation": "default",
28+
"typeDescriptions": {},
29+
"typeName":
30+
{
31+
"id": 2,
32+
"name": "string",
33+
"nodeType": "ElementaryTypeName",
34+
"src": "133:6:1",
35+
"typeDescriptions": {}
36+
},
37+
"visibility": "internal"
38+
},
39+
{
40+
"constant": false,
41+
"id": 5,
42+
"mutability": "mutable",
43+
"name": "valid",
44+
"nameLocation": "155:5:1",
45+
"nodeType": "VariableDeclaration",
46+
"src": "150:10:1",
47+
"stateVariable": false,
48+
"storageLocation": "default",
49+
"typeDescriptions": {},
50+
"typeName":
51+
{
52+
"id": 4,
53+
"name": "bool",
54+
"nodeType": "ElementaryTypeName",
55+
"src": "150:4:1",
56+
"typeDescriptions": {}
57+
},
58+
"visibility": "internal"
59+
},
60+
{
61+
"constant": false,
62+
"id": 7,
63+
"mutability": "mutable",
64+
"name": "value",
65+
"nameLocation": "174:5:1",
66+
"nodeType": "VariableDeclaration",
67+
"src": "166:13:1",
68+
"stateVariable": false,
69+
"storageLocation": "default",
70+
"typeDescriptions": {},
71+
"typeName":
72+
{
73+
"id": 6,
74+
"name": "uint256",
75+
"nodeType": "ElementaryTypeName",
76+
"src": "166:7:1",
77+
"typeDescriptions": {}
78+
},
79+
"visibility": "internal"
80+
}
81+
],
82+
"name": "Example",
83+
"nameLocation": "119:7:1",
84+
"nodeType": "StructDefinition",
85+
"src": "112:70:1",
86+
"visibility": "public"
87+
}
88+
],
89+
"src": "112:71:1"
90+
}

test/libsolidity/SolidityNatspecJSON.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,41 @@ BOOST_AUTO_TEST_CASE(dev_author_at_function)
10761076
expectNatspecError(sourceCode);
10771077
}
10781078

1079+
BOOST_AUTO_TEST_CASE(struct_no_docs)
1080+
{
1081+
char const* sourceCode = R"(
1082+
contract C {
1083+
/// @title example of title
1084+
/// @author example of author
1085+
/// @notice example of notice
1086+
/// @dev example of dev
1087+
struct Example {
1088+
string text;
1089+
bool valid;
1090+
uint256 value;
1091+
}
1092+
}
1093+
)";
1094+
1095+
char const* devDoc = R"ABCDEF(
1096+
{
1097+
"kind": "dev",
1098+
"methods": {},
1099+
"version": 1
1100+
})ABCDEF";
1101+
1102+
checkNatspec(sourceCode, "C", devDoc, false);
1103+
1104+
char const* userDoc = R"ABCDEF(
1105+
{
1106+
"kind": "user",
1107+
"methods": {},
1108+
"version": 1
1109+
})ABCDEF";
1110+
1111+
checkNatspec(sourceCode, "C", userDoc, true);
1112+
}
1113+
10791114
BOOST_AUTO_TEST_CASE(enum_no_docs)
10801115
{
10811116
char const* sourceCode = R"(

test/libsolidity/SolidityTypes.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ BOOST_AUTO_TEST_CASE(type_identifiers)
187187
BOOST_CHECK_EQUAL(c.type()->identifier(), "t_type$_t_contract$_MyContract$$$_$2_$");
188188
BOOST_CHECK_EQUAL(ContractType(c, true).identifier(), "t_super$_MyContract$$$_$2");
189189

190-
StructDefinition s(++id, {}, make_shared<string>("Struct"), {}, {});
190+
StructDefinition s(++id, {}, make_shared<string>("Struct"), {}, {}, {});
191191
s.annotation().recursive = false;
192192
BOOST_CHECK_EQUAL(s.type()->identifier(), "t_type$_t_struct$_Struct_$3_storage_ptr_$");
193193

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
contract C {
2+
/// @title example of title
3+
/// @author example of author
4+
/// @notice example of notice
5+
/// @dev example of dev
6+
struct Example {
7+
string text;
8+
bool valid;
9+
uint256 value;
10+
}
11+
}
12+
// ----

0 commit comments

Comments
 (0)