Skip to content

Commit 10f110c

Browse files
committed
[clang-doc] Use DiagnosticsEngine to handle diagnostic output
Right now we use a combination of outs() and errs() to handle tool output. Instead, we can use existing diagnostic support in clang and LLVM to ensure our tool has a consistent behavior with other tools.
1 parent c2445d9 commit 10f110c

21 files changed

+346
-221
lines changed

clang-tools-extra/clang-doc/BitcodeReader.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@
99
#include "BitcodeReader.h"
1010
#include "llvm/ADT/IndexedMap.h"
1111
#include "llvm/Support/Error.h"
12+
#include "llvm/Support/ErrorHandling.h"
1213
#include "llvm/Support/TimeProfiler.h"
1314
#include "llvm/Support/raw_ostream.h"
1415
#include <optional>
1516

1617
namespace clang {
1718
namespace doc {
1819

20+
static llvm::ExitOnError ExitOnErr("clang-doc error: ");
21+
1922
using Record = llvm::SmallVector<uint64_t, 1024>;
2023

2124
// This implements decode for SmallString.
@@ -717,8 +720,8 @@ llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F) {
717720

718721
template <typename T, typename ChildInfoType>
719722
static void addChild(T I, ChildInfoType &&R) {
720-
llvm::errs() << "invalid child type for info";
721-
exit(1);
723+
ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
724+
"invalid child type for info"));
722725
}
723726

