mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
NatSpec: Implement default inheritance.
This commit is contained in:
@@ -32,6 +32,33 @@ using namespace solidity;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void copyMissingTags(StructurallyDocumentedAnnotation& _target, set<CallableDeclaration const*> const& _baseFunctions)
|
||||
{
|
||||
if (_baseFunctions.size() != 1)
|
||||
return;
|
||||
|
||||
auto& sourceDoc = dynamic_cast<StructurallyDocumentedAnnotation const&>((*_baseFunctions.begin())->annotation());
|
||||
|
||||
set<string> existingTags;
|
||||
|
||||
for (auto const& iterator: _target.docTags)
|
||||
existingTags.insert(iterator.first);
|
||||
|
||||
for (auto const& [tag, content]: sourceDoc.docTags)
|
||||
if (tag != "inheritdoc" && !existingTags.count(tag))
|
||||
_target.docTags.emplace(tag, content);
|
||||
}
|
||||
|
||||
bool parameterNamesEqual(CallableDeclaration const& _a, CallableDeclaration const& _b)
|
||||
{
|
||||
return boost::range::equal(_a.parameters(), _b.parameters(), [](auto const& pa, auto const& pb) { return pa->name() == pb->name(); });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool DocStringAnalyser::analyseDocStrings(SourceUnit const& _sourceUnit)
|
||||
{
|
||||
auto errorWatcher = m_errorReporter.errorWatcher();
|
||||
@@ -79,6 +106,9 @@ bool DocStringAnalyser::visit(VariableDeclaration const& _variable)
|
||||
"Documentation tag @title and @author is only allowed on contract definitions. "
|
||||
"It will be disallowed in 0.7.0."
|
||||
);
|
||||
|
||||
if (_variable.annotation().docTags.empty())
|
||||
copyMissingTags(_variable.annotation(), _variable.annotation().baseFunctions);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -143,6 +173,13 @@ void DocStringAnalyser::handleCallable(
|
||||
parseDocStrings(_node, _annotation, validTags, "functions");
|
||||
checkParameters(_callable, _node, _annotation);
|
||||
|
||||
if (
|
||||
_annotation.docTags.empty() &&
|
||||
_callable.annotation().baseFunctions.size() == 1 &&
|
||||
parameterNamesEqual(_callable, **_callable.annotation().baseFunctions.begin())
|
||||
)
|
||||
copyMissingTags(_annotation, _callable.annotation().baseFunctions);
|
||||
|
||||
if (_node.documentation() && _annotation.docTags.count("author") > 0)
|
||||
m_errorReporter.warning(
|
||||
9843_error, _node.documentation()->location(),
|
||||
|
||||
@@ -307,11 +307,6 @@ bool CompilerStack::analyze()
|
||||
if (source->ast && !syntaxChecker.checkSyntax(*source->ast))
|
||||
noErrors = false;
|
||||
|
||||
DocStringAnalyser docStringAnalyser(m_errorReporter);
|
||||
for (Source const* source: m_sourceOrder)
|
||||
if (source->ast && !docStringAnalyser.analyseDocStrings(*source->ast))
|
||||
noErrors = false;
|
||||
|
||||
m_globalContext = make_shared<GlobalContext>();
|
||||
// We need to keep the same resolver during the whole process.
|
||||
NameAndTypeResolver resolver(*m_globalContext, m_evmVersion, m_errorReporter);
|
||||
@@ -367,6 +362,11 @@ bool CompilerStack::analyze()
|
||||
if (!contractLevelChecker.check(*contract))
|
||||
noErrors = false;
|
||||
|
||||
DocStringAnalyser docStringAnalyser(m_errorReporter);
|
||||
for (Source const* source: m_sourceOrder)
|
||||
if (source->ast && !docStringAnalyser.analyseDocStrings(*source->ast))
|
||||
noErrors = false;
|
||||
|
||||
// New we run full type checks that go down to the expression level. This
|
||||
// cannot be done earlier, because we need cross-contract types and information
|
||||
// about whether a contract is abstract for the `new` expression.
|
||||
|
||||
Reference in New Issue
Block a user