1aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko//===--- CommentCommandTraits.cpp - Comment command properties --*- C++ -*-===// 2aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko// 3aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko// The LLVM Compiler Infrastructure 4aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko// 5aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko// This file is distributed under the University of Illinois Open Source 6aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko// License. See LICENSE.TXT for details. 7aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko// 8aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko//===----------------------------------------------------------------------===// 9aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko 10aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko#include "clang/AST/CommentCommandTraits.h" 11e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko#include "llvm/ADT/STLExtras.h" 12aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko 13aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenkonamespace clang { 14aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenkonamespace comments { 15aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko 16e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko#include "clang/AST/CommentCommandInfo.inc" 17aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko 186ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri GribenkoCommandTraits::CommandTraits(llvm::BumpPtrAllocator &Allocator, 196ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko const CommentOptions &CommentOptions) : 206ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko NextID(llvm::array_lengthof(Commands)), Allocator(Allocator) { 216ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko registerCommentOptions(CommentOptions); 226ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko} 236ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko 246ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenkovoid CommandTraits::registerCommentOptions( 256ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko const CommentOptions &CommentOptions) { 266ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko for (CommentOptions::BlockCommandNamesTy::const_iterator 276ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko I = CommentOptions.BlockCommandNames.begin(), 286ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko E = CommentOptions.BlockCommandNames.end(); 296ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko I != E; I++) { 306ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko registerBlockCommand(*I); 316ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko } 326ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko} 33aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko 34e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenkoconst CommandInfo *CommandTraits::getCommandInfoOrNULL(StringRef Name) const { 35e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko if (const CommandInfo *Info = getBuiltinCommandInfo(Name)) 36e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko return Info; 37e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko return getRegisteredCommandInfo(Name); 38aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko} 39aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko 40e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenkoconst CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const { 41e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko if (const CommandInfo *Info = getBuiltinCommandInfo(CommandID)) 42e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko return Info; 43e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko return getRegisteredCommandInfo(CommandID); 44e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko} 45aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko 46ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanianstatic void 47ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz JahanianHelperTypoCorrectCommandInfo(SmallVectorImpl<const CommandInfo *> &BestCommand, 48ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian StringRef Typo, const CommandInfo *Command) { 490089bc4ddee6bb309ad25f4c7ad4b7ffe5df4512Fariborz Jahanian const unsigned MaxEditDistance = 1; 500089bc4ddee6bb309ad25f4c7ad4b7ffe5df4512Fariborz Jahanian unsigned BestEditDistance = MaxEditDistance + 1; 51ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian StringRef Name = Command->Name; 52ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian 53ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size()); 54ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian if (MinPossibleEditDistance > 0 && 55ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian Typo.size() / MinPossibleEditDistance < 1) 56ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian return; 57ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance); 58ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian if (EditDistance > MaxEditDistance) 59ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian return; 60ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian if (EditDistance == BestEditDistance) 61ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian BestCommand.push_back(Command); 62ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian else if (EditDistance < BestEditDistance) { 63ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian BestCommand.clear(); 64ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian BestCommand.push_back(Command); 65ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian BestEditDistance = EditDistance; 66ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian } 67ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian} 68ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian 69ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanianconst CommandInfo * 70ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz JahanianCommandTraits::getTypoCorrectCommandInfo(StringRef Typo) const { 71f4030ae4638d1831a2a031f1e33b86de8c5fef28Fariborz Jahanian // single character command impostures, such as \t or \n must not go 72f4030ae4638d1831a2a031f1e33b86de8c5fef28Fariborz Jahanian // through the fixit logic. 73f4030ae4638d1831a2a031f1e33b86de8c5fef28Fariborz Jahanian if (Typo.size() <= 1) 74f4030ae4638d1831a2a031f1e33b86de8c5fef28Fariborz Jahanian return NULL; 75f4030ae4638d1831a2a031f1e33b86de8c5fef28Fariborz Jahanian 760089bc4ddee6bb309ad25f4c7ad4b7ffe5df4512Fariborz Jahanian SmallVector<const CommandInfo *, 2> BestCommand; 770089bc4ddee6bb309ad25f4c7ad4b7ffe5df4512Fariborz Jahanian 78b960232518a1cd79c5f64ab5ef54c88e34660191Craig Topper const int NumOfCommands = llvm::array_lengthof(Commands); 79ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian for (int i = 0; i < NumOfCommands; i++) 80ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian HelperTypoCorrectCommandInfo(BestCommand, Typo, &Commands[i]); 81ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian 82ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) 83ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian if (!RegisteredCommands[i]->IsUnknownCommand) 84ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian HelperTypoCorrectCommandInfo(BestCommand, Typo, RegisteredCommands[i]); 85ad91e5431f2f2d0a32ccdff8c55e7fa921af42bdFariborz Jahanian 860089bc4ddee6bb309ad25f4c7ad4b7ffe5df4512Fariborz Jahanian return (BestCommand.size() != 1) ? NULL : BestCommand[0]; 870089bc4ddee6bb309ad25f4c7ad4b7ffe5df4512Fariborz Jahanian} 880089bc4ddee6bb309ad25f4c7ad4b7ffe5df4512Fariborz Jahanian 896ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri GribenkoCommandInfo *CommandTraits::createCommandInfoWithName(StringRef CommandName) { 90116bb09882bc1c9281cd84dd07496201feb18d18Eli Friedman char *Name = Allocator.Allocate<char>(CommandName.size() + 1); 91e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko memcpy(Name, CommandName.data(), CommandName.size()); 92116bb09882bc1c9281cd84dd07496201feb18d18Eli Friedman Name[CommandName.size()] = '\0'; 93aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko 94e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko // Value-initialize (=zero-initialize in this case) a new CommandInfo. 95e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko CommandInfo *Info = new (Allocator) CommandInfo(); 96e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko Info->Name = Name; 97e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko Info->ID = NextID++; 98aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko 99e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko RegisteredCommands.push_back(Info); 100aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko 101e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko return Info; 102aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko} 103aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko 1046ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenkoconst CommandInfo *CommandTraits::registerUnknownCommand( 1056ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko StringRef CommandName) { 1066ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko CommandInfo *Info = createCommandInfoWithName(CommandName); 1076ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko Info->IsUnknownCommand = true; 1086ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko return Info; 1096ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko} 1106ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko 1116ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenkoconst CommandInfo *CommandTraits::registerBlockCommand(StringRef CommandName) { 1126ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko CommandInfo *Info = createCommandInfoWithName(CommandName); 1136ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko Info->IsBlockCommand = true; 1146ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko return Info; 1156ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko} 1166ebf09130479bc7605aa09a3e6c4dc2ba3513495Dmitri Gribenko 117e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenkoconst CommandInfo *CommandTraits::getBuiltinCommandInfo( 118e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko unsigned CommandID) { 119e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko if (CommandID < llvm::array_lengthof(Commands)) 120e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko return &Commands[CommandID]; 121e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko return NULL; 12262290ae569016345b79d4e11dd93abc300e5a681Dmitri Gribenko} 12362290ae569016345b79d4e11dd93abc300e5a681Dmitri Gribenko 124e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenkoconst CommandInfo *CommandTraits::getRegisteredCommandInfo( 125e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko StringRef Name) const { 126e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) { 127e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko if (RegisteredCommands[i]->Name == Name) 128e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko return RegisteredCommands[i]; 129e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko } 130e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko return NULL; 131aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko} 132aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko 133e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenkoconst CommandInfo *CommandTraits::getRegisteredCommandInfo( 134e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko unsigned CommandID) const { 135e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko return RegisteredCommands[CommandID - llvm::array_lengthof(Commands)]; 136aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko} 137aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko 138aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko} // end namespace comments 139aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko} // end namespace clang 140aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko 141