]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / tools / clang / lib / AST / CommentCommandTraits.cpp
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