724727
// Namespace children:
@@ -767,8 +770,9 @@ template <> void addChild(BaseRecordInfo *I, FunctionInfo &&R) {
767770
// parameters) or TemplateSpecializationInfo (for the specialization's
768771
// parameters).
769772
template <typename T> static void addTemplateParam(T I, TemplateParamInfo &&P) {
770-
llvm::errs() << "invalid container for template parameter";
771-
exit(1);
773+
ExitOnErr(
774+
llvm::createStringError(llvm::inconvertibleErrorCode(),
775+
"invalid container for template parameter"));
772776
}
773777
template <> void addTemplateParam(TemplateInfo *I, TemplateParamInfo &&P) {
774778
I->Params.emplace_back(std::move(P));
@@ -780,8 +784,8 @@ void addTemplateParam(TemplateSpecializationInfo *I, TemplateParamInfo &&P) {
780784

781785
// Template info. These apply to either records or functions.
782786
template <typename T> static void addTemplate(T I, TemplateInfo &&P) {
783-
llvm::errs() << "invalid container for template info";
784-
exit(1);
787+
ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
788+
"invalid container for template info"));
785789
}
786790
template <> void addTemplate(RecordInfo *I, TemplateInfo &&P) {
787791
I->Template.emplace(std::move(P));
@@ -799,8 +803,9 @@ template <> void addTemplate(FriendInfo *I, TemplateInfo &&P) {
799803
// Template specializations go only into template records.
800804
template <typename T>
801805
static void addTemplateSpecialization(T I, TemplateSpecializationInfo &&TSI) {
802-
llvm::errs() << "invalid container for template specialization info";
803-
exit(1);
806+
ExitOnErr(llvm::createStringError(
807+
llvm::inconvertibleErrorCode(),
808+
"invalid container for template specialization info"));
804809
}
805810
template <>
806811
void addTemplateSpecialization(TemplateInfo *I,
@@ -809,8 +814,8 @@ void addTemplateSpecialization(TemplateInfo *I,
809814
}
810815

811816
template <typename T> static void addConstraint(T I, ConstraintInfo &&C) {
812-
llvm::errs() << "invalid container for constraint info";
813-
exit(1);
817+
ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
818+
"invalid container for constraint info"));
814819
}
815820
template <> void addConstraint(TemplateInfo *I, ConstraintInfo &&C) {
816821
I->Constraints.emplace_back(std::move(C));

clang-tools-extra/clang-doc/BitcodeReader.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ namespace doc {
2929
// Class to read bitstream into an InfoSet collection
3030
class ClangDocBitcodeReader {
3131
public:
32-
ClangDocBitcodeReader(llvm::BitstreamCursor &Stream) : Stream(Stream) {}
32+
ClangDocBitcodeReader(llvm::BitstreamCursor &Stream, DiagnosticsEngine &Diags)
33+
: Stream(Stream), Diags(Diags) {}
3334

3435
// Main entry point, calls readBlock to read each block in the given stream.
3536
llvm::Expected<std::vector<std::unique_ptr<Info>>> readBitcode();
@@ -74,6 +75,7 @@ class ClangDocBitcodeReader {
7475
llvm::BitstreamCursor &Stream;
7576
std::optional<llvm::BitstreamBlockInfo> BlockInfo;
7677
FieldId CurrentReferenceField;
78+
DiagnosticsEngine &Diags;
7779
};
7880

7981
} // namespace doc

clang-tools-extra/clang-doc/BitcodeWriter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,9 @@ bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) {
769769
emitBlock(*static_cast<FriendInfo *>(I));
770770
break;
771771
case InfoType::IT_default:
772-
llvm::errs() << "Unexpected info, unable to write.\n";
772+
unsigned ID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
773+
"Unexpected info, unable to write.");
774+
Diags.Report(ID);
773775
return true;
774776
}
775777
return false;

clang-tools-extra/clang-doc/BitcodeWriter.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "Representation.h"
1919
#include "clang/AST/AST.h"
20+
#include "clang/Basic/Diagnostic.h"
2021
#include "llvm/ADT/DenseMap.h"
2122
#include "llvm/ADT/SmallVector.h"
2223
#include "llvm/ADT/StringRef.h"
@@ -179,7 +180,8 @@ enum class FieldId {
179180

180181
class ClangDocBitcodeWriter {
181182
public:
182-
ClangDocBitcodeWriter(llvm::BitstreamWriter &Stream) : Stream(Stream) {
183+
ClangDocBitcodeWriter(llvm::BitstreamWriter &Stream, DiagnosticsEngine &Diags)
184+
: Stream(Stream), Diags(Diags) {
183185
emitHeader();
184186
emitBlockInfoBlock();
185187
emitVersionBlock();
@@ -264,6 +266,7 @@ class ClangDocBitcodeWriter {
264266
SmallVector<uint32_t, BitCodeConstants::RecordSize> Record;
265267
llvm::BitstreamWriter &Stream;
266268
AbbreviationMap Abbrevs;
269+
DiagnosticsEngine &Diags;
267270
};
268271

269272
} // namespace doc

clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "Generators.h"
1616
#include "Representation.h"
1717
#include "support/File.h"
18+
#include "clang/Basic/Diagnostic.h"
1819
#include "llvm/Support/Error.h"
1920
#include "llvm/Support/MemoryBuffer.h"
2021
#include "llvm/Support/Mustache.h"
@@ -187,11 +188,13 @@ Error MustacheHTMLGenerator::generateDocs(
187188
}
188189

189190
auto File = MemoryBuffer::getFile(Path);
190-
if (EC = File.getError(); EC)
191-
// TODO: Buffer errors to report later, look into using Clang
192-
// diagnostics.
193-
llvm::errs() << "Failed to open file: " << Path << " " << EC.message()
194-
<< '\n';
191+
if (EC = File.getError(); EC) {
192+
unsigned ID = CDCtx.Diags.getCustomDiagID(DiagnosticsEngine::Warning,
193+
"Failed to open file: %0 %1");
194+
CDCtx.Diags.Report(ID) << Path << EC.message();
195+
JSONIter.increment(EC);
196+
continue;
197+
}
195198

196199
auto Parsed = json::parse((*File)->getBuffer());
197200
if (!Parsed)

clang-tools-extra/clang-doc/Mapper.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,10 @@ bool MapASTVisitor::mapDecl(const T *D, bool IsDefinition) {
9595
// this decl for some reason (e.g. we're only reporting public decls).
9696
if (Child)
9797
CDCtx.ECtx->reportResult(llvm::toHex(llvm::toStringRef(Child->USR)),
98-
serialize::serialize(Child));
98+
serialize::serialize(Child, CDCtx.Diags));
9999
if (Parent)
100100
CDCtx.ECtx->reportResult(llvm::toHex(llvm::toStringRef(Parent->USR)),
101-
serialize::serialize(Parent));
101+
serialize::serialize(Parent, CDCtx.Diags));
102102
}
103103
return true;
104104
}

clang-tools-extra/clang-doc/Representation.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -481,10 +481,11 @@ ClangDocContext::ClangDocContext(tooling::ExecutionContext *ECtx,
481481
StringRef RepositoryUrl,
482482
StringRef RepositoryLinePrefix, StringRef Base,
483483
std::vector<std::string> UserStylesheets,
484+
clang::DiagnosticsEngine &Diags,
484485
bool FTimeTrace)
485-
: ECtx(ECtx), ProjectName(ProjectName), PublicOnly(PublicOnly),
486-
FTimeTrace(FTimeTrace), OutDirectory(OutDirectory),
487-
UserStylesheets(UserStylesheets), Base(Base) {
486+
: ECtx(ECtx), ProjectName(ProjectName), OutDirectory(OutDirectory),
487+
SourceRoot(std::string(SourceRoot)), UserStylesheets(UserStylesheets),
488+
Base(Base), Diags(Diags), PublicOnly(PublicOnly), FTimeTrace(FTimeTrace) {
488489
llvm::SmallString<128> SourceRootDir(SourceRoot);
489490
if (SourceRoot.empty())
490491
// If no SourceRoot was provided the current path is used as the default

clang-tools-extra/clang-doc/Representation.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H
1616

1717
#include "clang/AST/Type.h"
18+
#include "clang/Basic/Diagnostic.h"
1819
#include "clang/Basic/Specifiers.h"
1920
#include "clang/Tooling/StandaloneExecution.h"
2021
#include "llvm/ADT/APSInt.h"
@@ -600,17 +601,13 @@ llvm::Expected<std::unique_ptr<Info>>
600601
mergeInfos(std::vector<std::unique_ptr<Info>> &Values);
601602

602603
struct ClangDocContext {
603-
ClangDocContext() = default;
604604
ClangDocContext(tooling::ExecutionContext *ECtx, StringRef ProjectName,
605605
bool PublicOnly, StringRef OutDirectory, StringRef SourceRoot,
606606
StringRef RepositoryUrl, StringRef RepositoryCodeLinePrefix,
607607
StringRef Base, std::vector<std::string> UserStylesheets,
608-
bool FTimeTrace = false);
608+
clang::DiagnosticsEngine &Diags, bool FTimeTrace = false);
609609
tooling::ExecutionContext *ECtx;
610-
std::string ProjectName; // Name of project clang-doc is documenting.
611-
bool PublicOnly; // Indicates if only public declarations are documented.
612-
bool FTimeTrace; // Indicates if ftime trace is turned on
613-
int Granularity; // Granularity of ftime trace
610+
std::string ProjectName; // Name of project clang-doc is documenting.
614611
std::string OutDirectory; // Directory for outputting generated files.
615612
std::string SourceRoot; // Directory where processed files are stored. Links
616613
// to definition locations will only be generated if
@@ -629,7 +626,12 @@ struct ClangDocContext {
629626
// Maps mustache template types to specific mustache template files.
630627
// Ex. comment-template -> /path/to/comment-template.mustache
631628
llvm::StringMap<std::string> MustacheTemplates;
629+
// A pointer to a DiagnosticsEngine for error reporting.
630+
clang::DiagnosticsEngine &Diags;
632631
Index Idx;
632+
int Granularity; // Granularity of ftime trace
633+
bool PublicOnly; // Indicates if only public declarations are documented.
634+
bool FTimeTrace; // Indicates if ftime trace is turned on
633635
};
634636

635637
} // namespace doc

clang-tools-extra/clang-doc/Serialize.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -335,28 +335,29 @@ static std::string getSourceCode(const Decl *D, const SourceRange &R) {
335335
.str();
336336
}
337337

338-
template <typename T> static std::string serialize(T &I) {
338+
template <typename T>
339+
static std::string serialize(T &I, DiagnosticsEngine &Diags) {
339340
SmallString<2048> Buffer;
340341
llvm::BitstreamWriter Stream(Buffer);
341-
ClangDocBitcodeWriter Writer(Stream);
342+
ClangDocBitcodeWriter Writer(Stream, Diags);
342343
Writer.emitBlock(I);
343344
return Buffer.str().str();
344345
}
345346

346-
std::string serialize(std::unique_ptr<Info> &I) {
347+
std::string serialize(std::unique_ptr<Info> &I, DiagnosticsEngine &Diags) {
347348
switch (I->IT) {
348349
case InfoType::IT_namespace:
349-
return serialize(*static_cast<NamespaceInfo *>(I.get()));
350+
return serialize(*static_cast<NamespaceInfo *>(I.get()), Diags);
350351
case InfoType::IT_record:
351-
return serialize(*static_cast<RecordInfo *>(I.get()));
352+
return serialize(*static_cast<RecordInfo *>(I.get()), Diags);
352353
case InfoType::IT_enum:
353-
return serialize(*static_cast<EnumInfo *>(I.get()));
354+
return serialize(*static_cast<EnumInfo *>(I.get()), Diags);
354355
case InfoType::IT_function:
355-
return serialize(*static_cast<FunctionInfo *>(I.get()));
356+
return serialize(*static_cast<FunctionInfo *>(I.get()), Diags);
356357
case InfoType::IT_concept:
357-
return serialize(*static_cast<ConceptInfo *>(I.get()));
358+
return serialize(*static_cast<ConceptInfo *>(I.get()), Diags);
358359
case InfoType::IT_variable:
359-
return serialize(*static_cast<VarInfo *>(I.get()));
360+
return serialize(*static_cast<VarInfo *>(I.get()), Diags);
360361
case InfoType::IT_friend:
361362
case InfoType::IT_typedef:
362363
case InfoType::IT_default:

clang-tools-extra/clang-doc/Serialize.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ emitInfo(const VarDecl *D, const FullComment *FC, const Location &Loc,
8383
// memory (vs storing USRs directly).
8484
SymbolID hashUSR(llvm::StringRef USR);
8585

86-
std::string serialize(std::unique_ptr<Info> &I);
86+
std::string serialize(std::unique_ptr<Info> &I, DiagnosticsEngine &Diags);
8787

8888
} // namespace serialize
8989
} // namespace doc

0 commit comments

Comments
 (0)