Allow natspec comments on state variables.

This commit is contained in:
Alexander Arlt
2020-05-19 11:01:52 -05:00
parent 7d37ed4531
commit af8bb5fb60
21 changed files with 320 additions and 161 deletions
+35 -14
View File
@@ -59,9 +59,27 @@ bool DocStringAnalyser::visit(FunctionDefinition const& _function)
bool DocStringAnalyser::visit(VariableDeclaration const& _variable)
{
if (_variable.isStateVariable() && _variable.isPartOfExternalInterface())
handleDeclaration(_variable, _variable, _variable.annotation());
return true;
if (_variable.isStateVariable())
{
static set<string> const validPublicTags = set<string>{"dev", "notice", "return", "title", "author"};
if (_variable.isPublic())
parseDocStrings(_variable, _variable.annotation(), validPublicTags, "public state variables");
else
{
parseDocStrings(_variable, _variable.annotation(), validPublicTags, "non-public state variables");
if (_variable.annotation().docTags.count("notice") > 0)
m_errorReporter.warning(
9098_error, _variable.documentation()->location(),
"Documentation tag on non-public state variables will be disallowed in 0.7.0. You will need to use the @dev tag explicitly."
);
}
if (_variable.annotation().docTags.count("title") > 0 || _variable.annotation().docTags.count("author") > 0)
m_errorReporter.warning(
4822_error, _variable.documentation()->location(),
"Documentation tag @title and @author is only allowed on contract definitions. It will be disallowed in 0.7.0."
);
}
return false;
}
bool DocStringAnalyser::visit(ModifierDefinition const& _modifier)
@@ -124,16 +142,6 @@ void DocStringAnalyser::handleCallable(
checkParameters(_callable, _node, _annotation);
}
void DocStringAnalyser::handleDeclaration(
Declaration const&,
StructurallyDocumented const& _node,
StructurallyDocumentedAnnotation& _annotation
)
{
static set<string> const validTags = set<string>{"author", "dev", "notice", "return", "param"};
parseDocStrings(_node, _annotation, validTags, "state variables");
}
void DocStringAnalyser::parseDocStrings(
StructurallyDocumented const& _node,
StructurallyDocumentedAnnotation& _annotation,
@@ -161,7 +169,20 @@ void DocStringAnalyser::parseDocStrings(
if (docTag.first == "return")
{
returnTagsVisited++;
if (auto* function = dynamic_cast<FunctionDefinition const*>(&_node))
if (auto* varDecl = dynamic_cast<VariableDeclaration const*>(&_node))
{
if (!varDecl->isPublic())
appendError(
_node.documentation()->location(),
"Documentation tag \"@" + docTag.first + "\" is only allowed on public state-variables."
);
if (returnTagsVisited > 1)
appendError(
_node.documentation()->location(),
"Documentation tag \"@" + docTag.first + "\" is only allowed once on state-variables."
);
}
else if (auto* function = dynamic_cast<FunctionDefinition const*>(&_node))
{
string content = docTag.second.content;
string firstWord = content.substr(0, content.find_first_of(" \t"));
+4 -4
View File
@@ -882,7 +882,7 @@ public:
ASTPointer<ASTString> const& _name,
ASTPointer<Expression> _value,
Visibility _visibility,
ASTPointer<StructuredDocumentation> const& _documentation,
ASTPointer<StructuredDocumentation> const _documentation = nullptr,
bool _isStateVar = false,
bool _isIndexed = false,
Mutability _mutability = Mutability::Mutable,
@@ -890,9 +890,9 @@ public:
Location _referenceLocation = Location::Unspecified
):
Declaration(_id, _location, _name, _visibility),
StructurallyDocumented(_documentation),
m_typeName(_type),
m_value(_value),
StructurallyDocumented(std::move(_documentation)),
m_typeName(std::move(_type)),
m_value(std::move(_value)),
m_isStateVariable(_isStateVar),
m_isIndexed(_isIndexed),
m_mutability(_mutability),
+2 -3
View File
@@ -390,10 +390,9 @@ bool ASTJsonConverter::visit(VariableDeclaration const& _node)
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
};
if (_node.isStateVariable() && _node.isPublic())
{
attributes.emplace_back("functionSelector", _node.externalIdentifierHex());
attributes.emplace_back("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue);
}
if (_node.isStateVariable() && _node.documentation())
attributes.emplace_back("documentation", toJson(*_node.documentation()));
if (m_inEvent)
attributes.emplace_back("indexed", _node.isIndexed());
if (!_node.annotation().baseFunctions.empty())
+1 -1
View File
@@ -441,7 +441,7 @@ ASTPointer<VariableDeclaration> ASTJsonImporter::createVariableDeclaration(Json:
make_shared<ASTString>(member(_node, "name").asString()),
nullOrCast<Expression>(member(_node, "value")),
visibility(_node),
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")),
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")),
memberAsBool(_node, "stateVariable"),
_node.isMember("indexed") ? memberAsBool(_node, "indexed") : false,
mutability,
+14 -13
View File
@@ -40,7 +40,7 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef)
auto constructorDefinition(_contractDef.constructor());
if (constructorDefinition)
{
string value = extractDoc(constructorDefinition->annotation().docTags, "notice");
string const value = extractDoc(constructorDefinition->annotation().docTags, "notice");
if (!value.empty())
// add the constructor, only if we have any documentation to add
methods["constructor"] = Json::Value(value);
@@ -64,8 +64,9 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef)
methods[it.second->externalSignature()] = user;
}
}
if (auto var = dynamic_cast<VariableDeclaration const*>(&it.second->declaration()))
else if (auto var = dynamic_cast<VariableDeclaration const*>(&it.second->declaration()))
{
solAssert(var->isStateVariable() && var->isPublic(), "");
string value = extractDoc(var->annotation().docTags, "notice");
if (!value.empty())
{
@@ -121,22 +122,22 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef)
if (!method.empty())
methods[it.second->externalSignature()] = method;
}
if (auto var = dynamic_cast<VariableDeclaration const*>(&it.second->declaration()))
{
Json::Value method(devDocumentation(var->annotation().docTags));
if (!method.empty())
{
// Json::Value jsonReturn = extractReturnParameterDocs(var->annotation().docTags, *var);
}
// if (!jsonReturn.empty())
// method["returns"] = jsonReturn;
Json::Value stateVariables(Json::objectValue);
for (VariableDeclaration const* varDecl: _contractDef.stateVariables())
{
if (auto devDoc = devDocumentation(varDecl->annotation().docTags); !devDoc.empty())
stateVariables[varDecl->name()] = devDoc;
methods[it.second->externalSignature()] = method;
}
}
solAssert(varDecl->annotation().docTags.count("return") <= 1, "");
if (varDecl->annotation().docTags.count("return") == 1)
stateVariables[varDecl->name()]["return"] = extractDoc(varDecl->annotation().docTags, "return");
}
doc["methods"] = methods;
if (!stateVariables.empty())
doc["stateVariables"] = stateVariables;
return doc;
}
+5 -6
View File
@@ -686,7 +686,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
ASTNodeFactory nodeFactory = _lookAheadArrayType ?
ASTNodeFactory(*this, _lookAheadArrayType) : ASTNodeFactory(*this);
ASTPointer<TypeName> type;
ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
ASTPointer<StructuredDocumentation> const documentation = parseStructuredDocumentation();
if (_lookAheadArrayType)
type = _lookAheadArrayType;
else
@@ -696,8 +696,8 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
nodeFactory.setEndPositionFromNode(type);
}
// if (!_options.isStateVariable && documentation != nullptr)
// fatalParserError("Only state variables can retrieve a docstring.");
if (!_options.isStateVariable && documentation != nullptr)
parserWarning(2837_error, "Only state variables can have a docstring. This will be disallowed in 0.7.0.");
if (dynamic_cast<FunctionTypeName*>(type.get()) && _options.isStateVariable && m_scanner->currentToken() == Token::LBrace)
fatalParserError(
@@ -813,7 +813,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
identifier,
value,
visibility,
documentation,
documentation,
_options.isStateVariable,
isIndexed,
mutability,
@@ -1579,8 +1579,7 @@ ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStateme
ASTPointer<TypeName>(),
name,
ASTPointer<Expression>(),
Visibility::Default,
nullptr
Visibility::Default
);
}
variables.push_back(var);