@@ -47,6 +47,68 @@ bool DocStringTagParser::parseDocStrings(SourceUnit const& _sourceUnit)
4747 return errorWatcher.ok ();
4848}
4949
50+ bool DocStringTagParser::validateDocStringsUsingTypes (SourceUnit const & _sourceUnit)
51+ {
52+ ErrorReporter::ErrorWatcher errorWatcher = m_errorReporter.errorWatcher ();
53+
54+ SimpleASTVisitor visitReturns (
55+ [](ASTNode const &) { return true ; },
56+ [&](ASTNode const & _node)
57+ {
58+ if (auto const * annotation = dynamic_cast <StructurallyDocumentedAnnotation const *>(&_node.annotation ()))
59+ {
60+ auto const & documentationNode = dynamic_cast <StructurallyDocumented const &>(_node);
61+
62+ size_t returnTagsVisited = 0 ;
63+
64+ for (auto const & [tagName, tagValue]: annotation->docTags )
65+ if (tagName == " return" )
66+ {
67+ returnTagsVisited++;
68+ vector<string> returnParameterNames;
69+
70+ if (auto const * varDecl = dynamic_cast <VariableDeclaration const *>(&_node))
71+ {
72+ if (!varDecl->isPublic ())
73+ continue ;
74+
75+ // FunctionType() requires the DeclarationTypeChecker to have run.
76+ returnParameterNames = FunctionType (*varDecl).returnParameterNames ();
77+ }
78+ else if (auto const * function = dynamic_cast <FunctionDefinition const *>(&_node))
79+ returnParameterNames = FunctionType (*function).returnParameterNames ();
80+ else
81+ continue ;
82+
83+ string content = tagValue.content ;
84+ string firstWord = content.substr (0 , content.find_first_of (" \t " ));
85+
86+ if (returnTagsVisited > returnParameterNames.size ())
87+ m_errorReporter.docstringParsingError (
88+ 2604_error,
89+ documentationNode.documentation ()->location (),
90+ " Documentation tag \" @" + tagName + " " + content + " \" " +
91+ " exceeds the number of return parameters."
92+ );
93+ else
94+ {
95+ string const & parameter = returnParameterNames.at (returnTagsVisited - 1 );
96+ if (!parameter.empty () && parameter != firstWord)
97+ m_errorReporter.docstringParsingError (
98+ 5856_error,
99+ documentationNode.documentation ()->location (),
100+ " Documentation tag \" @" + tagName + " " + content + " \" " +
101+ " does not contain the name of its return parameter."
102+ );
103+ }
104+ }
105+ }
106+ });
107+
108+ _sourceUnit.accept (visitReturns);
109+ return errorWatcher.ok ();
110+ }
111+
50112bool DocStringTagParser::visit (ContractDefinition const & _contract)
51113{
52114 static set<string> const validTags = set<string>{" author" , " title" , " dev" , " notice" };
@@ -169,7 +231,6 @@ void DocStringTagParser::parseDocStrings(
169231
170232 _annotation.docTags = DocStringParser{*_node.documentation (), m_errorReporter}.parse ();
171233
172- size_t returnTagsVisited = 0 ;
173234 for (auto const & [tagName, tagValue]: _annotation.docTags )
174235 {
175236 string static const customPrefix (" custom:" );
@@ -196,43 +257,6 @@ void DocStringTagParser::parseDocStrings(
196257 _node.documentation ()->location (),
197258 " Documentation tag @" + tagName + " not valid for " + _nodeName + " ."
198259 );
199- else if (tagName == " return" )
200- {
201- returnTagsVisited++;
202- if (auto const * varDecl = dynamic_cast <VariableDeclaration const *>(&_node))
203- {
204- solAssert (varDecl->isPublic (), " @return is only allowed on public state-variables." );
205- if (returnTagsVisited > 1 )
206- m_errorReporter.docstringParsingError (
207- 5256_error,
208- _node.documentation ()->location (),
209- " Documentation tag \" @" + tagName + " \" is only allowed once on state-variables."
210- );
211- }
212- else if (auto const * function = dynamic_cast <FunctionDefinition const *>(&_node))
213- {
214- string content = tagValue.content ;
215- string firstWord = content.substr (0 , content.find_first_of (" \t " ));
216-
217- if (returnTagsVisited > function->returnParameters ().size ())
218- m_errorReporter.docstringParsingError (
219- 2604_error,
220- _node.documentation ()->location (),
221- " Documentation tag \" @" + tagName + " " + tagValue.content + " \" " +
222- " exceeds the number of return parameters."
223- );
224- else
225- {
226- auto parameter = function->returnParameters ().at (returnTagsVisited - 1 );
227- if (!parameter->name ().empty () && parameter->name () != firstWord)
228- m_errorReporter.docstringParsingError (
229- 5856_error,
230- _node.documentation ()->location (),
231- " Documentation tag \" @" + tagName + " " + tagValue.content + " \" " +
232- " does not contain the name of its return parameter."
233- );
234- }
235- }
236- }
237260 }
238261}
262+
0 commit comments