summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-doc
diff options
context:
space:
mode:
authorJulie Hockett <juliehockett@google.com>2018-08-16 21:54:34 +0000
committerJulie Hockett <juliehockett@google.com>2018-08-16 21:54:34 +0000
commit1bcd1b03243e887437a165e25e12888f9c7a6e0f (patch)
tree541ceb6963811f194b2f68c7363de916406ef3fd /clang-tools-extra/clang-doc
parentd4b3f19ba6617c7aef8f538fa657bb6de7fc31f6 (diff)
downloadbcm5719-llvm-1bcd1b03243e887437a165e25e12888f9c7a6e0f.tar.gz
bcm5719-llvm-1bcd1b03243e887437a165e25e12888f9c7a6e0f.zip
Implement a (simple) Markdown generator
Implementing a simple Markdown generator from the emitted bitcode summary of declarations. Very primitive at this point, but will be expanded. Currently emits an .md file for each class and namespace, listing its contents. For a more detailed overview of the tool, see the design document on the mailing list: http://lists.llvm.org/pipermail/cfe-dev/2017-December/056203.html Differential Revision: https://reviews.llvm.org/D43424 llvm-svn: 339948
Diffstat (limited to 'clang-tools-extra/clang-doc')
-rw-r--r--clang-tools-extra/clang-doc/CMakeLists.txt1
-rw-r--r--clang-tools-extra/clang-doc/Generators.cpp3
-rw-r--r--clang-tools-extra/clang-doc/Generators.h2
-rw-r--r--clang-tools-extra/clang-doc/MDGenerator.cpp314
-rw-r--r--clang-tools-extra/clang-doc/Representation.h15
-rw-r--r--clang-tools-extra/clang-doc/YAMLGenerator.cpp10
-rw-r--r--clang-tools-extra/clang-doc/gen_tests.py33
-rw-r--r--clang-tools-extra/clang-doc/tool/ClangDocMain.cpp43
8 files changed, 383 insertions, 38 deletions
diff --git a/clang-tools-extra/clang-doc/CMakeLists.txt b/clang-tools-extra/clang-doc/CMakeLists.txt
index eaebf616f6f..1d70bb08fea 100644
--- a/clang-tools-extra/clang-doc/CMakeLists.txt
+++ b/clang-tools-extra/clang-doc/CMakeLists.txt
@@ -10,6 +10,7 @@ add_clang_library(clangDoc
ClangDoc.cpp
Generators.cpp
Mapper.cpp
+ MDGenerator.cpp
Representation.cpp
Serialize.cpp
YAMLGenerator.cpp
diff --git a/clang-tools-extra/clang-doc/Generators.cpp b/clang-tools-extra/clang-doc/Generators.cpp
index fe01d610970..5a0d0c5c138 100644
--- a/clang-tools-extra/clang-doc/Generators.cpp
+++ b/clang-tools-extra/clang-doc/Generators.cpp
@@ -29,8 +29,11 @@ findGeneratorByName(llvm::StringRef Format) {
// This anchor is used to force the linker to link in the generated object file
// and thus register the generators.
extern volatile int YAMLGeneratorAnchorSource;
+extern volatile int MDGeneratorAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED YAMLGeneratorAnchorDest =
YAMLGeneratorAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED MDGeneratorAnchorDest =
+ MDGeneratorAnchorSource;
} // namespace doc
} // namespace clang
diff --git a/clang-tools-extra/clang-doc/Generators.h b/clang-tools-extra/clang-doc/Generators.h
index 9106d2cff6a..90a81e82d6c 100644
--- a/clang-tools-extra/clang-doc/Generators.h
+++ b/clang-tools-extra/clang-doc/Generators.h
@@ -27,7 +27,7 @@ public:
virtual ~Generator() = default;
// Write out the decl info in the specified format.
- virtual bool generateDocForInfo(Info *I, llvm::raw_ostream &OS) = 0;
+ virtual llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS) = 0;
};
typedef llvm::Registry<Generator> GeneratorRegistry;
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
new file mode 100644
index 00000000000..f989f3fa65c
--- /dev/null
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -0,0 +1,314 @@
+//===-- MDGenerator.cpp - Markdown Generator --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Generators.h"
+#include "Representation.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include <string>
+
+using namespace llvm;
+
+namespace clang {
+namespace doc {
+
+// Enum conversion
+
+std::string getAccess(AccessSpecifier AS) {
+ switch (AS) {
+ case AccessSpecifier::AS_public:
+ return "public";
+ case AccessSpecifier::AS_protected:
+ return "protected";
+ case AccessSpecifier::AS_private:
+ return "private";
+ case AccessSpecifier::AS_none:
+ return {};
+ }
+}
+
+std::string getTagType(TagTypeKind AS) {
+ switch (AS) {
+ case TagTypeKind::TTK_Class:
+ return "class";
+ case TagTypeKind::TTK_Union:
+ return "union";
+ case TagTypeKind::TTK_Interface:
+ return "interface";
+ case TagTypeKind::TTK_Struct:
+ return "struct";
+ case TagTypeKind::TTK_Enum:
+ return "enum";
+ }
+}
+
+// Markdown generation
+
+std::string genItalic(const Twine &Text) { return "*" + Text.str() + "*"; }
+
+std::string genEmphasis(const Twine &Text) { return "**" + Text.str() + "**"; }
+
+std::string genLink(const Twine &Text, const Twine &Link) {
+ return "[" + Text.str() + "](" + Link.str() + ")";
+}
+
+std::string genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs) {
+ std::string Buffer;
+ llvm::raw_string_ostream Stream(Buffer);
+ bool First = true;
+ for (const auto &R : Refs) {
+ if (!First)
+ Stream << ", ";
+ Stream << R.Name;
+ First = false;
+ }
+ return Stream.str();
+}
+
+void writeLine(const Twine &Text, raw_ostream &OS) { OS << Text << "\n"; }
+
+void writeNewLine(raw_ostream &OS) { OS << "\n"; }
+
+void writeHeader(const Twine &Text, unsigned int Num, raw_ostream &OS) {
+ OS << std::string(Num, '#') + " " + Text << "\n";
+}
+
+void writeFileDefinition(const Location &L, raw_ostream &OS) {
+ OS << genItalic("Defined at line " + std::to_string(L.LineNumber) + " of " +
+ L.Filename)
+ << "\n";
+}
+
+void writeDescription(const CommentInfo &I, raw_ostream &OS) {
+ if (I.Kind == "FullComment") {
+ for (const auto &Child : I.Children)
+ writeDescription(*Child, OS);
+ } else if (I.Kind == "ParagraphComment") {
+ for (const auto &Child : I.Children)
+ writeDescription(*Child, OS);
+ writeNewLine(OS);
+ } else if (I.Kind == "BlockCommandComment") {
+ OS << genEmphasis(I.Name);
+ for (const auto &Child : I.Children)
+ writeDescription(*Child, OS);
+ } else if (I.Kind == "InlineCommandComment") {
+ OS << genEmphasis(I.Name) << " " << I.Text;
+ } else if (I.Kind == "ParamCommandComment") {
+ std::string Direction = I.Explicit ? (" " + I.Direction).str() : "";
+ OS << genEmphasis(I.ParamName) << I.Text << Direction << "\n";
+ } else if (I.Kind == "TParamCommandComment") {
+ std::string Direction = I.Explicit ? (" " + I.Direction).str() : "";
+ OS << genEmphasis(I.ParamName) << I.Text << Direction << "\n";
+ } else if (I.Kind == "VerbatimBlockComment") {
+ for (const auto &Child : I.Children)
+ writeDescription(*Child, OS);
+ } else if (I.Kind == "VerbatimBlockLineComment") {
+ OS << I.Text;
+ writeNewLine(OS);
+ } else if (I.Kind == "VerbatimLineComment") {
+ OS << I.Text;
+ writeNewLine(OS);
+ } else if (I.Kind == "HTMLStartTagComment") {
+ if (I.AttrKeys.size() != I.AttrValues.size())
+ return;
+ std::string Buffer;
+ llvm::raw_string_ostream Attrs(Buffer);
+ for (unsigned Idx = 0; Idx < I.AttrKeys.size(); ++Idx)
+ Attrs << " \"" << I.AttrKeys[Idx] << "=" << I.AttrValues[Idx] << "\"";
+
+ std::string CloseTag = I.SelfClosing ? "/>" : ">";
+ writeLine("<" + I.Name + Attrs.str() + CloseTag, OS);
+ } else if (I.Kind == "HTMLEndTagComment") {
+ writeLine("</" + I.Name + ">", OS);
+ } else if (I.Kind == "TextComment") {
+ OS << I.Text;
+ } else {
+ OS << "Unknown comment kind: " << I.Kind << ".\n";
+ }
+}
+
+void genMarkdown(const EnumInfo &I, llvm::raw_ostream &OS) {
+ if (I.Scoped)
+ writeLine("| enum class " + I.Name + " |", OS);
+ else
+ writeLine("| enum " + I.Name + " |", OS);
+ writeLine("--", OS);
+
+ std::string Buffer;
+ llvm::raw_string_ostream Members(Buffer);
+ if (!I.Members.empty())
+ for (const auto &N : I.Members)
+ Members << "| " << N << " |\n";
+ writeLine(Members.str(), OS);
+ if (I.DefLoc)
+ writeFileDefinition(I.DefLoc.getValue(), OS);
+
+ for (const auto &C : I.Description)
+ writeDescription(C, OS);
+}
+
+void genMarkdown(const FunctionInfo &I, llvm::raw_ostream &OS) {
+ std::string Buffer;
+ llvm::raw_string_ostream Stream(Buffer);
+ bool First = true;
+ for (const auto &N : I.Params) {
+ if (!First)
+ Stream << ", ";
+ Stream << N.Type.Name + " " + N.Name;
+ First = false;
+ }
+ Twine Signature =
+ I.ReturnType.Type.Name + " " + I.Name + "(" + Stream.str() + ")";
+ std::string Access = getAccess(I.Access);
+ if (Access != "")
+ writeHeader(genItalic(Access) + " " + Signature, 3, OS);
+ else
+ writeHeader(Signature, 3, OS);
+ if (I.DefLoc)
+ writeFileDefinition(I.DefLoc.getValue(), OS);
+
+ for (const auto &C : I.Description)
+ writeDescription(C, OS);
+}
+
+void genMarkdown(const NamespaceInfo &I, llvm::raw_ostream &OS) {
+ if (I.Name == "")
+ writeHeader("Global Namespace", 1, OS);
+ else
+ writeHeader("namespace " + I.Name, 1, OS);
+ writeNewLine(OS);
+
+ if (!I.Description.empty()) {
+ for (const auto &C : I.Description)
+ writeDescription(C, OS);
+ writeNewLine(OS);
+ }
+
+ if (!I.ChildNamespaces.empty()) {
+ writeHeader("Namespaces", 2, OS);
+ for (const auto &R : I.ChildNamespaces)
+ writeLine(R.Name, OS);
+ writeNewLine(OS);
+ }
+ if (!I.ChildRecords.empty()) {
+ writeHeader("Records", 2, OS);
+ for (const auto &R : I.ChildRecords)
+ writeLine(R.Name, OS);
+ writeNewLine(OS);
+ }
+ if (!I.ChildFunctions.empty()) {
+ writeHeader("Functions", 2, OS);
+ for (const auto &F : I.ChildFunctions)
+ genMarkdown(F, OS);
+ writeNewLine(OS);
+ }
+ if (!I.ChildEnums.empty()) {
+ writeHeader("Enums", 2, OS);
+ for (const auto &E : I.ChildEnums)
+ genMarkdown(E, OS);
+ writeNewLine(OS);
+ }
+}
+
+void genMarkdown(const RecordInfo &I, llvm::raw_ostream &OS) {
+ writeHeader(getTagType(I.TagType) + " " + I.Name, 1, OS);
+ if (I.DefLoc)
+ writeFileDefinition(I.DefLoc.getValue(), OS);
+
+ if (!I.Description.empty()) {
+ for (const auto &C : I.Description)
+ writeDescription(C, OS);
+ writeNewLine(OS);
+ }
+
+ std::string Parents = genReferenceList(I.Parents);
+ std::string VParents = genReferenceList(I.VirtualParents);
+ if (!Parents.empty() || !VParents.empty()) {
+ if (Parents.empty())
+ writeLine("Inherits from " + VParents, OS);
+ else if (VParents.empty())
+ writeLine("Inherits from " + Parents, OS);
+ else
+ writeLine("Inherits from " + Parents + ", " + VParents, OS);
+ writeNewLine(OS);
+ }
+
+ if (!I.Members.empty()) {
+ writeHeader("Members", 2, OS);
+ for (const auto Member : I.Members) {
+ std::string Access = getAccess(Member.Access);
+ if (Access != "")
+ writeLine(Access + " " + Member.Type.Name + " " + Member.Name, OS);
+ else
+ writeLine(Member.Type.Name + " " + Member.Name, OS);
+ }
+ writeNewLine(OS);
+ }
+
+ if (!I.ChildRecords.empty()) {
+ writeHeader("Records", 2, OS);
+ for (const auto &R : I.ChildRecords)
+ writeLine(R.Name, OS);
+ writeNewLine(OS);
+ }
+ if (!I.ChildFunctions.empty()) {
+ writeHeader("Functions", 2, OS);
+ for (const auto &F : I.ChildFunctions)
+ genMarkdown(F, OS);
+ writeNewLine(OS);
+ }
+ if (!I.ChildEnums.empty()) {
+ writeHeader("Enums", 2, OS);
+ for (const auto &E : I.ChildEnums)
+ genMarkdown(E, OS);
+ writeNewLine(OS);
+ }
+}
+
+/// Generator for Markdown documentation.
+class MDGenerator : public Generator {
+public:
+ static const char *Format;
+
+ llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS) override;
+};
+
+const char *MDGenerator::Format = "md";
+
+llvm::Error MDGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS) {
+ switch (I->IT) {
+ case InfoType::IT_namespace:
+ genMarkdown(*static_cast<clang::doc::NamespaceInfo *>(I), OS);
+ break;
+ case InfoType::IT_record:
+ genMarkdown(*static_cast<clang::doc::RecordInfo *>(I), OS);
+ break;
+ case InfoType::IT_enum:
+ genMarkdown(*static_cast<clang::doc::EnumInfo *>(I), OS);
+ break;
+ case InfoType::IT_function:
+ genMarkdown(*static_cast<clang::doc::FunctionInfo *>(I), OS);
+ break;
+ case InfoType::IT_default:
+ return llvm::make_error<llvm::StringError>("Unexpected info type.\n",
+ llvm::inconvertibleErrorCode());
+ }
+ return llvm::Error::success();
+}
+
+static GeneratorRegistry::Add<MDGenerator> MD(MDGenerator::Format,
+ "Generator for MD output.");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the generator.
+volatile int MDGeneratorAnchorSource = 0;
+
+} // namespace doc
+} // namespace clang
diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h
index 9e88bd9c8db..57f51012606 100644
--- a/clang-tools-extra/clang-doc/Representation.h
+++ b/clang-tools-extra/clang-doc/Representation.h
@@ -48,13 +48,14 @@ struct CommentInfo {
CommentInfo(CommentInfo &Other) = delete;
CommentInfo(CommentInfo &&Other) = default;
- SmallString<16> Kind; // Kind of comment (TextComment, InlineCommandComment,
- // HTMLStartTagComment, HTMLEndTagComment,
- // BlockCommandComment, ParamCommandComment,
- // TParamCommandComment, VerbatimBlockComment,
- // VerbatimBlockLineComment, VerbatimLineComment).
- SmallString<64> Text; // Text of the comment.
- SmallString<16> Name; // Name of the comment (for Verbatim and HTML).
+ SmallString<16>
+ Kind; // Kind of comment (FullComment, ParagraphComment, TextComment,
+ // InlineCommandComment, HTMLStartTagComment, HTMLEndTagComment,
+ // BlockCommandComment, ParamCommandComment,
+ // TParamCommandComment, VerbatimBlockComment,
+ // VerbatimBlockLineComment, VerbatimLineComment).
+ SmallString<64> Text; // Text of the comment.
+ SmallString<16> Name; // Name of the comment (for Verbatim and HTML).
SmallString<8> Direction; // Parameter direction (for (T)ParamCommand).
SmallString<16> ParamName; // Parameter name (for (T)ParamCommand).
SmallString<16> CloseName; // Closing tag name (for VerbatimBlock).
diff --git a/clang-tools-extra/clang-doc/YAMLGenerator.cpp b/clang-tools-extra/clang-doc/YAMLGenerator.cpp
index 58c1e1f36b9..e093901987e 100644
--- a/clang-tools-extra/clang-doc/YAMLGenerator.cpp
+++ b/clang-tools-extra/clang-doc/YAMLGenerator.cpp
@@ -242,12 +242,12 @@ class YAMLGenerator : public Generator {
public:
static const char *Format;
- bool generateDocForInfo(Info *I, llvm::raw_ostream &OS) override;
+ llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS) override;
};
const char *YAMLGenerator::Format = "yaml";
-bool YAMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS) {
+llvm::Error YAMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS) {
llvm::yaml::Output InfoYAML(OS);
switch (I->IT) {
case InfoType::IT_namespace:
@@ -263,10 +263,10 @@ bool YAMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS) {
InfoYAML << *static_cast<clang::doc::FunctionInfo *>(I);
break;
case InfoType::IT_default:
- llvm::errs() << "Unexpected info type in index.\n";
- return true;
+ return llvm::make_error<llvm::StringError>("Unexpected info type.\n",
+ llvm::inconvertibleErrorCode());
}
- return false;
+ return llvm::Error::success();
}
static GeneratorRegistry::Add<YAMLGenerator> YAML(YAMLGenerator::Format,
diff --git a/clang-tools-extra/clang-doc/gen_tests.py b/clang-tools-extra/clang-doc/gen_tests.py
index ccdb069c433..9259684d588 100644
--- a/clang-tools-extra/clang-doc/gen_tests.py
+++ b/clang-tools-extra/clang-doc/gen_tests.py
@@ -18,16 +18,19 @@ accuracy before using.
To generate all current tests:
- Generate mapper tests:
- python gen_tests.py -flag='--dump-mapper' -flag='--doxygen' -flag='--extra-arg=-fmodules-ts' -prefix mapper
+ python gen_tests.py -flag='--dump-mapper' -flag='--doxygen' -flag='--extra-arg=-fmodules-ts' -prefix mapper -use-check-next
- Generate reducer tests:
- python gen_tests.py -flag='--dump-intermediate' -flag='--doxygen' -flag='--extra-arg=-fmodules-ts' -prefix bc
+ python gen_tests.py -flag='--dump-intermediate' -flag='--doxygen' -flag='--extra-arg=-fmodules-ts' -prefix bc -use-check-next
- Generate yaml tests:
- python gen_tests.py -flag='--format=yaml' -flag='--doxygen' -flag='--extra-arg=-fmodules-ts' -prefix yaml
+ python gen_tests.py -flag='--format=yaml' -flag='--doxygen' -flag='--extra-arg=-fmodules-ts' -prefix yaml -use-check-next
- Generate public decl tests:
- python gen_tests.py -flag='--format=yaml' -flag='--doxygen' -flag='--public' -flag='--extra-arg=-fmodules-ts' -prefix public
+ python gen_tests.py -flag='--format=yaml' -flag='--doxygen' -flag='--public' -flag='--extra-arg=-fmodules-ts' -prefix public -use-check-next
+
+- Generate Markdown tests:
+ python gen_tests.py -flag='--format=md' -flag='--doxygen' -flag='--public' -flag='--extra-arg=-fmodules-ts' -prefix md
This script was written on/for Linux, and has not been tested on any other
platform and so it may not work.
@@ -95,7 +98,8 @@ def get_test_case_code(test_case_path, flags):
return code
-def get_output(root, out_file, case_out_path, flags, checkname, bcanalyzer):
+def get_output(root, out_file, case_out_path, flags, checkname, bcanalyzer,
+ check_next=True):
output = ''
run_cmd = ''
if '--dump-mapper' in flags or '--dump-intermediate' in flags:
@@ -119,8 +123,14 @@ def get_output(root, out_file, case_out_path, flags, checkname, bcanalyzer):
output = re.sub(YAML_USR_REGEX, YAML_USR, output)
output = re.sub(BITCODE_USR_REGEX, BITCODE_USR, output)
output = CHECK.format(checkname) + output.rstrip()
- output = run_cmd + output.replace('\n',
- '\n' + CHECK_NEXT.format(checkname))
+
+ if check_next:
+ check_comment = CHECK_NEXT.format(checkname)
+ else:
+ check_comment = CHECK.format(checkname)
+
+ output = output.replace('\n', '\n' + check_comment)
+ output = run_cmd + output.replace('%s\n' % check_comment, "")
return output + '\n'
@@ -151,6 +161,12 @@ def main():
metavar="PATH",
default='llvm-bcanalyzer',
help='path to llvm-bcanalyzer binary')
+ parser.add_argument(
+ '-use-check-next',
+ dest='check_next',
+ default=False,
+ action='store_true',
+ help='Whether or not to use CHECK-NEXT in the resulting tests.')
args = parser.parse_args()
flags = ' '.join(args.flags)
@@ -188,7 +204,8 @@ def main():
if len(usr) < 2:
continue
all_output += get_output(root, out_file, out_dir, args.flags,
- num_outputs, args.bcanalyzer)
+ num_outputs, args.bcanalyzer,
+ args.check_next)
num_outputs += 1
# Add test case code to test
diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
index 6e4a92d7b06..6b50f6ca838 100644
--- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
+++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -34,6 +34,7 @@
#include "clang/Tooling/StandaloneExecution.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/APFloat.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -69,13 +70,18 @@ static llvm::cl::opt<bool>
llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
enum OutputFormatTy {
+ md,
yaml,
};
-static llvm::cl::opt<OutputFormatTy> FormatEnum(
- "format", llvm::cl::desc("Format for outputted docs."),
- llvm::cl::values(clEnumVal(yaml, "Documentation in YAML format.")),
- llvm::cl::init(yaml), llvm::cl::cat(ClangDocCategory));
+static llvm::cl::opt<OutputFormatTy>
+ FormatEnum("format", llvm::cl::desc("Format for outputted docs."),
+ llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml",
+ "Documentation in YAML format."),
+ clEnumValN(OutputFormatTy::md, "md",
+ "Documentation in MD format.")),
+ llvm::cl::init(OutputFormatTy::yaml),
+ llvm::cl::cat(ClangDocCategory));
static llvm::cl::opt<bool> DoxygenOnly(
"doxygen",
@@ -155,10 +161,12 @@ getInfoOutputFile(StringRef Root,
return Path;
}
-std::string getFormatString(OutputFormatTy Ty) {
- switch (Ty) {
- case yaml:
+std::string getFormatString() {
+ switch (FormatEnum) {
+ case OutputFormatTy::yaml:
return "yaml";
+ case OutputFormatTy::md:
+ return "md";
}
llvm_unreachable("Unknown OutputFormatTy");
}
@@ -191,14 +199,6 @@ int main(int argc, const char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
std::error_code OK;
- // Fail early if an invalid format was provided.
- std::string Format = getFormatString(FormatEnum);
- auto G = doc::findGeneratorByName(Format);
- if (!G) {
- llvm::errs() << toString(G.takeError()) << "\n";
- return 1;
- }
-
auto Exec = clang::tooling::createExecutorFromCommandLineArgs(
argc, argv, ClangDocCategory);
@@ -207,6 +207,15 @@ int main(int argc, const char **argv) {
return 1;
}
+ // Fail early if an invalid format was provided.
+ std::string Format = getFormatString();
+ llvm::outs() << "Emiting docs in " << Format << " format.\n";
+ auto G = doc::findGeneratorByName(Format);
+ if (!G) {
+ llvm::errs() << toString(G.takeError()) << "\n";
+ return 1;
+ }
+
ArgumentsAdjuster ArgAdjuster;
if (!DoxygenOnly)
ArgAdjuster = combineAdjusters(
@@ -277,8 +286,8 @@ int main(int argc, const char **argv) {
continue;
}
- if (G->get()->generateDocForInfo(I, InfoOS))
- llvm::errs() << "Unable to generate docs for info.\n";
+ if (auto Err = G->get()->generateDocForInfo(I, InfoOS))
+ llvm::errs() << toString(std::move(Err)) << "\n";
}
return 0;
OpenPOWER on IntegriCloud