mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #7834 from ethereum/docstring-ast-node
[natspec] Introduce AST node for structured documentation
This commit is contained in:
commit
2098dbade9
@ -6,6 +6,7 @@ Language Features:
|
|||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
* Code Generator: Use ``calldatacopy`` instead of ``codecopy`` to zero out memory past input.
|
* Code Generator: Use ``calldatacopy`` instead of ``codecopy`` to zero out memory past input.
|
||||||
|
* AST: Add a new node for doxygen-style, structured documentation that can be received by contract, function, event and modifier definitions.
|
||||||
|
|
||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
|
@ -428,6 +428,7 @@ Token Scanner::scanSlash()
|
|||||||
// doxygen style /// comment
|
// doxygen style /// comment
|
||||||
Token comment;
|
Token comment;
|
||||||
m_skippedComments[NextNext].location.start = firstSlashPosition;
|
m_skippedComments[NextNext].location.start = firstSlashPosition;
|
||||||
|
m_skippedComments[NextNext].location.source = m_source;
|
||||||
comment = scanSingleLineDocComment();
|
comment = scanSingleLineDocComment();
|
||||||
m_skippedComments[NextNext].location.end = sourcePos();
|
m_skippedComments[NextNext].location.end = sourcePos();
|
||||||
m_skippedComments[NextNext].token = comment;
|
m_skippedComments[NextNext].token = comment;
|
||||||
@ -454,6 +455,7 @@ Token Scanner::scanSlash()
|
|||||||
// we actually have a multiline documentation comment
|
// we actually have a multiline documentation comment
|
||||||
Token comment;
|
Token comment;
|
||||||
m_skippedComments[NextNext].location.start = firstSlashPosition;
|
m_skippedComments[NextNext].location.start = firstSlashPosition;
|
||||||
|
m_skippedComments[NextNext].location.source = m_source;
|
||||||
comment = scanMultiLineDocComment();
|
comment = scanMultiLineDocComment();
|
||||||
m_skippedComments[NextNext].location.end = sourcePos();
|
m_skippedComments[NextNext].location.end = sourcePos();
|
||||||
m_skippedComments[NextNext].token = comment;
|
m_skippedComments[NextNext].token = comment;
|
||||||
|
@ -73,7 +73,7 @@ bool DocStringAnalyser::visit(EventDefinition const& _event)
|
|||||||
|
|
||||||
void DocStringAnalyser::checkParameters(
|
void DocStringAnalyser::checkParameters(
|
||||||
CallableDeclaration const& _callable,
|
CallableDeclaration const& _callable,
|
||||||
DocumentedAnnotation& _annotation
|
StructurallyDocumentedAnnotation& _annotation
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
set<string> validParams;
|
set<string> validParams;
|
||||||
@ -95,8 +95,8 @@ void DocStringAnalyser::checkParameters(
|
|||||||
|
|
||||||
void DocStringAnalyser::handleConstructor(
|
void DocStringAnalyser::handleConstructor(
|
||||||
CallableDeclaration const& _callable,
|
CallableDeclaration const& _callable,
|
||||||
Documented const& _node,
|
StructurallyDocumented const& _node,
|
||||||
DocumentedAnnotation& _annotation
|
StructurallyDocumentedAnnotation& _annotation
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
static set<string> const validTags = set<string>{"author", "dev", "notice", "param"};
|
static set<string> const validTags = set<string>{"author", "dev", "notice", "param"};
|
||||||
@ -106,8 +106,8 @@ void DocStringAnalyser::handleConstructor(
|
|||||||
|
|
||||||
void DocStringAnalyser::handleCallable(
|
void DocStringAnalyser::handleCallable(
|
||||||
CallableDeclaration const& _callable,
|
CallableDeclaration const& _callable,
|
||||||
Documented const& _node,
|
StructurallyDocumented const& _node,
|
||||||
DocumentedAnnotation& _annotation
|
StructurallyDocumentedAnnotation& _annotation
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
static set<string> const validTags = set<string>{"author", "dev", "notice", "return", "param"};
|
static set<string> const validTags = set<string>{"author", "dev", "notice", "return", "param"};
|
||||||
@ -116,16 +116,16 @@ void DocStringAnalyser::handleCallable(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DocStringAnalyser::parseDocStrings(
|
void DocStringAnalyser::parseDocStrings(
|
||||||
Documented const& _node,
|
StructurallyDocumented const& _node,
|
||||||
DocumentedAnnotation& _annotation,
|
StructurallyDocumentedAnnotation& _annotation,
|
||||||
set<string> const& _validTags,
|
set<string> const& _validTags,
|
||||||
string const& _nodeName
|
string const& _nodeName
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
DocStringParser parser;
|
DocStringParser parser;
|
||||||
if (_node.documentation() && !_node.documentation()->empty())
|
if (_node.documentation() && !_node.documentation()->text()->empty())
|
||||||
{
|
{
|
||||||
if (!parser.parse(*_node.documentation(), m_errorReporter))
|
if (!parser.parse(*_node.documentation()->text(), m_errorReporter))
|
||||||
m_errorOccured = true;
|
m_errorOccured = true;
|
||||||
_annotation.docTags = parser.tags();
|
_annotation.docTags = parser.tags();
|
||||||
}
|
}
|
||||||
|
@ -51,24 +51,24 @@ private:
|
|||||||
|
|
||||||
void checkParameters(
|
void checkParameters(
|
||||||
CallableDeclaration const& _callable,
|
CallableDeclaration const& _callable,
|
||||||
DocumentedAnnotation& _annotation
|
StructurallyDocumentedAnnotation& _annotation
|
||||||
);
|
);
|
||||||
|
|
||||||
void handleConstructor(
|
void handleConstructor(
|
||||||
CallableDeclaration const& _callable,
|
CallableDeclaration const& _callable,
|
||||||
Documented const& _node,
|
StructurallyDocumented const& _node,
|
||||||
DocumentedAnnotation& _annotation
|
StructurallyDocumentedAnnotation& _annotation
|
||||||
);
|
);
|
||||||
|
|
||||||
void handleCallable(
|
void handleCallable(
|
||||||
CallableDeclaration const& _callable,
|
CallableDeclaration const& _callable,
|
||||||
Documented const& _node,
|
StructurallyDocumented const& _node,
|
||||||
DocumentedAnnotation& _annotation
|
StructurallyDocumentedAnnotation& _annotation
|
||||||
);
|
);
|
||||||
|
|
||||||
void parseDocStrings(
|
void parseDocStrings(
|
||||||
Documented const& _node,
|
StructurallyDocumented const& _node,
|
||||||
DocumentedAnnotation& _annotation,
|
StructurallyDocumentedAnnotation& _annotation,
|
||||||
std::set<std::string> const& _validTags,
|
std::set<std::string> const& _validTags,
|
||||||
std::string const& _nodeName
|
std::string const& _nodeName
|
||||||
);
|
);
|
||||||
|
@ -345,6 +345,30 @@ private:
|
|||||||
std::vector<VariableDeclaration const*> m_localVariables;
|
std::vector<VariableDeclaration const*> m_localVariables;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The doxygen-style, structured documentation class that represents an AST node.
|
||||||
|
*/
|
||||||
|
class StructuredDocumentation: public ASTNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StructuredDocumentation(
|
||||||
|
int64_t _id,
|
||||||
|
SourceLocation const& _location,
|
||||||
|
ASTPointer<ASTString> const& _text
|
||||||
|
): ASTNode(_id, _location), m_text(_text)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void accept(ASTVisitor& _visitor) override;
|
||||||
|
void accept(ASTConstVisitor& _visitor) const override;
|
||||||
|
|
||||||
|
/// @return A shared pointer of an ASTString.
|
||||||
|
/// Contains doxygen-style, structured documentation that is parsed later on.
|
||||||
|
ASTPointer<ASTString> const& text() const { return m_text; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ASTPointer<ASTString> m_text;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class that is added to each AST node that can receive documentation.
|
* Abstract class that is added to each AST node that can receive documentation.
|
||||||
*/
|
*/
|
||||||
@ -362,6 +386,24 @@ protected:
|
|||||||
ASTPointer<ASTString> m_documentation;
|
ASTPointer<ASTString> m_documentation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract class that is added to each AST node that can receive a structured documentation.
|
||||||
|
*/
|
||||||
|
class StructurallyDocumented
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~StructurallyDocumented() = default;
|
||||||
|
explicit StructurallyDocumented(ASTPointer<StructuredDocumentation> const& _documentation): m_documentation(_documentation) {}
|
||||||
|
|
||||||
|
/// @return A shared pointer of a FormalDocumentation.
|
||||||
|
/// Can contain a nullptr in which case indicates absence of documentation
|
||||||
|
ASTPointer<StructuredDocumentation> const& documentation() const { return m_documentation; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ASTPointer<StructuredDocumentation> m_documentation;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class that is added to AST nodes that can be marked as not being fully implemented
|
* Abstract class that is added to AST nodes that can be marked as not being fully implemented
|
||||||
*/
|
*/
|
||||||
@ -385,21 +427,21 @@ protected:
|
|||||||
* document order. It first visits all struct declarations, then all variable declarations and
|
* document order. It first visits all struct declarations, then all variable declarations and
|
||||||
* finally all function declarations.
|
* finally all function declarations.
|
||||||
*/
|
*/
|
||||||
class ContractDefinition: public Declaration, public Documented
|
class ContractDefinition: public Declaration, public StructurallyDocumented
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ContractDefinition(
|
ContractDefinition(
|
||||||
int64_t _id,
|
int64_t _id,
|
||||||
SourceLocation const& _location,
|
SourceLocation const& _location,
|
||||||
ASTPointer<ASTString> const& _name,
|
ASTPointer<ASTString> const& _name,
|
||||||
ASTPointer<ASTString> const& _documentation,
|
ASTPointer<StructuredDocumentation> const& _documentation,
|
||||||
std::vector<ASTPointer<InheritanceSpecifier>> const& _baseContracts,
|
std::vector<ASTPointer<InheritanceSpecifier>> const& _baseContracts,
|
||||||
std::vector<ASTPointer<ASTNode>> const& _subNodes,
|
std::vector<ASTPointer<ASTNode>> const& _subNodes,
|
||||||
ContractKind _contractKind = ContractKind::Contract,
|
ContractKind _contractKind = ContractKind::Contract,
|
||||||
bool _abstract = false
|
bool _abstract = false
|
||||||
):
|
):
|
||||||
Declaration(_id, _location, _name),
|
Declaration(_id, _location, _name),
|
||||||
Documented(_documentation),
|
StructurallyDocumented(_documentation),
|
||||||
m_baseContracts(_baseContracts),
|
m_baseContracts(_baseContracts),
|
||||||
m_subNodes(_subNodes),
|
m_subNodes(_subNodes),
|
||||||
m_contractKind(_contractKind),
|
m_contractKind(_contractKind),
|
||||||
@ -681,7 +723,7 @@ protected:
|
|||||||
std::vector<ASTPointer<UserDefinedTypeName>> m_overrides;
|
std::vector<ASTPointer<UserDefinedTypeName>> m_overrides;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FunctionDefinition: public CallableDeclaration, public Documented, public ImplementationOptional
|
class FunctionDefinition: public CallableDeclaration, public StructurallyDocumented, public ImplementationOptional
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FunctionDefinition(
|
FunctionDefinition(
|
||||||
@ -693,14 +735,14 @@ public:
|
|||||||
Token _kind,
|
Token _kind,
|
||||||
bool _isVirtual,
|
bool _isVirtual,
|
||||||
ASTPointer<OverrideSpecifier> const& _overrides,
|
ASTPointer<OverrideSpecifier> const& _overrides,
|
||||||
ASTPointer<ASTString> const& _documentation,
|
ASTPointer<StructuredDocumentation> const& _documentation,
|
||||||
ASTPointer<ParameterList> const& _parameters,
|
ASTPointer<ParameterList> const& _parameters,
|
||||||
std::vector<ASTPointer<ModifierInvocation>> const& _modifiers,
|
std::vector<ASTPointer<ModifierInvocation>> const& _modifiers,
|
||||||
ASTPointer<ParameterList> const& _returnParameters,
|
ASTPointer<ParameterList> const& _returnParameters,
|
||||||
ASTPointer<Block> const& _body
|
ASTPointer<Block> const& _body
|
||||||
):
|
):
|
||||||
CallableDeclaration(_id, _location, _name, _visibility, _parameters, _isVirtual, _overrides, _returnParameters),
|
CallableDeclaration(_id, _location, _name, _visibility, _parameters, _isVirtual, _overrides, _returnParameters),
|
||||||
Documented(_documentation),
|
StructurallyDocumented(_documentation),
|
||||||
ImplementationOptional(_body != nullptr),
|
ImplementationOptional(_body != nullptr),
|
||||||
m_stateMutability(_stateMutability),
|
m_stateMutability(_stateMutability),
|
||||||
m_kind(_kind),
|
m_kind(_kind),
|
||||||
@ -870,21 +912,21 @@ private:
|
|||||||
/**
|
/**
|
||||||
* Definition of a function modifier.
|
* Definition of a function modifier.
|
||||||
*/
|
*/
|
||||||
class ModifierDefinition: public CallableDeclaration, public Documented
|
class ModifierDefinition: public CallableDeclaration, public StructurallyDocumented
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ModifierDefinition(
|
ModifierDefinition(
|
||||||
int64_t _id,
|
int64_t _id,
|
||||||
SourceLocation const& _location,
|
SourceLocation const& _location,
|
||||||
ASTPointer<ASTString> const& _name,
|
ASTPointer<ASTString> const& _name,
|
||||||
ASTPointer<ASTString> const& _documentation,
|
ASTPointer<StructuredDocumentation> const& _documentation,
|
||||||
ASTPointer<ParameterList> const& _parameters,
|
ASTPointer<ParameterList> const& _parameters,
|
||||||
bool _isVirtual,
|
bool _isVirtual,
|
||||||
ASTPointer<OverrideSpecifier> const& _overrides,
|
ASTPointer<OverrideSpecifier> const& _overrides,
|
||||||
ASTPointer<Block> const& _body
|
ASTPointer<Block> const& _body
|
||||||
):
|
):
|
||||||
CallableDeclaration(_id, _location, _name, Visibility::Internal, _parameters, _isVirtual, _overrides),
|
CallableDeclaration(_id, _location, _name, Visibility::Internal, _parameters, _isVirtual, _overrides),
|
||||||
Documented(_documentation),
|
StructurallyDocumented(_documentation),
|
||||||
m_body(_body)
|
m_body(_body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -935,19 +977,19 @@ private:
|
|||||||
/**
|
/**
|
||||||
* Definition of a (loggable) event.
|
* Definition of a (loggable) event.
|
||||||
*/
|
*/
|
||||||
class EventDefinition: public CallableDeclaration, public Documented
|
class EventDefinition: public CallableDeclaration, public StructurallyDocumented
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EventDefinition(
|
EventDefinition(
|
||||||
int64_t _id,
|
int64_t _id,
|
||||||
SourceLocation const& _location,
|
SourceLocation const& _location,
|
||||||
ASTPointer<ASTString> const& _name,
|
ASTPointer<ASTString> const& _name,
|
||||||
ASTPointer<ASTString> const& _documentation,
|
ASTPointer<StructuredDocumentation> const& _documentation,
|
||||||
ASTPointer<ParameterList> const& _parameters,
|
ASTPointer<ParameterList> const& _parameters,
|
||||||
bool _anonymous = false
|
bool _anonymous = false
|
||||||
):
|
):
|
||||||
CallableDeclaration(_id, _location, _name, Visibility::Default, _parameters),
|
CallableDeclaration(_id, _location, _name, Visibility::Default, _parameters),
|
||||||
Documented(_documentation),
|
StructurallyDocumented(_documentation),
|
||||||
m_anonymous(_anonymous)
|
m_anonymous(_anonymous)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -56,9 +56,9 @@ struct DocTag
|
|||||||
std::string paramName; ///< Only used for @param, stores the parameter name.
|
std::string paramName; ///< Only used for @param, stores the parameter name.
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DocumentedAnnotation
|
struct StructurallyDocumentedAnnotation
|
||||||
{
|
{
|
||||||
virtual ~DocumentedAnnotation() = default;
|
virtual ~StructurallyDocumentedAnnotation() = default;
|
||||||
/// Mapping docstring tag name -> content.
|
/// Mapping docstring tag name -> content.
|
||||||
std::multimap<std::string, DocTag> docTags;
|
std::multimap<std::string, DocTag> docTags;
|
||||||
};
|
};
|
||||||
@ -101,7 +101,7 @@ struct TypeDeclarationAnnotation: DeclarationAnnotation
|
|||||||
std::string canonicalName;
|
std::string canonicalName;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ContractDefinitionAnnotation: TypeDeclarationAnnotation, DocumentedAnnotation
|
struct ContractDefinitionAnnotation: TypeDeclarationAnnotation, StructurallyDocumentedAnnotation
|
||||||
{
|
{
|
||||||
/// List of functions without a body. Can also contain functions from base classes.
|
/// List of functions without a body. Can also contain functions from base classes.
|
||||||
std::vector<FunctionDefinition const*> unimplementedFunctions;
|
std::vector<FunctionDefinition const*> unimplementedFunctions;
|
||||||
@ -122,15 +122,15 @@ struct CallableDeclarationAnnotation: DeclarationAnnotation
|
|||||||
std::set<CallableDeclaration const*> baseFunctions;
|
std::set<CallableDeclaration const*> baseFunctions;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FunctionDefinitionAnnotation: CallableDeclarationAnnotation, DocumentedAnnotation
|
struct FunctionDefinitionAnnotation: CallableDeclarationAnnotation, StructurallyDocumentedAnnotation
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EventDefinitionAnnotation: CallableDeclarationAnnotation, DocumentedAnnotation
|
struct EventDefinitionAnnotation: CallableDeclarationAnnotation, StructurallyDocumentedAnnotation
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ModifierDefinitionAnnotation: CallableDeclarationAnnotation, DocumentedAnnotation
|
struct ModifierDefinitionAnnotation: CallableDeclarationAnnotation, StructurallyDocumentedAnnotation
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ struct VariableDeclarationAnnotation: DeclarationAnnotation
|
|||||||
std::set<CallableDeclaration const*> baseFunctions;
|
std::set<CallableDeclaration const*> baseFunctions;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StatementAnnotation: ASTAnnotation, DocumentedAnnotation
|
struct StatementAnnotation: ASTAnnotation
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,6 +93,7 @@ class PrimaryExpression;
|
|||||||
class Identifier;
|
class Identifier;
|
||||||
class ElementaryTypeNameExpression;
|
class ElementaryTypeNameExpression;
|
||||||
class Literal;
|
class Literal;
|
||||||
|
class StructuredDocumentation;
|
||||||
|
|
||||||
class VariableScope;
|
class VariableScope;
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ bool ASTJsonConverter::visit(ContractDefinition const& _node)
|
|||||||
{
|
{
|
||||||
setJsonNode(_node, "ContractDefinition", {
|
setJsonNode(_node, "ContractDefinition", {
|
||||||
make_pair("name", _node.name()),
|
make_pair("name", _node.name()),
|
||||||
make_pair("documentation", _node.documentation() ? Json::Value(*_node.documentation()) : Json::nullValue),
|
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||||
make_pair("contractKind", contractKind(_node.contractKind())),
|
make_pair("contractKind", contractKind(_node.contractKind())),
|
||||||
make_pair("abstract", _node.abstract()),
|
make_pair("abstract", _node.abstract()),
|
||||||
make_pair("fullyImplemented", _node.annotation().unimplementedFunctions.empty()),
|
make_pair("fullyImplemented", _node.annotation().unimplementedFunctions.empty()),
|
||||||
@ -349,7 +349,7 @@ bool ASTJsonConverter::visit(FunctionDefinition 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("documentation", _node.documentation() ? Json::Value(*_node.documentation()) : Json::nullValue),
|
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||||
make_pair("kind", TokenTraits::toString(_node.kind())),
|
make_pair("kind", TokenTraits::toString(_node.kind())),
|
||||||
make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
|
make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
|
||||||
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
||||||
@ -400,7 +400,7 @@ bool ASTJsonConverter::visit(ModifierDefinition 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("documentation", _node.documentation() ? Json::Value(*_node.documentation()) : Json::nullValue),
|
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||||
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
||||||
make_pair("parameters", toJson(_node.parameterList())),
|
make_pair("parameters", toJson(_node.parameterList())),
|
||||||
make_pair("virtual", _node.markedVirtual()),
|
make_pair("virtual", _node.markedVirtual()),
|
||||||
@ -427,7 +427,7 @@ bool ASTJsonConverter::visit(EventDefinition const& _node)
|
|||||||
m_inEvent = true;
|
m_inEvent = true;
|
||||||
setJsonNode(_node, "EventDefinition", {
|
setJsonNode(_node, "EventDefinition", {
|
||||||
make_pair("name", _node.name()),
|
make_pair("name", _node.name()),
|
||||||
make_pair("documentation", _node.documentation() ? Json::Value(*_node.documentation()) : Json::nullValue),
|
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||||
make_pair("parameters", toJson(_node.parameterList())),
|
make_pair("parameters", toJson(_node.parameterList())),
|
||||||
make_pair("anonymous", _node.isAnonymous())
|
make_pair("anonymous", _node.isAnonymous())
|
||||||
});
|
});
|
||||||
@ -833,6 +833,17 @@ bool ASTJsonConverter::visit(Literal const& _node)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ASTJsonConverter::visit(StructuredDocumentation const& _node)
|
||||||
|
{
|
||||||
|
Json::Value text{*_node.text()};
|
||||||
|
std::vector<pair<string, Json::Value>> attributes = {
|
||||||
|
make_pair("text", text)
|
||||||
|
};
|
||||||
|
setJsonNode(_node, "StructuredDocumentation", std::move(attributes));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ASTJsonConverter::endVisit(EventDefinition const&)
|
void ASTJsonConverter::endVisit(EventDefinition const&)
|
||||||
{
|
{
|
||||||
|
@ -119,6 +119,7 @@ public:
|
|||||||
bool visit(Identifier const& _node) override;
|
bool visit(Identifier const& _node) override;
|
||||||
bool visit(ElementaryTypeNameExpression const& _node) override;
|
bool visit(ElementaryTypeNameExpression const& _node) override;
|
||||||
bool visit(Literal const& _node) override;
|
bool visit(Literal const& _node) override;
|
||||||
|
bool visit(StructuredDocumentation const& _node) override;
|
||||||
|
|
||||||
void endVisit(EventDefinition const&) override;
|
void endVisit(EventDefinition const&) override;
|
||||||
|
|
||||||
|
@ -208,6 +208,8 @@ ASTPointer<ASTNode> ASTJsonImporter::convertJsonToASTNode(Json::Value const& _js
|
|||||||
return createElementaryTypeNameExpression(_json);
|
return createElementaryTypeNameExpression(_json);
|
||||||
if (nodeType == "Literal")
|
if (nodeType == "Literal")
|
||||||
return createLiteral(_json);
|
return createLiteral(_json);
|
||||||
|
if (nodeType == "StructuredDocumentation")
|
||||||
|
return createDocumentation(_json);
|
||||||
else
|
else
|
||||||
astAssert(false, "Unknown type of ASTNode: " + nodeType);
|
astAssert(false, "Unknown type of ASTNode: " + nodeType);
|
||||||
}
|
}
|
||||||
@ -283,7 +285,7 @@ ASTPointer<ContractDefinition> ASTJsonImporter::createContractDefinition(Json::V
|
|||||||
return createASTNode<ContractDefinition>(
|
return createASTNode<ContractDefinition>(
|
||||||
_node,
|
_node,
|
||||||
make_shared<ASTString>(_node["name"].asString()),
|
make_shared<ASTString>(_node["name"].asString()),
|
||||||
nullOrASTString(_node, "documentation"),
|
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")),
|
||||||
baseContracts,
|
baseContracts,
|
||||||
subNodes,
|
subNodes,
|
||||||
contractKind(_node),
|
contractKind(_node),
|
||||||
@ -397,7 +399,7 @@ ASTPointer<FunctionDefinition> ASTJsonImporter::createFunctionDefinition(Json::V
|
|||||||
kind,
|
kind,
|
||||||
memberAsBool(_node, "virtual"),
|
memberAsBool(_node, "virtual"),
|
||||||
_node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
|
_node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
|
||||||
nullOrASTString(_node, "documentation"),
|
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")),
|
||||||
createParameterList(member(_node, "parameters")),
|
createParameterList(member(_node, "parameters")),
|
||||||
modifiers,
|
modifiers,
|
||||||
createParameterList(member(_node, "returnParameters")),
|
createParameterList(member(_node, "returnParameters")),
|
||||||
@ -428,7 +430,7 @@ ASTPointer<ModifierDefinition> ASTJsonImporter::createModifierDefinition(Json::V
|
|||||||
return createASTNode<ModifierDefinition>(
|
return createASTNode<ModifierDefinition>(
|
||||||
_node,
|
_node,
|
||||||
memberAsASTString(_node, "name"),
|
memberAsASTString(_node, "name"),
|
||||||
nullOrASTString(_node,"documentation"),
|
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")),
|
||||||
createParameterList(member(_node, "parameters")),
|
createParameterList(member(_node, "parameters")),
|
||||||
memberAsBool(_node, "virtual"),
|
memberAsBool(_node, "virtual"),
|
||||||
_node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
|
_node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
|
||||||
@ -453,7 +455,7 @@ ASTPointer<EventDefinition> ASTJsonImporter::createEventDefinition(Json::Value c
|
|||||||
return createASTNode<EventDefinition>(
|
return createASTNode<EventDefinition>(
|
||||||
_node,
|
_node,
|
||||||
memberAsASTString(_node, "name"),
|
memberAsASTString(_node, "name"),
|
||||||
nullOrASTString(_node, "documentation"),
|
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")),
|
||||||
createParameterList(member(_node, "parameters")),
|
createParameterList(member(_node, "parameters")),
|
||||||
memberAsBool(_node, "anonymous")
|
memberAsBool(_node, "anonymous")
|
||||||
);
|
);
|
||||||
@ -842,6 +844,18 @@ ASTPointer<ASTNode> ASTJsonImporter::createLiteral(Json::Value const& _node)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASTPointer<StructuredDocumentation> ASTJsonImporter::createDocumentation(Json::Value const& _node)
|
||||||
|
{
|
||||||
|
static string const textString = "text";
|
||||||
|
|
||||||
|
astAssert(member(_node, textString).isString(), "'text' must be a string");
|
||||||
|
|
||||||
|
return createASTNode<StructuredDocumentation>(
|
||||||
|
_node,
|
||||||
|
make_shared<ASTString>(_node[textString].asString())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// ===== helper functions ==========
|
// ===== helper functions ==========
|
||||||
|
|
||||||
Json::Value ASTJsonImporter::member(Json::Value const& _node, string const& _name)
|
Json::Value ASTJsonImporter::member(Json::Value const& _node, string const& _name)
|
||||||
|
@ -119,6 +119,7 @@ private:
|
|||||||
ASTPointer<Identifier> createIdentifier(Json::Value const& _node);
|
ASTPointer<Identifier> createIdentifier(Json::Value const& _node);
|
||||||
ASTPointer<ElementaryTypeNameExpression> createElementaryTypeNameExpression(Json::Value const& _node);
|
ASTPointer<ElementaryTypeNameExpression> createElementaryTypeNameExpression(Json::Value const& _node);
|
||||||
ASTPointer<ASTNode> createLiteral(Json::Value const& _node);
|
ASTPointer<ASTNode> createLiteral(Json::Value const& _node);
|
||||||
|
ASTPointer<StructuredDocumentation> createDocumentation(Json::Value const& _node);
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
// =============== general helper functions ===================
|
// =============== general helper functions ===================
|
||||||
|
@ -92,6 +92,7 @@ public:
|
|||||||
virtual bool visit(Identifier& _node) { return visitNode(_node); }
|
virtual bool visit(Identifier& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(ElementaryTypeNameExpression& _node) { return visitNode(_node); }
|
virtual bool visit(ElementaryTypeNameExpression& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(Literal& _node) { return visitNode(_node); }
|
virtual bool visit(Literal& _node) { return visitNode(_node); }
|
||||||
|
virtual bool visit(StructuredDocumentation& _node) { return visitNode(_node); }
|
||||||
|
|
||||||
virtual void endVisit(SourceUnit& _node) { endVisitNode(_node); }
|
virtual void endVisit(SourceUnit& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(PragmaDirective& _node) { endVisitNode(_node); }
|
virtual void endVisit(PragmaDirective& _node) { endVisitNode(_node); }
|
||||||
@ -143,6 +144,7 @@ public:
|
|||||||
virtual void endVisit(Identifier& _node) { endVisitNode(_node); }
|
virtual void endVisit(Identifier& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(ElementaryTypeNameExpression& _node) { endVisitNode(_node); }
|
virtual void endVisit(ElementaryTypeNameExpression& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(Literal& _node) { endVisitNode(_node); }
|
virtual void endVisit(Literal& _node) { endVisitNode(_node); }
|
||||||
|
virtual void endVisit(StructuredDocumentation& _node) { endVisitNode(_node); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Generic function called by default for each node, to be overridden by derived classes
|
/// Generic function called by default for each node, to be overridden by derived classes
|
||||||
@ -207,6 +209,7 @@ public:
|
|||||||
virtual bool visit(Identifier const& _node) { return visitNode(_node); }
|
virtual bool visit(Identifier const& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(ElementaryTypeNameExpression const& _node) { return visitNode(_node); }
|
virtual bool visit(ElementaryTypeNameExpression const& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(Literal const& _node) { return visitNode(_node); }
|
virtual bool visit(Literal const& _node) { return visitNode(_node); }
|
||||||
|
virtual bool visit(StructuredDocumentation const& _node) { return visitNode(_node); }
|
||||||
|
|
||||||
virtual void endVisit(SourceUnit const& _node) { endVisitNode(_node); }
|
virtual void endVisit(SourceUnit const& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(PragmaDirective const& _node) { endVisitNode(_node); }
|
virtual void endVisit(PragmaDirective const& _node) { endVisitNode(_node); }
|
||||||
@ -258,6 +261,7 @@ public:
|
|||||||
virtual void endVisit(Identifier const& _node) { endVisitNode(_node); }
|
virtual void endVisit(Identifier const& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(ElementaryTypeNameExpression const& _node) { endVisitNode(_node); }
|
virtual void endVisit(ElementaryTypeNameExpression const& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(Literal const& _node) { endVisitNode(_node); }
|
virtual void endVisit(Literal const& _node) { endVisitNode(_node); }
|
||||||
|
virtual void endVisit(StructuredDocumentation const& _node) { endVisitNode(_node); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Generic function called by default for each node, to be overridden by derived classes
|
/// Generic function called by default for each node, to be overridden by derived classes
|
||||||
|
@ -67,10 +67,24 @@ void ImportDirective::accept(ASTConstVisitor& _visitor) const
|
|||||||
_visitor.endVisit(*this);
|
_visitor.endVisit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StructuredDocumentation::accept(ASTVisitor& _visitor)
|
||||||
|
{
|
||||||
|
_visitor.visit(*this);
|
||||||
|
_visitor.endVisit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StructuredDocumentation::accept(ASTConstVisitor& _visitor) const
|
||||||
|
{
|
||||||
|
_visitor.visit(*this);
|
||||||
|
_visitor.endVisit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
void ContractDefinition::accept(ASTVisitor& _visitor)
|
void ContractDefinition::accept(ASTVisitor& _visitor)
|
||||||
{
|
{
|
||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
{
|
{
|
||||||
|
if (m_documentation)
|
||||||
|
m_documentation->accept(_visitor);
|
||||||
listAccept(m_baseContracts, _visitor);
|
listAccept(m_baseContracts, _visitor);
|
||||||
listAccept(m_subNodes, _visitor);
|
listAccept(m_subNodes, _visitor);
|
||||||
}
|
}
|
||||||
@ -81,6 +95,8 @@ void ContractDefinition::accept(ASTConstVisitor& _visitor) const
|
|||||||
{
|
{
|
||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
{
|
{
|
||||||
|
if (m_documentation)
|
||||||
|
m_documentation->accept(_visitor);
|
||||||
listAccept(m_baseContracts, _visitor);
|
listAccept(m_baseContracts, _visitor);
|
||||||
listAccept(m_subNodes, _visitor);
|
listAccept(m_subNodes, _visitor);
|
||||||
}
|
}
|
||||||
@ -203,6 +219,8 @@ void FunctionDefinition::accept(ASTVisitor& _visitor)
|
|||||||
{
|
{
|
||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
{
|
{
|
||||||
|
if (m_documentation)
|
||||||
|
m_documentation->accept(_visitor);
|
||||||
if (m_overrides)
|
if (m_overrides)
|
||||||
m_overrides->accept(_visitor);
|
m_overrides->accept(_visitor);
|
||||||
m_parameters->accept(_visitor);
|
m_parameters->accept(_visitor);
|
||||||
@ -219,6 +237,8 @@ void FunctionDefinition::accept(ASTConstVisitor& _visitor) const
|
|||||||
{
|
{
|
||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
{
|
{
|
||||||
|
if (m_documentation)
|
||||||
|
m_documentation->accept(_visitor);
|
||||||
if (m_overrides)
|
if (m_overrides)
|
||||||
m_overrides->accept(_visitor);
|
m_overrides->accept(_visitor);
|
||||||
m_parameters->accept(_visitor);
|
m_parameters->accept(_visitor);
|
||||||
@ -263,6 +283,8 @@ void ModifierDefinition::accept(ASTVisitor& _visitor)
|
|||||||
{
|
{
|
||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
{
|
{
|
||||||
|
if (m_documentation)
|
||||||
|
m_documentation->accept(_visitor);
|
||||||
m_parameters->accept(_visitor);
|
m_parameters->accept(_visitor);
|
||||||
if (m_overrides)
|
if (m_overrides)
|
||||||
m_overrides->accept(_visitor);
|
m_overrides->accept(_visitor);
|
||||||
@ -275,6 +297,8 @@ void ModifierDefinition::accept(ASTConstVisitor& _visitor) const
|
|||||||
{
|
{
|
||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
{
|
{
|
||||||
|
if (m_documentation)
|
||||||
|
m_documentation->accept(_visitor);
|
||||||
m_parameters->accept(_visitor);
|
m_parameters->accept(_visitor);
|
||||||
if (m_overrides)
|
if (m_overrides)
|
||||||
m_overrides->accept(_visitor);
|
m_overrides->accept(_visitor);
|
||||||
@ -308,14 +332,22 @@ void ModifierInvocation::accept(ASTConstVisitor& _visitor) const
|
|||||||
void EventDefinition::accept(ASTVisitor& _visitor)
|
void EventDefinition::accept(ASTVisitor& _visitor)
|
||||||
{
|
{
|
||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
|
{
|
||||||
|
if (m_documentation)
|
||||||
|
m_documentation->accept(_visitor);
|
||||||
m_parameters->accept(_visitor);
|
m_parameters->accept(_visitor);
|
||||||
|
}
|
||||||
_visitor.endVisit(*this);
|
_visitor.endVisit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventDefinition::accept(ASTConstVisitor& _visitor) const
|
void EventDefinition::accept(ASTConstVisitor& _visitor) const
|
||||||
{
|
{
|
||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
|
{
|
||||||
|
if (m_documentation)
|
||||||
|
m_documentation->accept(_visitor);
|
||||||
m_parameters->accept(_visitor);
|
m_parameters->accept(_visitor);
|
||||||
|
}
|
||||||
_visitor.endVisit(*this);
|
_visitor.endVisit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3323,13 +3323,13 @@ Type const* FunctionType::selfType() const
|
|||||||
return m_parameterTypes.at(0);
|
return m_parameterTypes.at(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<ASTString> FunctionType::documentation() const
|
ASTPointer<StructuredDocumentation> FunctionType::documentation() const
|
||||||
{
|
{
|
||||||
auto function = dynamic_cast<Documented const*>(m_declaration);
|
auto function = dynamic_cast<StructurallyDocumented const*>(m_declaration);
|
||||||
if (function)
|
if (function)
|
||||||
return function->documentation();
|
return function->documentation();
|
||||||
|
|
||||||
return ASTPointer<ASTString>();
|
return ASTPointer<StructuredDocumentation>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FunctionType::padArguments() const
|
bool FunctionType::padArguments() const
|
||||||
|
@ -1208,9 +1208,9 @@ public:
|
|||||||
/// Currently, this will only return true for internal functions like keccak and ecrecover.
|
/// Currently, this will only return true for internal functions like keccak and ecrecover.
|
||||||
bool isPure() const;
|
bool isPure() const;
|
||||||
bool isPayable() const { return m_stateMutability == StateMutability::Payable; }
|
bool isPayable() const { return m_stateMutability == StateMutability::Payable; }
|
||||||
/// @return A shared pointer of an ASTString.
|
/// @return A shared pointer of StructuredDocumentation.
|
||||||
/// Can contain a nullptr in which case indicates absence of documentation
|
/// Can contain a nullptr in which case indicates absence of documentation.
|
||||||
ASTPointer<ASTString> documentation() const;
|
ASTPointer<StructuredDocumentation> documentation() const;
|
||||||
|
|
||||||
/// true iff arguments are to be padded to multiples of 32 bytes for external calls
|
/// true iff arguments are to be padded to multiples of 32 bytes for external calls
|
||||||
/// The only functions that do not pad are hash functions, the low-level call functions
|
/// The only functions that do not pad are hash functions, the low-level call functions
|
||||||
|
@ -135,6 +135,19 @@ void Parser::parsePragmaVersion(SourceLocation const& _location, vector<Token> c
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASTPointer<StructuredDocumentation> Parser::parseStructuredDocumentation()
|
||||||
|
{
|
||||||
|
if (m_scanner->currentCommentLiteral() != "")
|
||||||
|
{
|
||||||
|
ASTNodeFactory nodeFactory{*this};
|
||||||
|
nodeFactory.setLocation(m_scanner->currentCommentLocation());
|
||||||
|
return nodeFactory.createNode<StructuredDocumentation>(
|
||||||
|
make_shared<ASTString>(m_scanner->currentCommentLiteral())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
ASTPointer<PragmaDirective> Parser::parsePragmaDirective()
|
ASTPointer<PragmaDirective> Parser::parsePragmaDirective()
|
||||||
{
|
{
|
||||||
RecursionGuard recursionGuard(*this);
|
RecursionGuard recursionGuard(*this);
|
||||||
@ -276,14 +289,13 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
|
|||||||
RecursionGuard recursionGuard(*this);
|
RecursionGuard recursionGuard(*this);
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
ASTPointer<ASTString> name = nullptr;
|
ASTPointer<ASTString> name = nullptr;
|
||||||
ASTPointer<ASTString> docString;
|
ASTPointer<StructuredDocumentation> documentation;
|
||||||
vector<ASTPointer<InheritanceSpecifier>> baseContracts;
|
vector<ASTPointer<InheritanceSpecifier>> baseContracts;
|
||||||
vector<ASTPointer<ASTNode>> subNodes;
|
vector<ASTPointer<ASTNode>> subNodes;
|
||||||
std::pair<ContractKind, bool> contractKind{};
|
std::pair<ContractKind, bool> contractKind{};
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (m_scanner->currentCommentLiteral() != "")
|
documentation = parseStructuredDocumentation();
|
||||||
docString = make_shared<ASTString>(m_scanner->currentCommentLiteral());
|
|
||||||
contractKind = parseContractKind();
|
contractKind = parseContractKind();
|
||||||
name = expectIdentifierToken();
|
name = expectIdentifierToken();
|
||||||
if (m_scanner->currentToken() == Token::Is)
|
if (m_scanner->currentToken() == Token::Is)
|
||||||
@ -350,7 +362,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
|
|||||||
expectToken(Token::RBrace);
|
expectToken(Token::RBrace);
|
||||||
return nodeFactory.createNode<ContractDefinition>(
|
return nodeFactory.createNode<ContractDefinition>(
|
||||||
name,
|
name,
|
||||||
docString,
|
documentation,
|
||||||
baseContracts,
|
baseContracts,
|
||||||
subNodes,
|
subNodes,
|
||||||
contractKind.first,
|
contractKind.first,
|
||||||
@ -538,9 +550,7 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinition()
|
|||||||
{
|
{
|
||||||
RecursionGuard recursionGuard(*this);
|
RecursionGuard recursionGuard(*this);
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
ASTPointer<ASTString> docstring;
|
ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
|
||||||
if (m_scanner->currentCommentLiteral() != "")
|
|
||||||
docstring = make_shared<ASTString>(m_scanner->currentCommentLiteral());
|
|
||||||
|
|
||||||
Token kind = m_scanner->currentToken();
|
Token kind = m_scanner->currentToken();
|
||||||
ASTPointer<ASTString> name;
|
ASTPointer<ASTString> name;
|
||||||
@ -598,7 +608,7 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinition()
|
|||||||
kind,
|
kind,
|
||||||
header.isVirtual,
|
header.isVirtual,
|
||||||
header.overrides,
|
header.overrides,
|
||||||
docstring,
|
documentation,
|
||||||
header.parameters,
|
header.parameters,
|
||||||
header.modifiers,
|
header.modifiers,
|
||||||
header.returnParameters,
|
header.returnParameters,
|
||||||
@ -792,9 +802,7 @@ ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
|
|||||||
m_insideModifier = true;
|
m_insideModifier = true;
|
||||||
|
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
ASTPointer<ASTString> docstring;
|
ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
|
||||||
if (m_scanner->currentCommentLiteral() != "")
|
|
||||||
docstring = make_shared<ASTString>(m_scanner->currentCommentLiteral());
|
|
||||||
|
|
||||||
expectToken(Token::Modifier);
|
expectToken(Token::Modifier);
|
||||||
ASTPointer<ASTString> name(expectIdentifierToken());
|
ASTPointer<ASTString> name(expectIdentifierToken());
|
||||||
@ -835,16 +843,14 @@ ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
|
|||||||
|
|
||||||
ASTPointer<Block> block = parseBlock();
|
ASTPointer<Block> block = parseBlock();
|
||||||
nodeFactory.setEndPositionFromNode(block);
|
nodeFactory.setEndPositionFromNode(block);
|
||||||
return nodeFactory.createNode<ModifierDefinition>(name, docstring, parameters, isVirtual, overrides, block);
|
return nodeFactory.createNode<ModifierDefinition>(name, documentation, parameters, isVirtual, overrides, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<EventDefinition> Parser::parseEventDefinition()
|
ASTPointer<EventDefinition> Parser::parseEventDefinition()
|
||||||
{
|
{
|
||||||
RecursionGuard recursionGuard(*this);
|
RecursionGuard recursionGuard(*this);
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
ASTPointer<ASTString> docstring;
|
ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
|
||||||
if (m_scanner->currentCommentLiteral() != "")
|
|
||||||
docstring = make_shared<ASTString>(m_scanner->currentCommentLiteral());
|
|
||||||
|
|
||||||
expectToken(Token::Event);
|
expectToken(Token::Event);
|
||||||
ASTPointer<ASTString> name(expectIdentifierToken());
|
ASTPointer<ASTString> name(expectIdentifierToken());
|
||||||
@ -861,7 +867,7 @@ ASTPointer<EventDefinition> Parser::parseEventDefinition()
|
|||||||
}
|
}
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
expectToken(Token::Semicolon);
|
expectToken(Token::Semicolon);
|
||||||
return nodeFactory.createNode<EventDefinition>(name, docstring, parameters, anonymous);
|
return nodeFactory.createNode<EventDefinition>(name, documentation, parameters, anonymous);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<UsingForDirective> Parser::parseUsingDirective()
|
ASTPointer<UsingForDirective> Parser::parseUsingDirective()
|
||||||
@ -1355,7 +1361,7 @@ ASTPointer<EmitStatement> Parser::parseEmitStatement(ASTPointer<ASTString> const
|
|||||||
if (m_scanner->currentToken() != Token::Period)
|
if (m_scanner->currentToken() != Token::Period)
|
||||||
break;
|
break;
|
||||||
m_scanner->next();
|
m_scanner->next();
|
||||||
};
|
}
|
||||||
|
|
||||||
auto eventName = expressionFromIndexAccessStructure(iap);
|
auto eventName = expressionFromIndexAccessStructure(iap);
|
||||||
expectToken(Token::LParen);
|
expectToken(Token::LParen);
|
||||||
|
@ -80,6 +80,7 @@ private:
|
|||||||
///@{
|
///@{
|
||||||
///@name Parsing functions for the AST nodes
|
///@name Parsing functions for the AST nodes
|
||||||
void parsePragmaVersion(langutil::SourceLocation const& _location, std::vector<Token> const& _tokens, std::vector<std::string> const& _literals);
|
void parsePragmaVersion(langutil::SourceLocation const& _location, std::vector<Token> const& _tokens, std::vector<std::string> const& _literals);
|
||||||
|
ASTPointer<StructuredDocumentation> parseStructuredDocumentation();
|
||||||
ASTPointer<PragmaDirective> parsePragmaDirective();
|
ASTPointer<PragmaDirective> parsePragmaDirective();
|
||||||
ASTPointer<ImportDirective> parseImportDirective();
|
ASTPointer<ImportDirective> parseImportDirective();
|
||||||
/// @returns an std::pair<ContractKind, bool>, where
|
/// @returns an std::pair<ContractKind, bool>, where
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
{
|
{
|
||||||
"C":
|
"C":
|
||||||
[
|
[
|
||||||
1
|
2
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"id": 2,
|
"id": 3,
|
||||||
"nodeType": "SourceUnit",
|
"nodeType": "SourceUnit",
|
||||||
"nodes":
|
"nodes":
|
||||||
[
|
[
|
||||||
@ -16,17 +16,23 @@
|
|||||||
"baseContracts": [],
|
"baseContracts": [],
|
||||||
"contractDependencies": [],
|
"contractDependencies": [],
|
||||||
"contractKind": "contract",
|
"contractKind": "contract",
|
||||||
"documentation": "This contract is empty",
|
"documentation":
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"nodeType": "StructuredDocumentation",
|
||||||
|
"src": "0:27:1",
|
||||||
|
"text": "This contract is empty"
|
||||||
|
},
|
||||||
"fullyImplemented": true,
|
"fullyImplemented": true,
|
||||||
"id": 1,
|
"id": 2,
|
||||||
"linearizedBaseContracts":
|
"linearizedBaseContracts":
|
||||||
[
|
[
|
||||||
1
|
2
|
||||||
],
|
],
|
||||||
"name": "C",
|
"name": "C",
|
||||||
"nodeType": "ContractDefinition",
|
"nodeType": "ContractDefinition",
|
||||||
"nodes": [],
|
"nodes": [],
|
||||||
"scope": 2,
|
"scope": 3,
|
||||||
"src": "28:13:1"
|
"src": "28:13:1"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -38,10 +44,10 @@
|
|||||||
{
|
{
|
||||||
"C":
|
"C":
|
||||||
[
|
[
|
||||||
3
|
5
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"id": 4,
|
"id": 6,
|
||||||
"nodeType": "SourceUnit",
|
"nodeType": "SourceUnit",
|
||||||
"nodes":
|
"nodes":
|
||||||
[
|
[
|
||||||
@ -50,17 +56,23 @@
|
|||||||
"baseContracts": [],
|
"baseContracts": [],
|
||||||
"contractDependencies": [],
|
"contractDependencies": [],
|
||||||
"contractKind": "contract",
|
"contractKind": "contract",
|
||||||
"documentation": "This contract is empty\nand has a line-breaking comment.",
|
"documentation":
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"nodeType": "StructuredDocumentation",
|
||||||
|
"src": "0:61:2",
|
||||||
|
"text": "This contract is empty\nand has a line-breaking comment."
|
||||||
|
},
|
||||||
"fullyImplemented": true,
|
"fullyImplemented": true,
|
||||||
"id": 3,
|
"id": 5,
|
||||||
"linearizedBaseContracts":
|
"linearizedBaseContracts":
|
||||||
[
|
[
|
||||||
3
|
5
|
||||||
],
|
],
|
||||||
"name": "C",
|
"name": "C",
|
||||||
"nodeType": "ContractDefinition",
|
"nodeType": "ContractDefinition",
|
||||||
"nodes": [],
|
"nodes": [],
|
||||||
"scope": 4,
|
"scope": 6,
|
||||||
"src": "62:13:2"
|
"src": "62:13:2"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -72,10 +84,10 @@
|
|||||||
{
|
{
|
||||||
"C":
|
"C":
|
||||||
[
|
[
|
||||||
15
|
20
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"id": 16,
|
"id": 21,
|
||||||
"nodeType": "SourceUnit",
|
"nodeType": "SourceUnit",
|
||||||
"nodes":
|
"nodes":
|
||||||
[
|
[
|
||||||
@ -86,10 +98,10 @@
|
|||||||
"contractKind": "contract",
|
"contractKind": "contract",
|
||||||
"documentation": null,
|
"documentation": null,
|
||||||
"fullyImplemented": true,
|
"fullyImplemented": true,
|
||||||
"id": 15,
|
"id": 20,
|
||||||
"linearizedBaseContracts":
|
"linearizedBaseContracts":
|
||||||
[
|
[
|
||||||
15
|
20
|
||||||
],
|
],
|
||||||
"name": "C",
|
"name": "C",
|
||||||
"nodeType": "ContractDefinition",
|
"nodeType": "ContractDefinition",
|
||||||
@ -97,13 +109,19 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"anonymous": false,
|
"anonymous": false,
|
||||||
"documentation": "Some comment on Evt.",
|
"documentation":
|
||||||
"id": 6,
|
{
|
||||||
|
"id": 7,
|
||||||
|
"nodeType": "StructuredDocumentation",
|
||||||
|
"src": "15:26:3",
|
||||||
|
"text": "Some comment on Evt."
|
||||||
|
},
|
||||||
|
"id": 9,
|
||||||
"name": "Evt",
|
"name": "Evt",
|
||||||
"nodeType": "EventDefinition",
|
"nodeType": "EventDefinition",
|
||||||
"parameters":
|
"parameters":
|
||||||
{
|
{
|
||||||
"id": 5,
|
"id": 8,
|
||||||
"nodeType": "ParameterList",
|
"nodeType": "ParameterList",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"src": "51:2:3"
|
"src": "51:2:3"
|
||||||
@ -113,26 +131,32 @@
|
|||||||
{
|
{
|
||||||
"body":
|
"body":
|
||||||
{
|
{
|
||||||
"id": 9,
|
"id": 13,
|
||||||
"nodeType": "Block",
|
"nodeType": "Block",
|
||||||
"src": "99:6:3",
|
"src": "99:6:3",
|
||||||
"statements":
|
"statements":
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": 8,
|
"id": 12,
|
||||||
"nodeType": "PlaceholderStatement",
|
"nodeType": "PlaceholderStatement",
|
||||||
"src": "101:1:3"
|
"src": "101:1:3"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"documentation": "Some comment on mod.",
|
"documentation":
|
||||||
"id": 10,
|
{
|
||||||
|
"id": 10,
|
||||||
|
"nodeType": "StructuredDocumentation",
|
||||||
|
"src": "57:26:3",
|
||||||
|
"text": "Some comment on mod."
|
||||||
|
},
|
||||||
|
"id": 14,
|
||||||
"name": "mod",
|
"name": "mod",
|
||||||
"nodeType": "ModifierDefinition",
|
"nodeType": "ModifierDefinition",
|
||||||
"overrides": null,
|
"overrides": null,
|
||||||
"parameters":
|
"parameters":
|
||||||
{
|
{
|
||||||
"id": 7,
|
"id": 11,
|
||||||
"nodeType": "ParameterList",
|
"nodeType": "ParameterList",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"src": "96:2:3"
|
"src": "96:2:3"
|
||||||
@ -144,14 +168,20 @@
|
|||||||
{
|
{
|
||||||
"body":
|
"body":
|
||||||
{
|
{
|
||||||
"id": 13,
|
"id": 18,
|
||||||
"nodeType": "Block",
|
"nodeType": "Block",
|
||||||
"src": "155:2:3",
|
"src": "155:2:3",
|
||||||
"statements": []
|
"statements": []
|
||||||
},
|
},
|
||||||
"documentation": "Some comment on fn.",
|
"documentation":
|
||||||
|
{
|
||||||
|
"id": 15,
|
||||||
|
"nodeType": "StructuredDocumentation",
|
||||||
|
"src": "108:25:3",
|
||||||
|
"text": "Some comment on fn."
|
||||||
|
},
|
||||||
"functionSelector": "a4a2c40b",
|
"functionSelector": "a4a2c40b",
|
||||||
"id": 14,
|
"id": 19,
|
||||||
"implemented": true,
|
"implemented": true,
|
||||||
"kind": "function",
|
"kind": "function",
|
||||||
"modifiers": [],
|
"modifiers": [],
|
||||||
@ -160,26 +190,26 @@
|
|||||||
"overrides": null,
|
"overrides": null,
|
||||||
"parameters":
|
"parameters":
|
||||||
{
|
{
|
||||||
"id": 11,
|
"id": 16,
|
||||||
"nodeType": "ParameterList",
|
"nodeType": "ParameterList",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"src": "145:2:3"
|
"src": "145:2:3"
|
||||||
},
|
},
|
||||||
"returnParameters":
|
"returnParameters":
|
||||||
{
|
{
|
||||||
"id": 12,
|
"id": 17,
|
||||||
"nodeType": "ParameterList",
|
"nodeType": "ParameterList",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"src": "155:0:3"
|
"src": "155:0:3"
|
||||||
},
|
},
|
||||||
"scope": 15,
|
"scope": 20,
|
||||||
"src": "134:23:3",
|
"src": "134:23:3",
|
||||||
"stateMutability": "nonpayable",
|
"stateMutability": "nonpayable",
|
||||||
"virtual": false,
|
"virtual": false,
|
||||||
"visibility": "public"
|
"visibility": "public"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"scope": 16,
|
"scope": 21,
|
||||||
"src": "0:159:3"
|
"src": "0:159:3"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
{
|
{
|
||||||
"C":
|
"C":
|
||||||
[
|
[
|
||||||
15
|
20
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -29,10 +29,10 @@
|
|||||||
"fullyImplemented": true,
|
"fullyImplemented": true,
|
||||||
"linearizedBaseContracts":
|
"linearizedBaseContracts":
|
||||||
[
|
[
|
||||||
15
|
20
|
||||||
],
|
],
|
||||||
"name": "C",
|
"name": "C",
|
||||||
"scope": 16
|
"scope": 21
|
||||||
},
|
},
|
||||||
"children":
|
"children":
|
||||||
[
|
[
|
||||||
@ -40,11 +40,19 @@
|
|||||||
"attributes":
|
"attributes":
|
||||||
{
|
{
|
||||||
"anonymous": false,
|
"anonymous": false,
|
||||||
"documentation": "Some comment on Evt.",
|
|
||||||
"name": "Evt"
|
"name": "Evt"
|
||||||
},
|
},
|
||||||
"children":
|
"children":
|
||||||
[
|
[
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"text": "Some comment on Evt."
|
||||||
|
},
|
||||||
|
"id": 7,
|
||||||
|
"name": "StructuredDocumentation",
|
||||||
|
"src": "15:26:3"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"attributes":
|
"attributes":
|
||||||
{
|
{
|
||||||
@ -54,19 +62,18 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"children": [],
|
"children": [],
|
||||||
"id": 5,
|
"id": 8,
|
||||||
"name": "ParameterList",
|
"name": "ParameterList",
|
||||||
"src": "51:2:3"
|
"src": "51:2:3"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"id": 6,
|
"id": 9,
|
||||||
"name": "EventDefinition",
|
"name": "EventDefinition",
|
||||||
"src": "42:12:3"
|
"src": "42:12:3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"attributes":
|
"attributes":
|
||||||
{
|
{
|
||||||
"documentation": "Some comment on mod.",
|
|
||||||
"name": "mod",
|
"name": "mod",
|
||||||
"overrides": null,
|
"overrides": null,
|
||||||
"virtual": false,
|
"virtual": false,
|
||||||
@ -77,55 +84,12 @@
|
|||||||
{
|
{
|
||||||
"attributes":
|
"attributes":
|
||||||
{
|
{
|
||||||
"parameters":
|
"text": "Some comment on mod."
|
||||||
[
|
|
||||||
null
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"children": [],
|
"id": 10,
|
||||||
"id": 7,
|
"name": "StructuredDocumentation",
|
||||||
"name": "ParameterList",
|
"src": "57:26:3"
|
||||||
"src": "96:2:3"
|
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"children":
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"id": 8,
|
|
||||||
"name": "PlaceholderStatement",
|
|
||||||
"src": "101:1:3"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"id": 9,
|
|
||||||
"name": "Block",
|
|
||||||
"src": "99:6:3"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"id": 10,
|
|
||||||
"name": "ModifierDefinition",
|
|
||||||
"src": "84:21:3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"attributes":
|
|
||||||
{
|
|
||||||
"documentation": "Some comment on fn.",
|
|
||||||
"functionSelector": "a4a2c40b",
|
|
||||||
"implemented": true,
|
|
||||||
"isConstructor": false,
|
|
||||||
"kind": "function",
|
|
||||||
"modifiers":
|
|
||||||
[
|
|
||||||
null
|
|
||||||
],
|
|
||||||
"name": "fn",
|
|
||||||
"overrides": null,
|
|
||||||
"scope": 15,
|
|
||||||
"stateMutability": "nonpayable",
|
|
||||||
"virtual": false,
|
|
||||||
"visibility": "public"
|
|
||||||
},
|
|
||||||
"children":
|
|
||||||
[
|
|
||||||
{
|
{
|
||||||
"attributes":
|
"attributes":
|
||||||
{
|
{
|
||||||
@ -137,6 +101,66 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"id": 11,
|
"id": 11,
|
||||||
"name": "ParameterList",
|
"name": "ParameterList",
|
||||||
|
"src": "96:2:3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"children":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 12,
|
||||||
|
"name": "PlaceholderStatement",
|
||||||
|
"src": "101:1:3"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 13,
|
||||||
|
"name": "Block",
|
||||||
|
"src": "99:6:3"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 14,
|
||||||
|
"name": "ModifierDefinition",
|
||||||
|
"src": "84:21:3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"functionSelector": "a4a2c40b",
|
||||||
|
"implemented": true,
|
||||||
|
"isConstructor": false,
|
||||||
|
"kind": "function",
|
||||||
|
"modifiers":
|
||||||
|
[
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"name": "fn",
|
||||||
|
"overrides": null,
|
||||||
|
"scope": 20,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"virtual": false,
|
||||||
|
"visibility": "public"
|
||||||
|
},
|
||||||
|
"children":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"text": "Some comment on fn."
|
||||||
|
},
|
||||||
|
"id": 15,
|
||||||
|
"name": "StructuredDocumentation",
|
||||||
|
"src": "108:25:3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"parameters":
|
||||||
|
[
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"children": [],
|
||||||
|
"id": 16,
|
||||||
|
"name": "ParameterList",
|
||||||
"src": "145:2:3"
|
"src": "145:2:3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -148,7 +172,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"children": [],
|
"children": [],
|
||||||
"id": 12,
|
"id": 17,
|
||||||
"name": "ParameterList",
|
"name": "ParameterList",
|
||||||
"src": "155:0:3"
|
"src": "155:0:3"
|
||||||
},
|
},
|
||||||
@ -161,22 +185,22 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"children": [],
|
"children": [],
|
||||||
"id": 13,
|
"id": 18,
|
||||||
"name": "Block",
|
"name": "Block",
|
||||||
"src": "155:2:3"
|
"src": "155:2:3"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"id": 14,
|
"id": 19,
|
||||||
"name": "FunctionDefinition",
|
"name": "FunctionDefinition",
|
||||||
"src": "134:23:3"
|
"src": "134:23:3"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"id": 15,
|
"id": 20,
|
||||||
"name": "ContractDefinition",
|
"name": "ContractDefinition",
|
||||||
"src": "0:159:3"
|
"src": "0:159:3"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"id": 16,
|
"id": 21,
|
||||||
"name": "SourceUnit",
|
"name": "SourceUnit",
|
||||||
"src": "0:160:3"
|
"src": "0:160:3"
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ void checkFunctionNatspec(
|
|||||||
std::string const& _expectedDoc
|
std::string const& _expectedDoc
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
auto doc = _function->documentation();
|
auto doc = _function->documentation()->text();
|
||||||
BOOST_CHECK_MESSAGE(doc != nullptr, "Function does not have Natspec Doc as expected");
|
BOOST_CHECK_MESSAGE(doc != nullptr, "Function does not have Natspec Doc as expected");
|
||||||
BOOST_CHECK_EQUAL(*doc, _expectedDoc);
|
BOOST_CHECK_EQUAL(*doc, _expectedDoc);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user