Skip to content

Commit bc51965

Browse files
committed
ordered warnings
#feat
1 parent fb7e59f commit bc51965

File tree

2 files changed

+145
-91
lines changed

2 files changed

+145
-91
lines changed

src/lib/Metadata/Finalizers/JavadocFinalizer.cpp

Lines changed: 75 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -110,34 +110,34 @@ operator()(InfoTy& I)
110110

111111
void
112112
JavadocFinalizer::
113-
finalize(doc::Reference& ref)
113+
finalize(doc::Reference& ref, bool const emitWarning)
114114
{
115-
Info const* res = corpus_.lookup(current_context_->id, ref.string);
116-
if (res)
115+
if (Expected<Info const*> res
116+
= corpus_.lookup(current_context_->id, ref.string))
117117
{
118-
ref.id = res->id;
118+
Info const* resPtr = *res;
119+
MRDOCS_ASSERT(resPtr);
120+
ref.id = resPtr->id;
119121
}
120-
if (res == nullptr &&
122+
else if (
123+
emitWarning &&
121124
corpus_.config->warnings &&
122125
corpus_.config->warnBrokenRef &&
123126
// Only warn once per reference
124-
!warned_.contains({ref.string, current_context_->Name}) &&
127+
!refWarned_.contains({ref.string, current_context_->Name}) &&
125128
// Ignore std:: references
126129
!ref.string.starts_with("std::") &&
127130
// Ignore other reference types that can't be replaced by `...`
128131
ref.Kind == doc::NodeKind::reference)
129132
{
130133
MRDOCS_ASSERT(current_context_);
131-
if (auto primaryLoc = getPrimaryLocation(*current_context_))
132-
{
133-
this->warn(
134-
"{}:{}\n{}: Failed to resolve reference to '{}'",
135-
primaryLoc->FullPath,
136-
primaryLoc->LineNumber,
137-
corpus_.Corpus::qualifiedName(*current_context_),
138-
ref.string);
139-
}
140-
warned_.insert({ref.string, current_context_->Name});
134+
this->warn(
135+
"{}: Failed to resolve reference to '{}'\n"
136+
" {}",
137+
corpus_.Corpus::qualifiedName(*current_context_),
138+
ref.string,
139+
res.error().reason());
140+
refWarned_.insert({ref.string, current_context_->Name});
141141
}
142142
}
143143

@@ -154,11 +154,11 @@ finalize(doc::Node& node)
154154

155155
if constexpr(std::same_as<NodeTy, doc::Reference>)
156156
{
157-
finalize(dynamic_cast<doc::Reference&>(N));
157+
finalize(dynamic_cast<doc::Reference&>(N), true);
158158
}
159159
else if constexpr (std::same_as<NodeTy, doc::Throws>)
160160
{
161-
finalize(dynamic_cast<doc::Throws&>(N).exception);
161+
finalize(dynamic_cast<doc::Throws&>(N).exception, false);
162162
}
163163
});
164164
}
@@ -280,62 +280,55 @@ copyBriefAndDetails(Javadoc& javadoc)
280280
}
281281

282282
// Find the node to copy from
283-
Info const* res = corpus_.lookup(current_context_->id, copied->string);
284-
if (!res)
283+
Expected<Info const*> res = corpus_.lookup(current_context_->id, copied->string);
284+
if (!res || !*res)
285285
{
286286
if (corpus_.config->warnings &&
287287
corpus_.config->warnBrokenRef &&
288-
!warned_.contains({copied->string, current_context_->Name}))
288+
!refWarned_.contains({copied->string, current_context_->Name}))
289289
{
290-
MRDOCS_ASSERT(current_context_);
291-
auto primaryLoc = getPrimaryLocation(*current_context_);
292290
this->warn(
293-
"{}:{}\n"
294-
"{}: Failed to copy documentation from '{}'\n"
295-
" Note: Symbol '{}' not found.",
296-
primaryLoc->FullPath,
297-
primaryLoc->LineNumber,
291+
"{}: Failed to copy documentation from '{}' (symbol not found)\n"
292+
" {}",
298293
corpus_.Corpus::qualifiedName(*current_context_),
299294
copied->string,
300-
copied->string);
295+
res.error().reason());
301296
}
302297
continue;
303298
}
304299

