ClangCommentCommandInfoEmitter.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. //===--- ClangCommentCommandInfoEmitter.cpp - Generate command lists -----====//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This tablegen backend emits command lists and efficient matchers for command
  10. // names that are used in documentation comments.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "TableGenBackends.h"
  14. #include "llvm/TableGen/Record.h"
  15. #include "llvm/TableGen/StringMatcher.h"
  16. #include "llvm/TableGen/TableGenBackend.h"
  17. #include <vector>
  18. using namespace llvm;
  19. void clang::EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) {
  20. emitSourceFileHeader("A list of commands useable in documentation "
  21. "comments", OS);
  22. OS << "namespace {\n"
  23. "const CommandInfo Commands[] = {\n";
  24. std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command");
  25. for (size_t i = 0, e = Tags.size(); i != e; ++i) {
  26. Record &Tag = *Tags[i];
  27. OS << " { "
  28. << "\"" << Tag.getValueAsString("Name") << "\", "
  29. << "\"" << Tag.getValueAsString("EndCommandName") << "\", "
  30. << i << ", "
  31. << Tag.getValueAsInt("NumArgs") << ", "
  32. << Tag.getValueAsBit("IsInlineCommand") << ", "
  33. << Tag.getValueAsBit("IsBlockCommand") << ", "
  34. << Tag.getValueAsBit("IsBriefCommand") << ", "
  35. << Tag.getValueAsBit("IsReturnsCommand") << ", "
  36. << Tag.getValueAsBit("IsParamCommand") << ", "
  37. << Tag.getValueAsBit("IsTParamCommand") << ", "
  38. << Tag.getValueAsBit("IsThrowsCommand") << ", "
  39. << Tag.getValueAsBit("IsDeprecatedCommand") << ", "
  40. << Tag.getValueAsBit("IsHeaderfileCommand") << ", "
  41. << Tag.getValueAsBit("IsEmptyParagraphAllowed") << ", "
  42. << Tag.getValueAsBit("IsVerbatimBlockCommand") << ", "
  43. << Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", "
  44. << Tag.getValueAsBit("IsVerbatimLineCommand") << ", "
  45. << Tag.getValueAsBit("IsDeclarationCommand") << ", "
  46. << Tag.getValueAsBit("IsFunctionDeclarationCommand") << ", "
  47. << Tag.getValueAsBit("IsRecordLikeDetailCommand") << ", "
  48. << Tag.getValueAsBit("IsRecordLikeDeclarationCommand") << ", "
  49. << /* IsUnknownCommand = */ "0"
  50. << " }";
  51. if (i + 1 != e)
  52. OS << ",";
  53. OS << "\n";
  54. }
  55. OS << "};\n"
  56. "} // unnamed namespace\n\n";
  57. std::vector<StringMatcher::StringPair> Matches;
  58. for (size_t i = 0, e = Tags.size(); i != e; ++i) {
  59. Record &Tag = *Tags[i];
  60. std::string Name = std::string(Tag.getValueAsString("Name"));
  61. std::string Return;
  62. raw_string_ostream(Return) << "return &Commands[" << i << "];";
  63. Matches.emplace_back(std::move(Name), std::move(Return));
  64. }
  65. OS << "const CommandInfo *CommandTraits::getBuiltinCommandInfo(\n"
  66. << " StringRef Name) {\n";
  67. StringMatcher("Name", Matches, OS).Emit();
  68. OS << " return nullptr;\n"
  69. << "}\n\n";
  70. }
  71. static std::string MangleName(StringRef Str) {
  72. std::string Mangled;
  73. for (unsigned i = 0, e = Str.size(); i != e; ++i) {
  74. switch (Str[i]) {
  75. default:
  76. Mangled += Str[i];
  77. break;
  78. case '(':
  79. Mangled += "lparen";
  80. break;
  81. case ')':
  82. Mangled += "rparen";
  83. break;
  84. case '[':
  85. Mangled += "lsquare";
  86. break;
  87. case ']':
  88. Mangled += "rsquare";
  89. break;
  90. case '{':
  91. Mangled += "lbrace";
  92. break;
  93. case '}':
  94. Mangled += "rbrace";
  95. break;
  96. case '$':
  97. Mangled += "dollar";
  98. break;
  99. case '/':
  100. Mangled += "slash";
  101. break;
  102. }
  103. }
  104. return Mangled;
  105. }
  106. void clang::EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS) {
  107. emitSourceFileHeader("A list of commands useable in documentation "
  108. "comments", OS);
  109. OS << "#ifndef COMMENT_COMMAND\n"
  110. << "# define COMMENT_COMMAND(NAME)\n"
  111. << "#endif\n";
  112. std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command");
  113. for (size_t i = 0, e = Tags.size(); i != e; ++i) {
  114. Record &Tag = *Tags[i];
  115. std::string MangledName = MangleName(Tag.getValueAsString("Name"));
  116. OS << "COMMENT_COMMAND(" << MangledName << ")\n";
  117. }
  118. }