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