1f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross//===--- CommentCommandTraits.cpp - Comment command properties --*- C++ -*-===// 2f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross// 3f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross// The LLVM Compiler Infrastructure 4f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross// 5f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross// This file is distributed under the University of Illinois Open Source 6f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross// License. See LICENSE.TXT for details. 7f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross// 8f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross//===----------------------------------------------------------------------===// 9f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross 10f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include "clang/AST/CommentCommandTraits.h" 11f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include "llvm/ADT/STLExtras.h" 12f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross 13f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossnamespace clang { 14f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossnamespace comments { 15f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross 16f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include "clang/AST/CommentCommandInfo.inc" 172db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg 18f45fa6b2853cc32385375a0b63ee39ad6a968869Colin CrossCommandTraits::CommandTraits(llvm::BumpPtrAllocator &Allocator, 19f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross const CommentOptions &CommentOptions) : 20ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme NextID(llvm::array_lengthof(Commands)), Allocator(Allocator) { 21f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross registerCommentOptions(CommentOptions); 226e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme} 23ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme 24635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Lemevoid CommandTraits::registerCommentOptions( 258f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn const CommentOptions &CommentOptions) { 26f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross for (CommentOptions::BlockCommandNamesTy::const_iterator 27f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross I = CommentOptions.BlockCommandNames.begin(), 286e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme E = CommentOptions.BlockCommandNames.end(); 29f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross I != E; I++) { 307dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris registerBlockCommand(*I); 31f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross } 32f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross} 33f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross 34f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossconst CommandInfo *CommandTraits::getCommandInfoOrNULL(StringRef Name) const { 35f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross if (const CommandInfo *Info = getBuiltinCommandInfo(Name)) 36f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross return Info; 379dc117c415d0df0a3acd900709d05deabe975704Elliott Hughes return getRegisteredCommandInfo(Name); 38f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross} 39f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross 40f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossconst CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const { 41f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross if (const CommandInfo *Info = getBuiltinCommandInfo(CommandID)) 42f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross return Info; 43656a6b9e3645bfe2cf073b69cbb9d02832f62c26Alex Ray return getRegisteredCommandInfo(CommandID); 44f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross} 45f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross 466e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Lemeconst CommandInfo * 476e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe LemeCommandTraits::getTypoCorrectCommandInfo(StringRef Typo) const { 486e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme // Single-character command impostures, such as \t or \n, should not go 494db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski // through the fixit logic. 504db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski if (Typo.size() <= 1) 516e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme return nullptr; 52f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross 53f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross // The maximum edit distance we're prepared to accept. 54f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross const unsigned MaxEditDistance = 1; 55f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross 56f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross unsigned BestEditDistance = MaxEditDistance; 57e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme SmallVector<const CommandInfo *, 2> BestCommand; 588fecfdda012928bc2fe6d0e66fd4a4c912946254Felipe Leme 5978f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme auto ConsiderCorrection = [&](const CommandInfo *Command) { 60e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme StringRef Name = Command->Name; 61e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme 62635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size()); 63635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme if (MinPossibleEditDistance <= BestEditDistance) { 642628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme unsigned EditDistance = Typo.edit_distance(Name, true, BestEditDistance); 6571ca15eadd3da0c102a8539f7a88294a94456623Felipe Leme if (EditDistance < BestEditDistance) { 6671ca15eadd3da0c102a8539f7a88294a94456623Felipe Leme BestEditDistance = EditDistance; 6771ca15eadd3da0c102a8539f7a88294a94456623Felipe Leme BestCommand.clear(); 6878f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme } 692a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor if (EditDistance == BestEditDistance) 70ced6078b0e03a75d9b78e61ce25609bd2cb97b1dMark Salyzyn BestCommand.push_back(Command); 712a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor } 728d4cb7ffc11050eebb4d06684e0eb14d9aadacb5Sharvil Nanavati }; 73e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme 74d6ab01105bbd80dfa2fc2debc8e31d6422c378eeMark Salyzyn for (const auto &Command : Commands) 754d42dea08915ccbb61ca05903af5330d02d66755Mark Salyzyn ConsiderCorrection(&Command); 767dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris 777dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris for (const auto *Command : RegisteredCommands) 787dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris if (!Command->IsUnknownCommand) 797dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris ConsiderCorrection(Command); 807dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris 810816520c5cd60519d8e221ed92497aa5464e3039Erik Kline return BestCommand.size() == 1 ? BestCommand[0] : nullptr; 827dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris} 837dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris 847dc7f3221f26b771c266a26ec785eb74287922f1Christopher FerrisCommandInfo *CommandTraits::createCommandInfoWithName(StringRef CommandName) { 857dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris char *Name = Allocator.Allocate<char>(CommandName.size() + 1); 867dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris memcpy(Name, CommandName.data(), CommandName.size()); 877dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris Name[CommandName.size()] = '\0'; 887dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris 897dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris // Value-initialize (=zero-initialize in this case) a new CommandInfo. 9071ca15eadd3da0c102a8539f7a88294a94456623Felipe Leme CommandInfo *Info = new (Allocator) CommandInfo(); 9171ca15eadd3da0c102a8539f7a88294a94456623Felipe Leme Info->Name = Name; 92e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme // We only have a limited number of bits to encode command IDs in the 93809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme // CommandInfo structure, so the ID numbers can potentially wrap around. 94809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme assert((NextID < (1 << CommandInfo::NumCommandIDBits)) 95809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme && "Too many commands. We have limited bits for the command ID."); 96809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme Info->ID = NextID++; 97809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme 98ca9c12e64d44f6c67cd46819583239f0ad051a51Felipe Leme RegisteredCommands.push_back(Info); 99809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme 100249beee359da256f7c41c481d45c06765b6a1d8aCalvin On return Info; 101c4eee56dab06a7de1db18327f8d4831f89d1d640Felipe Leme} 102c4eee56dab06a7de1db18327f8d4831f89d1d640Felipe Leme 103c4eee56dab06a7de1db18327f8d4831f89d1d640Felipe Lemeconst CommandInfo *CommandTraits::registerUnknownCommand( 104e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme StringRef CommandName) { 105e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme CommandInfo *Info = createCommandInfoWithName(CommandName); 1067dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris Info->IsUnknownCommand = true; 107e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme return Info; 1087dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris} 1097dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris 11054bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferrisconst CommandInfo *CommandTraits::registerBlockCommand(StringRef CommandName) { 11154bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris CommandInfo *Info = createCommandInfoWithName(CommandName); 1127dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris Info->IsBlockCommand = true; 1137dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris return Info; 114e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme} 115e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme 1167dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferrisconst CommandInfo *CommandTraits::getBuiltinCommandInfo( 117e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme unsigned CommandID) { 1187dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris if (CommandID < llvm::array_lengthof(Commands)) 1197dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris return &Commands[CommandID]; 1207dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris return nullptr; 1217dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris} 1227dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris 123635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Lemeconst CommandInfo *CommandTraits::getRegisteredCommandInfo( 124635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme StringRef Name) const { 125635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) { 126635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme if (RegisteredCommands[i]->Name == Name) 127635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme return RegisteredCommands[i]; 128635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme } 129f0922cc1786c0c2fbf44c10b0005243ecbb4227dNick Kralevich return nullptr; 130635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme} 131635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme 132635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Lemeconst CommandInfo *CommandTraits::getRegisteredCommandInfo( 133cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme unsigned CommandID) const { 134635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme return RegisteredCommands[CommandID - llvm::array_lengthof(Commands)]; 135635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme} 136635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme 137635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme} // end namespace comments 138635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme} // end namespace clang 139635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme 140f0922cc1786c0c2fbf44c10b0005243ecbb4227dNick Kralevich