305300
// Ensure the source node is finalized
306-
if (!finalized_.contains(res))
301+
Info const* resPtr = *res;
302+
MRDOCS_ASSERT(resPtr);
303+
if (!finalized_.contains(resPtr))
307304
{
308-
operator()(const_cast<Info&>(*res));
305+
operator()(const_cast<Info&>(*resPtr));
309306
}
310-
if (!res->javadoc)
307+
if (!resPtr->javadoc)
311308
{
312309
if (corpus_.config->warnings &&
313310
corpus_.config->warnBrokenRef &&
314-
!warned_.contains({copied->string, current_context_->Name}))
311+
!refWarned_.contains({copied->string, current_context_->Name}))
315312
{
316-
auto ctxPrimaryLoc = getPrimaryLocation(*current_context_);
317-
auto resPrimaryLoc = getPrimaryLocation(*res);
313+
auto resPrimaryLoc = getPrimaryLocation(*resPtr);
318314
this->warn(
319-
"{}:{}\n"
320-
"{}: Failed to copy documentation from '{}'.\n"
321-
"No documentation available.\n"
322-
" {}:{}\n"
323-
" Note: No documentation available for '{}'.",
324-
ctxPrimaryLoc->FullPath,
325-
ctxPrimaryLoc->LineNumber,
315+
"{}: Failed to copy documentation from '{}' (no documentation available).\n"
316+
" No documentation available.\n"
317+
" {}:{}\n"
318+
" Note: No documentation available for '{}'.",
326319
corpus_.Corpus::qualifiedName(*current_context_),
327320
copied->string,
328321
resPrimaryLoc->FullPath,
329322
resPrimaryLoc->LineNumber,
330-
corpus_.Corpus::qualifiedName(*res));
323+
corpus_.Corpus::qualifiedName(*resPtr));
331324
}
332325
continue;
333326
}
334327

