xref: /minix3/external/bsd/llvm/dist/clang/lib/AST/CommentCommandTraits.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===--- CommentCommandTraits.cpp - Comment command properties --*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc 
10f4a2713aSLionel Sambuc #include "clang/AST/CommentCommandTraits.h"
11f4a2713aSLionel Sambuc #include "llvm/ADT/STLExtras.h"
12f4a2713aSLionel Sambuc 
13f4a2713aSLionel Sambuc namespace clang {
14f4a2713aSLionel Sambuc namespace comments {
15f4a2713aSLionel Sambuc 
16f4a2713aSLionel Sambuc #include "clang/AST/CommentCommandInfo.inc"
17f4a2713aSLionel Sambuc 
CommandTraits(llvm::BumpPtrAllocator & Allocator,const CommentOptions & CommentOptions)18f4a2713aSLionel Sambuc CommandTraits::CommandTraits(llvm::BumpPtrAllocator &Allocator,
19f4a2713aSLionel Sambuc                              const CommentOptions &CommentOptions) :
20f4a2713aSLionel Sambuc     NextID(llvm::array_lengthof(Commands)), Allocator(Allocator) {
21f4a2713aSLionel Sambuc   registerCommentOptions(CommentOptions);
22f4a2713aSLionel Sambuc }
23f4a2713aSLionel Sambuc 
registerCommentOptions(const CommentOptions & CommentOptions)24f4a2713aSLionel Sambuc void CommandTraits::registerCommentOptions(
25f4a2713aSLionel Sambuc     const CommentOptions &CommentOptions) {
26f4a2713aSLionel Sambuc   for (CommentOptions::BlockCommandNamesTy::const_iterator
27f4a2713aSLionel Sambuc            I = CommentOptions.BlockCommandNames.begin(),
28f4a2713aSLionel Sambuc            E = CommentOptions.BlockCommandNames.end();
29f4a2713aSLionel Sambuc        I != E; I++) {
30f4a2713aSLionel Sambuc     registerBlockCommand(*I);
31f4a2713aSLionel Sambuc   }
32f4a2713aSLionel Sambuc }
33f4a2713aSLionel Sambuc 
getCommandInfoOrNULL(StringRef Name) const34f4a2713aSLionel Sambuc const CommandInfo *CommandTraits::getCommandInfoOrNULL(StringRef Name) const {
35f4a2713aSLionel Sambuc   if (const CommandInfo *Info = getBuiltinCommandInfo(Name))
36f4a2713aSLionel Sambuc     return Info;
37f4a2713aSLionel Sambuc   return getRegisteredCommandInfo(Name);
38f4a2713aSLionel Sambuc }
39f4a2713aSLionel Sambuc 
getCommandInfo(unsigned CommandID) const40f4a2713aSLionel Sambuc const CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const {
41f4a2713aSLionel Sambuc   if (const CommandInfo *Info = getBuiltinCommandInfo(CommandID))
42f4a2713aSLionel Sambuc     return Info;
43f4a2713aSLionel Sambuc   return getRegisteredCommandInfo(CommandID);
44f4a2713aSLionel Sambuc }
45f4a2713aSLionel Sambuc 
46*0a6a1f1dSLionel Sambuc const CommandInfo *
getTypoCorrectCommandInfo(StringRef Typo) const47*0a6a1f1dSLionel Sambuc CommandTraits::getTypoCorrectCommandInfo(StringRef Typo) const {
48*0a6a1f1dSLionel Sambuc   // Single-character command impostures, such as \t or \n, should not go
49*0a6a1f1dSLionel Sambuc   // through the fixit logic.
50*0a6a1f1dSLionel Sambuc   if (Typo.size() <= 1)
51*0a6a1f1dSLionel Sambuc     return nullptr;
52*0a6a1f1dSLionel Sambuc 
53*0a6a1f1dSLionel Sambuc   // The maximum edit distance we're prepared to accept.
54f4a2713aSLionel Sambuc   const unsigned MaxEditDistance = 1;
55*0a6a1f1dSLionel Sambuc 
56*0a6a1f1dSLionel Sambuc   unsigned BestEditDistance = MaxEditDistance;
57*0a6a1f1dSLionel Sambuc   SmallVector<const CommandInfo *, 2> BestCommand;
58*0a6a1f1dSLionel Sambuc 
59*0a6a1f1dSLionel Sambuc   auto ConsiderCorrection = [&](const CommandInfo *Command) {
60f4a2713aSLionel Sambuc     StringRef Name = Command->Name;
61f4a2713aSLionel Sambuc 
62f4a2713aSLionel Sambuc     unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size());
63*0a6a1f1dSLionel Sambuc     if (MinPossibleEditDistance <= BestEditDistance) {
64*0a6a1f1dSLionel Sambuc       unsigned EditDistance = Typo.edit_distance(Name, true, BestEditDistance);
65*0a6a1f1dSLionel Sambuc       if (EditDistance < BestEditDistance) {
66*0a6a1f1dSLionel Sambuc         BestEditDistance = EditDistance;
67*0a6a1f1dSLionel Sambuc         BestCommand.clear();
68*0a6a1f1dSLionel Sambuc       }
69f4a2713aSLionel Sambuc       if (EditDistance == BestEditDistance)
70f4a2713aSLionel Sambuc         BestCommand.push_back(Command);
71f4a2713aSLionel Sambuc     }
72*0a6a1f1dSLionel Sambuc   };
73f4a2713aSLionel Sambuc 
74*0a6a1f1dSLionel Sambuc   for (const auto &Command : Commands)
75*0a6a1f1dSLionel Sambuc     ConsiderCorrection(&Command);
76f4a2713aSLionel Sambuc 
77*0a6a1f1dSLionel Sambuc   for (const auto *Command : RegisteredCommands)
78*0a6a1f1dSLionel Sambuc     if (!Command->IsUnknownCommand)
79*0a6a1f1dSLionel Sambuc       ConsiderCorrection(Command);
80f4a2713aSLionel Sambuc 
81*0a6a1f1dSLionel Sambuc   return BestCommand.size() == 1 ? BestCommand[0] : nullptr;
82f4a2713aSLionel Sambuc }
83f4a2713aSLionel Sambuc 
createCommandInfoWithName(StringRef CommandName)84f4a2713aSLionel Sambuc CommandInfo *CommandTraits::createCommandInfoWithName(StringRef CommandName) {
85f4a2713aSLionel Sambuc   char *Name = Allocator.Allocate<char>(CommandName.size() + 1);
86f4a2713aSLionel Sambuc   memcpy(Name, CommandName.data(), CommandName.size());
87f4a2713aSLionel Sambuc   Name[CommandName.size()] = '\0';
88f4a2713aSLionel Sambuc 
89f4a2713aSLionel Sambuc   // Value-initialize (=zero-initialize in this case) a new CommandInfo.
90f4a2713aSLionel Sambuc   CommandInfo *Info = new (Allocator) CommandInfo();
91f4a2713aSLionel Sambuc   Info->Name = Name;
92*0a6a1f1dSLionel Sambuc   // We only have a limited number of bits to encode command IDs in the
93*0a6a1f1dSLionel Sambuc   // CommandInfo structure, so the ID numbers can potentially wrap around.
94*0a6a1f1dSLionel Sambuc   assert((NextID < (1 << CommandInfo::NumCommandIDBits))
95*0a6a1f1dSLionel Sambuc          && "Too many commands. We have limited bits for the command ID.");
96f4a2713aSLionel Sambuc   Info->ID = NextID++;
97f4a2713aSLionel Sambuc 
98f4a2713aSLionel Sambuc   RegisteredCommands.push_back(Info);
99f4a2713aSLionel Sambuc 
100f4a2713aSLionel Sambuc   return Info;
101f4a2713aSLionel Sambuc }
102f4a2713aSLionel Sambuc 
registerUnknownCommand(StringRef CommandName)103f4a2713aSLionel Sambuc const CommandInfo *CommandTraits::registerUnknownCommand(
104f4a2713aSLionel Sambuc                                                   StringRef CommandName) {
105f4a2713aSLionel Sambuc   CommandInfo *Info = createCommandInfoWithName(CommandName);
106f4a2713aSLionel Sambuc   Info->IsUnknownCommand = true;
107f4a2713aSLionel Sambuc   return Info;
108f4a2713aSLionel Sambuc }
109f4a2713aSLionel Sambuc 
registerBlockCommand(StringRef CommandName)110f4a2713aSLionel Sambuc const CommandInfo *CommandTraits::registerBlockCommand(StringRef CommandName) {
111f4a2713aSLionel Sambuc   CommandInfo *Info = createCommandInfoWithName(CommandName);
112f4a2713aSLionel Sambuc   Info->IsBlockCommand = true;
113f4a2713aSLionel Sambuc   return Info;
114f4a2713aSLionel Sambuc }
115f4a2713aSLionel Sambuc 
getBuiltinCommandInfo(unsigned CommandID)116f4a2713aSLionel Sambuc const CommandInfo *CommandTraits::getBuiltinCommandInfo(
117f4a2713aSLionel Sambuc                                                   unsigned CommandID) {
118f4a2713aSLionel Sambuc   if (CommandID < llvm::array_lengthof(Commands))
119f4a2713aSLionel Sambuc     return &Commands[CommandID];
120*0a6a1f1dSLionel Sambuc   return nullptr;
121f4a2713aSLionel Sambuc }
122f4a2713aSLionel Sambuc 
getRegisteredCommandInfo(StringRef Name) const123f4a2713aSLionel Sambuc const CommandInfo *CommandTraits::getRegisteredCommandInfo(
124f4a2713aSLionel Sambuc                                                   StringRef Name) const {
125f4a2713aSLionel Sambuc   for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) {
126f4a2713aSLionel Sambuc     if (RegisteredCommands[i]->Name == Name)
127f4a2713aSLionel Sambuc       return RegisteredCommands[i];
128f4a2713aSLionel Sambuc   }
129*0a6a1f1dSLionel Sambuc   return nullptr;
130f4a2713aSLionel Sambuc }
131f4a2713aSLionel Sambuc 
getRegisteredCommandInfo(unsigned CommandID) const132f4a2713aSLionel Sambuc const CommandInfo *CommandTraits::getRegisteredCommandInfo(
133f4a2713aSLionel Sambuc                                                   unsigned CommandID) const {
134f4a2713aSLionel Sambuc   return RegisteredCommands[CommandID - llvm::array_lengthof(Commands)];
135f4a2713aSLionel Sambuc }
136f4a2713aSLionel Sambuc 
137f4a2713aSLionel Sambuc } // end namespace comments
138f4a2713aSLionel Sambuc } // end namespace clang
139f4a2713aSLionel Sambuc 
140