1239313Sdim//===--- CommentCommandTraits.cpp - Comment command properties --*- C++ -*-===// 2239313Sdim// 3239313Sdim// The LLVM Compiler Infrastructure 4239313Sdim// 5239313Sdim// This file is distributed under the University of Illinois Open Source 6239313Sdim// License. See LICENSE.TXT for details. 7239313Sdim// 8239313Sdim//===----------------------------------------------------------------------===// 9239313Sdim 10239313Sdim#include "clang/AST/CommentCommandTraits.h" 11245431Sdim#include "llvm/ADT/STLExtras.h" 12239313Sdim 13239313Sdimnamespace clang { 14239313Sdimnamespace comments { 15239313Sdim 16245431Sdim#include "clang/AST/CommentCommandInfo.inc" 17239313Sdim 18252723SdimCommandTraits::CommandTraits(llvm::BumpPtrAllocator &Allocator, 19252723Sdim const CommentOptions &CommentOptions) : 20252723Sdim NextID(llvm::array_lengthof(Commands)), Allocator(Allocator) { 21252723Sdim registerCommentOptions(CommentOptions); 22252723Sdim} 23239313Sdim 24252723Sdimvoid CommandTraits::registerCommentOptions( 25252723Sdim const CommentOptions &CommentOptions) { 26252723Sdim for (CommentOptions::BlockCommandNamesTy::const_iterator 27252723Sdim I = CommentOptions.BlockCommandNames.begin(), 28252723Sdim E = CommentOptions.BlockCommandNames.end(); 29252723Sdim I != E; I++) { 30252723Sdim registerBlockCommand(*I); 31252723Sdim } 32252723Sdim} 33252723Sdim 34245431Sdimconst CommandInfo *CommandTraits::getCommandInfoOrNULL(StringRef Name) const { 35245431Sdim if (const CommandInfo *Info = getBuiltinCommandInfo(Name)) 36245431Sdim return Info; 37245431Sdim return getRegisteredCommandInfo(Name); 38245431Sdim} 39239313Sdim 40245431Sdimconst CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const { 41245431Sdim if (const CommandInfo *Info = getBuiltinCommandInfo(CommandID)) 42245431Sdim return Info; 43245431Sdim return getRegisteredCommandInfo(CommandID); 44239313Sdim} 45239313Sdim 46263509Sdimstatic void 47263509SdimHelperTypoCorrectCommandInfo(SmallVectorImpl<const CommandInfo *> &BestCommand, 48263509Sdim StringRef Typo, const CommandInfo *Command) { 49263509Sdim const unsigned MaxEditDistance = 1; 50263509Sdim unsigned BestEditDistance = MaxEditDistance + 1; 51263509Sdim StringRef Name = Command->Name; 52263509Sdim 53263509Sdim unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size()); 54263509Sdim if (MinPossibleEditDistance > 0 && 55263509Sdim Typo.size() / MinPossibleEditDistance < 1) 56263509Sdim return; 57263509Sdim unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance); 58263509Sdim if (EditDistance > MaxEditDistance) 59263509Sdim return; 60263509Sdim if (EditDistance == BestEditDistance) 61263509Sdim BestCommand.push_back(Command); 62263509Sdim else if (EditDistance < BestEditDistance) { 63263509Sdim BestCommand.clear(); 64263509Sdim BestCommand.push_back(Command); 65263509Sdim BestEditDistance = EditDistance; 66263509Sdim } 67263509Sdim} 68263509Sdim 69263509Sdimconst CommandInfo * 70263509SdimCommandTraits::getTypoCorrectCommandInfo(StringRef Typo) const { 71263509Sdim // single character command impostures, such as \t or \n must not go 72263509Sdim // through the fixit logic. 73263509Sdim if (Typo.size() <= 1) 74263509Sdim return NULL; 75263509Sdim 76263509Sdim SmallVector<const CommandInfo *, 2> BestCommand; 77263509Sdim 78263509Sdim const int NumOfCommands = llvm::array_lengthof(Commands); 79263509Sdim for (int i = 0; i < NumOfCommands; i++) 80263509Sdim HelperTypoCorrectCommandInfo(BestCommand, Typo, &Commands[i]); 81263509Sdim 82263509Sdim for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) 83263509Sdim if (!RegisteredCommands[i]->IsUnknownCommand) 84263509Sdim HelperTypoCorrectCommandInfo(BestCommand, Typo, RegisteredCommands[i]); 85263509Sdim 86263509Sdim return (BestCommand.size() != 1) ? NULL : BestCommand[0]; 87263509Sdim} 88263509Sdim 89252723SdimCommandInfo *CommandTraits::createCommandInfoWithName(StringRef CommandName) { 90245431Sdim char *Name = Allocator.Allocate<char>(CommandName.size() + 1); 91245431Sdim memcpy(Name, CommandName.data(), CommandName.size()); 92245431Sdim Name[CommandName.size()] = '\0'; 93239313Sdim 94245431Sdim // Value-initialize (=zero-initialize in this case) a new CommandInfo. 95245431Sdim CommandInfo *Info = new (Allocator) CommandInfo(); 96245431Sdim Info->Name = Name; 97245431Sdim Info->ID = NextID++; 98239313Sdim 99245431Sdim RegisteredCommands.push_back(Info); 100239313Sdim 101245431Sdim return Info; 102239313Sdim} 103239313Sdim 104252723Sdimconst CommandInfo *CommandTraits::registerUnknownCommand( 105252723Sdim StringRef CommandName) { 106252723Sdim CommandInfo *Info = createCommandInfoWithName(CommandName); 107252723Sdim Info->IsUnknownCommand = true; 108252723Sdim return Info; 109252723Sdim} 110252723Sdim 111252723Sdimconst CommandInfo *CommandTraits::registerBlockCommand(StringRef CommandName) { 112252723Sdim CommandInfo *Info = createCommandInfoWithName(CommandName); 113252723Sdim Info->IsBlockCommand = true; 114252723Sdim return Info; 115252723Sdim} 116252723Sdim 117245431Sdimconst CommandInfo *CommandTraits::getBuiltinCommandInfo( 118245431Sdim unsigned CommandID) { 119245431Sdim if (CommandID < llvm::array_lengthof(Commands)) 120245431Sdim return &Commands[CommandID]; 121245431Sdim return NULL; 122239313Sdim} 123239313Sdim 124245431Sdimconst CommandInfo *CommandTraits::getRegisteredCommandInfo( 125245431Sdim StringRef Name) const { 126245431Sdim for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) { 127245431Sdim if (RegisteredCommands[i]->Name == Name) 128245431Sdim return RegisteredCommands[i]; 129245431Sdim } 130245431Sdim return NULL; 131239313Sdim} 132239313Sdim 133245431Sdimconst CommandInfo *CommandTraits::getRegisteredCommandInfo( 134245431Sdim unsigned CommandID) const { 135245431Sdim return RegisteredCommands[CommandID - llvm::array_lengthof(Commands)]; 136239313Sdim} 137239313Sdim 138239313Sdim} // end namespace comments 139239313Sdim} // end namespace clang 140239313Sdim 141