clang API Documentation

CommentCommandTraits.cpp
Go to the documentation of this file.
00001 //===--- CommentCommandTraits.cpp - Comment command properties --*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "clang/AST/CommentCommandTraits.h"
00011 #include "llvm/ADT/STLExtras.h"
00012 
00013 namespace clang {
00014 namespace comments {
00015 
00016 #include "clang/AST/CommentCommandInfo.inc"
00017 
00018 CommandTraits::CommandTraits(llvm::BumpPtrAllocator &Allocator,
00019                              const CommentOptions &CommentOptions) :
00020     NextID(llvm::array_lengthof(Commands)), Allocator(Allocator) {
00021   registerCommentOptions(CommentOptions);
00022 }
00023 
00024 void CommandTraits::registerCommentOptions(
00025     const CommentOptions &CommentOptions) {
00026   for (CommentOptions::BlockCommandNamesTy::const_iterator
00027            I = CommentOptions.BlockCommandNames.begin(),
00028            E = CommentOptions.BlockCommandNames.end();
00029        I != E; I++) {
00030     registerBlockCommand(*I);
00031   }
00032 }
00033 
00034 const CommandInfo *CommandTraits::getCommandInfoOrNULL(StringRef Name) const {
00035   if (const CommandInfo *Info = getBuiltinCommandInfo(Name))
00036     return Info;
00037   return getRegisteredCommandInfo(Name);
00038 }
00039 
00040 const CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const {
00041   if (const CommandInfo *Info = getBuiltinCommandInfo(CommandID))
00042     return Info;
00043   return getRegisteredCommandInfo(CommandID);
00044 }
00045 
00046 const CommandInfo *
00047 CommandTraits::getTypoCorrectCommandInfo(StringRef Typo) const {
00048   // Single-character command impostures, such as \t or \n, should not go
00049   // through the fixit logic.
00050   if (Typo.size() <= 1)
00051     return nullptr;
00052 
00053   // The maximum edit distance we're prepared to accept.
00054   const unsigned MaxEditDistance = 1;
00055 
00056   unsigned BestEditDistance = MaxEditDistance;
00057   SmallVector<const CommandInfo *, 2> BestCommand;
00058 
00059   auto ConsiderCorrection = [&](const CommandInfo *Command) {
00060     StringRef Name = Command->Name;
00061 
00062     unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size());
00063     if (MinPossibleEditDistance <= BestEditDistance) {
00064       unsigned EditDistance = Typo.edit_distance(Name, true, BestEditDistance);
00065       if (EditDistance < BestEditDistance) {
00066         BestEditDistance = EditDistance;
00067         BestCommand.clear();
00068       }
00069       if (EditDistance == BestEditDistance)
00070         BestCommand.push_back(Command);
00071     }
00072   };
00073 
00074   for (const auto &Command : Commands)
00075     ConsiderCorrection(&Command);
00076 
00077   for (const auto *Command : RegisteredCommands)
00078     if (!Command->IsUnknownCommand)
00079       ConsiderCorrection(Command);
00080 
00081   return BestCommand.size() == 1 ? BestCommand[0] : nullptr;
00082 }
00083 
00084 CommandInfo *CommandTraits::createCommandInfoWithName(StringRef CommandName) {
00085   char *Name = Allocator.Allocate<char>(CommandName.size() + 1);
00086   memcpy(Name, CommandName.data(), CommandName.size());
00087   Name[CommandName.size()] = '\0';
00088 
00089   // Value-initialize (=zero-initialize in this case) a new CommandInfo.
00090   CommandInfo *Info = new (Allocator) CommandInfo();
00091   Info->Name = Name;
00092   // We only have a limited number of bits to encode command IDs in the
00093   // CommandInfo structure, so the ID numbers can potentially wrap around.
00094   assert((NextID < (1 << CommandInfo::NumCommandIDBits))
00095          && "Too many commands. We have limited bits for the command ID.");
00096   Info->ID = NextID++;
00097 
00098   RegisteredCommands.push_back(Info);
00099 
00100   return Info;
00101 }
00102 
00103 const CommandInfo *CommandTraits::registerUnknownCommand(
00104                                                   StringRef CommandName) {
00105   CommandInfo *Info = createCommandInfoWithName(CommandName);
00106   Info->IsUnknownCommand = true;
00107   return Info;
00108 }
00109 
00110 const CommandInfo *CommandTraits::registerBlockCommand(StringRef CommandName) {
00111   CommandInfo *Info = createCommandInfoWithName(CommandName);
00112   Info->IsBlockCommand = true;
00113   return Info;
00114 }
00115 
00116 const CommandInfo *CommandTraits::getBuiltinCommandInfo(
00117                                                   unsigned CommandID) {
00118   if (CommandID < llvm::array_lengthof(Commands))
00119     return &Commands[CommandID];
00120   return nullptr;
00121 }
00122 
00123 const CommandInfo *CommandTraits::getRegisteredCommandInfo(
00124                                                   StringRef Name) const {
00125   for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) {
00126     if (RegisteredCommands[i]->Name == Name)
00127       return RegisteredCommands[i];
00128   }
00129   return nullptr;
00130 }
00131 
00132 const CommandInfo *CommandTraits::getRegisteredCommandInfo(
00133                                                   unsigned CommandID) const {
00134   return RegisteredCommands[CommandID - llvm::array_lengthof(Commands)];
00135 }
00136 
00137 } // end namespace comments
00138 } // end namespace clang
00139