CommentCommandTraits.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. #include "clang/AST/CommentCommandTraits.h"
  10. #include "llvm/ADT/STLExtras.h"
  11. namespace clang {
  12. namespace comments {
  13. #include "clang/AST/CommentCommandInfo.inc"
  14. CommandTraits::CommandTraits(llvm::BumpPtrAllocator &Allocator,
  15. const CommentOptions &CommentOptions) :
  16. NextID(llvm::array_lengthof(Commands)), Allocator(Allocator) {
  17. registerCommentOptions(CommentOptions);
  18. }
  19. void CommandTraits::registerCommentOptions(
  20. const CommentOptions &CommentOptions) {
  21. for (CommentOptions::BlockCommandNamesTy::const_iterator
  22. I = CommentOptions.BlockCommandNames.begin(),
  23. E = CommentOptions.BlockCommandNames.end();
  24. I != E; I++) {
  25. registerBlockCommand(*I);
  26. }
  27. }
  28. const CommandInfo *CommandTraits::getCommandInfoOrNULL(StringRef Name) const {
  29. if (const CommandInfo *Info = getBuiltinCommandInfo(Name))
  30. return Info;
  31. return getRegisteredCommandInfo(Name);
  32. }
  33. const CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const {
  34. if (const CommandInfo *Info = getBuiltinCommandInfo(CommandID))
  35. return Info;
  36. return getRegisteredCommandInfo(CommandID);
  37. }
  38. static void
  39. HelperTypoCorrectCommandInfo(SmallVectorImpl<const CommandInfo *> &BestCommand,
  40. StringRef Typo, const CommandInfo *Command) {
  41. const unsigned MaxEditDistance = 1;
  42. unsigned BestEditDistance = MaxEditDistance + 1;
  43. StringRef Name = Command->Name;
  44. unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size());
  45. if (MinPossibleEditDistance > 0 &&
  46. Typo.size() / MinPossibleEditDistance < 1)
  47. return;
  48. unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance);
  49. if (EditDistance > MaxEditDistance)
  50. return;
  51. if (EditDistance == BestEditDistance)
  52. BestCommand.push_back(Command);
  53. else if (EditDistance < BestEditDistance) {
  54. BestCommand.clear();
  55. BestCommand.push_back(Command);
  56. BestEditDistance = EditDistance;
  57. }
  58. }
  59. const CommandInfo *
  60. CommandTraits::getTypoCorrectCommandInfo(StringRef Typo) const {
  61. SmallVector<const CommandInfo *, 2> BestCommand;
  62. int NumOfCommands = sizeof(Commands) / sizeof(CommandInfo);
  63. for (int i = 0; i < NumOfCommands; i++)
  64. HelperTypoCorrectCommandInfo(BestCommand, Typo, &Commands[i]);
  65. for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i)
  66. if (!RegisteredCommands[i]->IsUnknownCommand)
  67. HelperTypoCorrectCommandInfo(BestCommand, Typo, RegisteredCommands[i]);
  68. return (BestCommand.size() != 1) ? NULL : BestCommand[0];
  69. }
  70. CommandInfo *CommandTraits::createCommandInfoWithName(StringRef CommandName) {
  71. char *Name = Allocator.Allocate<char>(CommandName.size() + 1);
  72. memcpy(Name, CommandName.data(), CommandName.size());
  73. Name[CommandName.size()] = '\0';
  74. // Value-initialize (=zero-initialize in this case) a new CommandInfo.
  75. CommandInfo *Info = new (Allocator) CommandInfo();
  76. Info->Name = Name;
  77. Info->ID = NextID++;
  78. RegisteredCommands.push_back(Info);
  79. return Info;
  80. }
  81. const CommandInfo *CommandTraits::registerUnknownCommand(
  82. StringRef CommandName) {
  83. CommandInfo *Info = createCommandInfoWithName(CommandName);
  84. Info->IsUnknownCommand = true;
  85. return Info;
  86. }
  87. const CommandInfo *CommandTraits::registerBlockCommand(StringRef CommandName) {
  88. CommandInfo *Info = createCommandInfoWithName(CommandName);
  89. Info->IsBlockCommand = true;
  90. return Info;
  91. }
  92. const CommandInfo *CommandTraits::getBuiltinCommandInfo(
  93. unsigned CommandID) {
  94. if (CommandID < llvm::array_lengthof(Commands))
  95. return &Commands[CommandID];
  96. return NULL;
  97. }
  98. const CommandInfo *CommandTraits::getRegisteredCommandInfo(
  99. StringRef Name) const {
  100. for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) {
  101. if (RegisteredCommands[i]->Name == Name)
  102. return RegisteredCommands[i];
  103. }
  104. return NULL;
  105. }
  106. const CommandInfo *CommandTraits::getRegisteredCommandInfo(
  107. unsigned CommandID) const {
  108. return RegisteredCommands[CommandID - llvm::array_lengthof(Commands)];
  109. }
  110. } // end namespace comments
  111. } // end namespace clang