335328
// Copy brief and details
336329
bool const copyBrief = copied->parts == doc::Parts::all || copied->parts == doc::Parts::brief;
337330
bool const copyDetails = copied->parts == doc::Parts::all || copied->parts == doc::Parts::description;
338-
Javadoc const& src = *res->javadoc;
331+
Javadoc const& src = *resPtr->javadoc;
339332
if (copyBrief && !javadoc.brief)
340333
{
341334
javadoc.brief = src.brief;
@@ -648,34 +641,54 @@ checkExists(SymbolID const& id) const
648641

649642
void
650643
JavadocFinalizer::
651-
emitWarnings() const
644+
emitWarnings()
652645
{
653646
MRDOCS_CHECK_OR(corpus_.config->warnings);
654647
warnUndocumented();
655648
warnDocErrors();
656649
warnNoParamDocs();
657650
warnUndocEnumValues();
651+
652+
// Print to the console
653+
auto const level = !corpus_.config->warnAsError ? report::Level::warn : report::Level::error;
654+
for (auto const& [loc, msgs] : warnings_)
655+
{
656+
std::string locWarning = fmt::format(
657+
"{}:{}\n",
658+
loc.FullPath,
659+
loc.LineNumber);
660+
for (auto const& msg : msgs)
661+
{
662+
locWarning += fmt::format(" {}\n", msg);
663+
}
664+
report::log(level, locWarning);
665+
}
658666
}
659667

660668
void
661669
JavadocFinalizer::
662-
warnUndocumented() const
670+
warnUndocumented()
663671
{
664672
MRDOCS_CHECK_OR(corpus_.config->warnIfUndocumented);
665-
for (auto& [id, name] : corpus_.undocumented_)
673+
for (auto& undocI : corpus_.undocumented_)
666674
{
667-
if (Info const* I = corpus_.find(id))
675+
if (Info const* I = corpus_.find(undocI.id))
668676
{
669-
MRDOCS_CHECK_OR(!I->javadoc || I->Extraction == ExtractionMode::Regular);
677+
MRDOCS_CHECK_OR(
678+
!I->javadoc || I->Extraction == ExtractionMode::Regular);
670679
}
671-
this->warn("{}: Symbol is undocumented", name);
680+
bool const prefer_definition = undocI.kind == InfoKind::Record
681+
|| undocI.kind == InfoKind::Enum;
682+
this->warn(
683+
*getPrimaryLocation(undocI, prefer_definition),
684+
"{}: Symbol is undocumented", undocI.name);
672685
}
673686
corpus_.undocumented_.clear();
674687
}
675688

676689
void
677690
JavadocFinalizer::
678-
warnDocErrors() const
691+
warnDocErrors()
679692
{
680693
MRDOCS_CHECK_OR(corpus_.config->warnIfDocError);
681694
for (auto const& I : corpus_.info_)
@@ -713,7 +726,7 @@ getJavadocParamNames(Javadoc const& javadoc)
713726

714727
void
715728
JavadocFinalizer::
716-
warnParamErrors(FunctionInfo const& I) const
729+
warnParamErrors(FunctionInfo const& I)
717730
{
718731
MRDOCS_CHECK_OR(I.javadoc);
719732

@@ -723,15 +736,12 @@ warnParamErrors(FunctionInfo const& I) const
723736
auto [firstDup, lastUnique] = std::ranges::unique(javadocParamNames);
724737
auto duplicateParamNames = std::ranges::subrange(firstDup, lastUnique);
725738
auto [firstDupDup, _] = std::ranges::unique(duplicateParamNames);
726-
for (auto uniqueDuplicateParamNames = std::ranges::subrange(firstDup, firstDupDup);
739+
for (auto const uniqueDuplicateParamNames = std::ranges::subrange(firstDup, firstDupDup);
727740
std::string_view duplicateParamName: uniqueDuplicateParamNames)
728741
{
729-
auto primaryLoc = getPrimaryLocation(I);
730742
this->warn(
731-
"{}:{}\n"
743+
*getPrimaryLocation(I),
732744
"{}: Duplicate parameter documentation for '{}'",
733-
primaryLoc->FullPath,
734-
primaryLoc->LineNumber,
735745
corpus_.Corpus::qualifiedName(I),
736746
duplicateParamName);
737747
}
@@ -745,12 +755,9 @@ warnParamErrors(FunctionInfo const& I) const
745755
{
746756
if (std::ranges::find(paramNames, javadocParamName) == paramNames.end())
747757
{
748-
auto primaryLoc = getPrimaryLocation(I);
749758
this->warn(
750-
"{}:{}\n"
759+
*getPrimaryLocation(I),
751760
"{}: Documented parameter '{}' does not exist",
752-
primaryLoc->FullPath,
753-
primaryLoc->LineNumber,
754761
corpus_.Corpus::qualifiedName(I),
755762
javadocParamName);
756763
}
@@ -760,7 +767,7 @@ warnParamErrors(FunctionInfo const& I) const
760767

761768
void
762769
JavadocFinalizer::
763-
warnNoParamDocs() const
770+
warnNoParamDocs()
764771
{
765772
MRDOCS_CHECK_OR(corpus_.config->warnNoParamdoc);
766773
for (auto const& I : corpus_.info_)
@@ -774,8 +781,9 @@ warnNoParamDocs() const
774781

775782
void
776783
JavadocFinalizer::
777-
warnNoParamDocs(FunctionInfo const& I) const
784+
warnNoParamDocs(FunctionInfo const& I)
778785
{
786+
MRDOCS_CHECK_OR(!I.IsDeleted);
779787
// Check for function parameters that are not documented in javadoc
780788
auto javadocParamNames = getJavadocParamNames(*I.javadoc);
781789
auto paramNames =
@@ -785,12 +793,9 @@ warnNoParamDocs(FunctionInfo const& I) const
785793
{
786794
if (std::ranges::find(javadocParamNames, paramName) == javadocParamNames.end())
787795
{
788-
auto primaryLoc = getPrimaryLocation(I);
789796
this->warn(
790-
"{}:{}\n"
797+
*getPrimaryLocation(I),
791798
"{}: Missing documentation for parameter '{}'",
792-
primaryLoc->FullPath,
793-
primaryLoc->LineNumber,
794799
corpus_.Corpus::qualifiedName(I),
795800
paramName);
796801
}
@@ -810,33 +815,27 @@ warnNoParamDocs(FunctionInfo const& I) const
810815
};
811816
if (!isVoid(*I.ReturnType))
812817
{
813-
auto primaryLoc = getPrimaryLocation(I);
814818
this->warn(
815-
"{}:{}\n"
819+
*getPrimaryLocation(I),
816820
"{}: Missing documentation for return type",
817-
primaryLoc->FullPath,
818-
primaryLoc->LineNumber,
819821
corpus_.Corpus::qualifiedName(I));
820822
}
821823
}
822824
}
823825

824826
void
825827
JavadocFinalizer::
826-
warnUndocEnumValues() const
828+
warnUndocEnumValues()
827829
{
828830
MRDOCS_CHECK_OR(corpus_.config->warnIfUndocEnumVal);
829831
for (auto const& I : corpus_.info_)
830832
{
831833
MRDOCS_CHECK_OR_CONTINUE(I->isEnumConstant());
832834
MRDOCS_CHECK_OR_CONTINUE(I->Extraction == ExtractionMode::Regular);
833835
MRDOCS_CHECK_OR_CONTINUE(!I->javadoc);
834-
auto primaryLoc = getPrimaryLocation(*I);
835836
this->warn(
836-
"{}:{}\n"
837+
*getPrimaryLocation(*I),
837838
"{}: Missing documentation for enum value",
838-
primaryLoc->FullPath,
839-
primaryLoc->LineNumber,
840839
corpus_.Corpus::qualifiedName(*I));
841840
}
842841
}

0 commit comments

Comments
 (0)