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 13 namespace clang { 14 namespace comments { 15 16 #include "clang/AST/CommentCommandInfo.inc" 17 18 CommandTraits::CommandTraits(llvm::BumpPtrAllocator &Allocator, 19 const CommentOptions &CommentOptions) : 20 NextID(llvm::array_lengthof(Commands)), Allocator(Allocator) { 21 registerCommentOptions(CommentOptions); 22 } 23 24 void 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 34 const CommandInfo *CommandTraits::getCommandInfoOrNULL(StringRef Name) const { 35 if (const CommandInfo *Info = getBuiltinCommandInfo(Name)) 36 return Info; 37 return getRegisteredCommandInfo(Name); 38 } 39 40 const CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const { 41 if (const CommandInfo *Info = getBuiltinCommandInfo(CommandID)) 42 return Info; 43 return getRegisteredCommandInfo(CommandID); 44 } 45 46 static void 47 HelperTypoCorrectCommandInfo(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 69 const CommandInfo * 70 CommandTraits::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 89 CommandInfo *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 104 const CommandInfo *CommandTraits::registerUnknownCommand( 105 StringRef CommandName) { 106 CommandInfo *Info = createCommandInfoWithName(CommandName); 107 Info->IsUnknownCommand = true; 108 return Info; 109 } 110 111 const CommandInfo *CommandTraits::registerBlockCommand(StringRef CommandName) { 112 CommandInfo *Info = createCommandInfoWithName(CommandName); 113 Info->IsBlockCommand = true; 114 return Info; 115 } 116 117 const CommandInfo *CommandTraits::getBuiltinCommandInfo( 118 unsigned CommandID) { 119 if (CommandID < llvm::array_lengthof(Commands)) 120 return &Commands[CommandID]; 121 return NULL; 122 } 123 124 const 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 133 const 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