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