@@ -110,34 +110,34 @@ operator()(InfoTy& I)
110
110
111
111
void
112
112
JavadocFinalizer::
113
- finalize (doc::Reference& ref)
113
+ finalize (doc::Reference& ref, bool const emitWarning )
114
114
{
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 ) )
117
117
{
118
- ref.id = res->id ;
118
+ Info const * resPtr = *res;
119
+ MRDOCS_ASSERT (resPtr);
120
+ ref.id = resPtr->id ;
119
121
}
120
- if (res == nullptr &&
122
+ else if (
123
+ emitWarning &&
121
124
corpus_.config ->warnings &&
122
125
corpus_.config ->warnBrokenRef &&
123
126
// Only warn once per reference
124
- !warned_ .contains ({ref.string , current_context_->Name }) &&
127
+ !refWarned_ .contains ({ref.string , current_context_->Name }) &&
125
128
// Ignore std:: references
126
129
!ref.string .starts_with (" std::" ) &&
127
130
// Ignore other reference types that can't be replaced by `...`
128
131
ref.Kind == doc::NodeKind::reference)
129
132
{
130
133
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 });
141
141
}
142
142
}
143
143
@@ -154,11 +154,11 @@ finalize(doc::Node& node)
154
154
155
155
if constexpr (std::same_as<NodeTy, doc::Reference>)
156
156
{
157
- finalize (dynamic_cast <doc::Reference&>(N));
157
+ finalize (dynamic_cast <doc::Reference&>(N), true );
158
158
}
159
159
else if constexpr (std::same_as<NodeTy, doc::Throws>)
160
160
{
161
- finalize (dynamic_cast <doc::Throws&>(N).exception );
161
+ finalize (dynamic_cast <doc::Throws&>(N).exception , false );
162
162
}
163
163
});
164
164
}
@@ -280,62 +280,55 @@ copyBriefAndDetails(Javadoc& javadoc)
280
280
}
281
281
282
282
// 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 )
285
285
{
286
286
if (corpus_.config ->warnings &&
287
287
corpus_.config ->warnBrokenRef &&
288
- !warned_ .contains ({copied->string , current_context_->Name }))
288
+ !refWarned_ .contains ({copied->string , current_context_->Name }))
289
289
{
290
- MRDOCS_ASSERT (current_context_);
291
- auto primaryLoc = getPrimaryLocation (*current_context_);
292
290
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
+ " {}" ,
298
293
corpus_.Corpus ::qualifiedName (*current_context_),
299
294
copied->string ,
300
- copied-> string );
295
+ res. error (). reason () );
301
296
}
302
297
continue ;
303
298
}
304
299
305
300
// 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))
307
304
{
308
- operator ()(const_cast <Info&>(*res ));
305
+ operator ()(const_cast <Info&>(*resPtr ));
309
306
}
310
- if (!res ->javadoc )
307
+ if (!resPtr ->javadoc )
311
308
{
312
309
if (corpus_.config ->warnings &&
313
310
corpus_.config ->warnBrokenRef &&
314
- !warned_ .contains ({copied->string , current_context_->Name }))
311
+ !refWarned_ .contains ({copied->string , current_context_->Name }))
315
312
{
316
- auto ctxPrimaryLoc = getPrimaryLocation (*current_context_);
317
- auto resPrimaryLoc = getPrimaryLocation (*res);
313
+ auto resPrimaryLoc = getPrimaryLocation (*resPtr);
318
314
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 '{}'." ,
326
319
corpus_.Corpus ::qualifiedName (*current_context_),
327
320
copied->string ,
328
321
resPrimaryLoc->FullPath ,
329
322
resPrimaryLoc->LineNumber ,
330
- corpus_.Corpus ::qualifiedName (*res ));
323
+ corpus_.Corpus ::qualifiedName (*resPtr ));
331
324
}
332
325
continue ;
333
326
}
334
327
335
328
// Copy brief and details
336
329
bool const copyBrief = copied->parts == doc::Parts::all || copied->parts == doc::Parts::brief;
337
330
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 ;
339
332
if (copyBrief && !javadoc.brief )
340
333
{
341
334
javadoc.brief = src.brief ;
@@ -648,34 +641,54 @@ checkExists(SymbolID const& id) const
648
641
649
642
void
650
643
JavadocFinalizer::
651
- emitWarnings () const
644
+ emitWarnings ()
652
645
{
653
646
MRDOCS_CHECK_OR (corpus_.config ->warnings );
654
647
warnUndocumented ();
655
648
warnDocErrors ();
656
649
warnNoParamDocs ();
657
650
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
+ }
658
666
}
659
667
660
668
void
661
669
JavadocFinalizer::
662
- warnUndocumented () const
670
+ warnUndocumented ()
663
671
{
664
672
MRDOCS_CHECK_OR (corpus_.config ->warnIfUndocumented );
665
- for (auto & [id, name] : corpus_.undocumented_ )
673
+ for (auto & undocI : corpus_.undocumented_ )
666
674
{
667
- if (Info const * I = corpus_.find (id))
675
+ if (Info const * I = corpus_.find (undocI. id ))
668
676
{
669
- MRDOCS_CHECK_OR (!I->javadoc || I->Extraction == ExtractionMode::Regular);
677
+ MRDOCS_CHECK_OR (
678
+ !I->javadoc || I->Extraction == ExtractionMode::Regular);
670
679
}
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 );
672
685
}
673
686
corpus_.undocumented_ .clear ();
674
687
}
675
688
676
689
void
677
690
JavadocFinalizer::
678
- warnDocErrors () const
691
+ warnDocErrors ()
679
692
{
680
693
MRDOCS_CHECK_OR (corpus_.config ->warnIfDocError );
681
694
for (auto const & I : corpus_.info_ )
@@ -713,7 +726,7 @@ getJavadocParamNames(Javadoc const& javadoc)
713
726
714
727
void
715
728
JavadocFinalizer::
716
- warnParamErrors (FunctionInfo const & I) const
729
+ warnParamErrors (FunctionInfo const & I)
717
730
{
718
731
MRDOCS_CHECK_OR (I.javadoc );
719
732
@@ -723,15 +736,12 @@ warnParamErrors(FunctionInfo const& I) const
723
736
auto [firstDup, lastUnique] = std::ranges::unique (javadocParamNames);
724
737
auto duplicateParamNames = std::ranges::subrange (firstDup, lastUnique);
725
738
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);
727
740
std::string_view duplicateParamName: uniqueDuplicateParamNames)
728
741
{
729
- auto primaryLoc = getPrimaryLocation (I);
730
742
this ->warn (
731
- " {}:{} \n "
743
+ * getPrimaryLocation (I),
732
744
" {}: Duplicate parameter documentation for '{}'" ,
733
- primaryLoc->FullPath ,
734
- primaryLoc->LineNumber ,
735
745
corpus_.Corpus ::qualifiedName (I),
736
746
duplicateParamName);
737
747
}
@@ -745,12 +755,9 @@ warnParamErrors(FunctionInfo const& I) const
745
755
{
746
756
if (std::ranges::find (paramNames, javadocParamName) == paramNames.end ())
747
757
{
748
- auto primaryLoc = getPrimaryLocation (I);
749
758
this ->warn (
750
- " {}:{} \n "
759
+ * getPrimaryLocation (I),
751
760
" {}: Documented parameter '{}' does not exist" ,
752
- primaryLoc->FullPath ,
753
- primaryLoc->LineNumber ,
754
761
corpus_.Corpus ::qualifiedName (I),
755
762
javadocParamName);
756
763
}
@@ -760,7 +767,7 @@ warnParamErrors(FunctionInfo const& I) const
760
767
761
768
void
762
769
JavadocFinalizer::
763
- warnNoParamDocs () const
770
+ warnNoParamDocs ()
764
771
{
765
772
MRDOCS_CHECK_OR (corpus_.config ->warnNoParamdoc );
766
773
for (auto const & I : corpus_.info_ )
@@ -774,8 +781,9 @@ warnNoParamDocs() const
774
781
775
782
void
776
783
JavadocFinalizer::
777
- warnNoParamDocs (FunctionInfo const & I) const
784
+ warnNoParamDocs (FunctionInfo const & I)
778
785
{
786
+ MRDOCS_CHECK_OR (!I.IsDeleted );
779
787
// Check for function parameters that are not documented in javadoc
780
788
auto javadocParamNames = getJavadocParamNames (*I.javadoc );
781
789
auto paramNames =
@@ -785,12 +793,9 @@ warnNoParamDocs(FunctionInfo const& I) const
785
793
{
786
794
if (std::ranges::find (javadocParamNames, paramName) == javadocParamNames.end ())
787
795
{
788
- auto primaryLoc = getPrimaryLocation (I);
789
796
this ->warn (
790
- " {}:{} \n "
797
+ * getPrimaryLocation (I),
791
798
" {}: Missing documentation for parameter '{}'" ,
792
- primaryLoc->FullPath ,
793
- primaryLoc->LineNumber ,
794
799
corpus_.Corpus ::qualifiedName (I),
795
800
paramName);
796
801
}
@@ -810,33 +815,27 @@ warnNoParamDocs(FunctionInfo const& I) const
810
815
};
811
816
if (!isVoid (*I.ReturnType ))
812
817
{
813
- auto primaryLoc = getPrimaryLocation (I);
814
818
this ->warn (
815
- " {}:{} \n "
819
+ * getPrimaryLocation (I),
816
820
" {}: Missing documentation for return type" ,
817
- primaryLoc->FullPath ,
818
- primaryLoc->LineNumber ,
819
821
corpus_.Corpus ::qualifiedName (I));
820
822
}
821
823
}
822
824
}
823
825
824
826
void
825
827
JavadocFinalizer::
826
- warnUndocEnumValues () const
828
+ warnUndocEnumValues ()
827
829
{
828
830
MRDOCS_CHECK_OR (corpus_.config ->warnIfUndocEnumVal );
829
831
for (auto const & I : corpus_.info_ )
830
832
{
831
833
MRDOCS_CHECK_OR_CONTINUE (I->isEnumConstant ());
832
834
MRDOCS_CHECK_OR_CONTINUE (I->Extraction == ExtractionMode::Regular);
833
835
MRDOCS_CHECK_OR_CONTINUE (!I->javadoc );
834
- auto primaryLoc = getPrimaryLocation (*I);
835
836
this ->warn (
836
- " {}:{} \n "
837
+ * getPrimaryLocation (*I),
837
838
" {}: Missing documentation for enum value" ,
838
- primaryLoc->FullPath ,
839
- primaryLoc->LineNumber ,
840
839
corpus_.Corpus ::qualifiedName (*I));
841
840
}
842
841
}
0 commit comments