clang API Documentation
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