xref: /minix3/external/bsd/llvm/dist/clang/lib/AST/CommentCommandTraits.cpp (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc //===--- CommentCommandTraits.cpp - Comment command properties --*- C++ -*-===//
2*f4a2713aSLionel Sambuc //
3*f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4*f4a2713aSLionel Sambuc //
5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7*f4a2713aSLionel Sambuc //
8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9*f4a2713aSLionel Sambuc 
10*f4a2713aSLionel Sambuc #include "clang/AST/CommentCommandTraits.h"
11*f4a2713aSLionel Sambuc #include "llvm/ADT/STLExtras.h"
12*f4a2713aSLionel Sambuc 
13*f4a2713aSLionel Sambuc namespace clang {
14*f4a2713aSLionel Sambuc namespace comments {
15*f4a2713aSLionel Sambuc 
16*f4a2713aSLionel Sambuc #include "clang/AST/CommentCommandInfo.inc"
17*f4a2713aSLionel Sambuc 
18*f4a2713aSLionel Sambuc CommandTraits::CommandTraits(llvm::BumpPtrAllocator &Allocator,
19*f4a2713aSLionel Sambuc                              const CommentOptions &CommentOptions) :
20*f4a2713aSLionel Sambuc     NextID(llvm::array_lengthof(Commands)), Allocator(Allocator) {
21*f4a2713aSLionel Sambuc   registerCommentOptions(CommentOptions);
22*f4a2713aSLionel Sambuc }
23*f4a2713aSLionel Sambuc 
24*f4a2713aSLionel Sambuc void CommandTraits::registerCommentOptions(
25*f4a2713aSLionel Sambuc     const CommentOptions &CommentOptions) {
26*f4a2713aSLionel Sambuc   for (CommentOptions::BlockCommandNamesTy::const_iterator
27*f4a2713aSLionel Sambuc            I = CommentOptions.BlockCommandNames.begin(),
28*f4a2713aSLionel Sambuc            E = CommentOptions.BlockCommandNames.end();
29*f4a2713aSLionel Sambuc        I != E; I++) {
30*f4a2713aSLionel Sambuc     registerBlockCommand(*I);
31*f4a2713aSLionel Sambuc   }
32*f4a2713aSLionel Sambuc }
33*f4a2713aSLionel Sambuc 
34*f4a2713aSLionel Sambuc const CommandInfo *CommandTraits::getCommandInfoOrNULL(StringRef Name) const {
35*f4a2713aSLionel Sambuc   if (const CommandInfo *Info = getBuiltinCommandInfo(Name))
36*f4a2713aSLionel Sambuc     return Info;
37*f4a2713aSLionel Sambuc   return getRegisteredCommandInfo(Name);
38*f4a2713aSLionel Sambuc }
39*f4a2713aSLionel Sambuc 
40*f4a2713aSLionel Sambuc const CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const {
41*f4a2713aSLionel Sambuc   if (const CommandInfo *Info = getBuiltinCommandInfo(CommandID))
42*f4a2713aSLionel Sambuc     return Info;
43*f4a2713aSLionel Sambuc   return getRegisteredCommandInfo(CommandID);
44*f4a2713aSLionel Sambuc }
45*f4a2713aSLionel Sambuc 
46*f4a2713aSLionel Sambuc static void
47*f4a2713aSLionel Sambuc HelperTypoCorrectCommandInfo(SmallVectorImpl<const CommandInfo *> &BestCommand,
48*f4a2713aSLionel Sambuc                              StringRef Typo, const CommandInfo *Command) {
49*f4a2713aSLionel Sambuc   const unsigned MaxEditDistance = 1;
50*f4a2713aSLionel Sambuc   unsigned BestEditDistance = MaxEditDistance + 1;
51*f4a2713aSLionel Sambuc   StringRef Name = Command->Name;
52*f4a2713aSLionel Sambuc 
53*f4a2713aSLionel Sambuc   unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size());
54*f4a2713aSLionel Sambuc   if (MinPossibleEditDistance > 0 &&
55*f4a2713aSLionel Sambuc       Typo.size() / MinPossibleEditDistance < 1)
56*f4a2713aSLionel Sambuc     return;
57*f4a2713aSLionel Sambuc   unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance);
58*f4a2713aSLionel Sambuc   if (EditDistance > MaxEditDistance)
59*f4a2713aSLionel Sambuc     return;
60*f4a2713aSLionel Sambuc   if (EditDistance == BestEditDistance)
61*f4a2713aSLionel Sambuc     BestCommand.push_back(Command);
62*f4a2713aSLionel Sambuc   else if (EditDistance < BestEditDistance) {
63*f4a2713aSLionel Sambuc     BestCommand.clear();
64*f4a2713aSLionel Sambuc     BestCommand.push_back(Command);
65*f4a2713aSLionel Sambuc     BestEditDistance = EditDistance;
66*f4a2713aSLionel Sambuc   }
67*f4a2713aSLionel Sambuc }
68*f4a2713aSLionel Sambuc 
69*f4a2713aSLionel Sambuc const CommandInfo *
70*f4a2713aSLionel Sambuc CommandTraits::getTypoCorrectCommandInfo(StringRef Typo) const {
71*f4a2713aSLionel Sambuc   // single character command impostures, such as \t or \n must not go
72*f4a2713aSLionel Sambuc   // through the fixit logic.
73*f4a2713aSLionel Sambuc   if (Typo.size() <= 1)
74*f4a2713aSLionel Sambuc     return NULL;
75*f4a2713aSLionel Sambuc 
76*f4a2713aSLionel Sambuc   SmallVector<const CommandInfo *, 2> BestCommand;
77*f4a2713aSLionel Sambuc 
78*f4a2713aSLionel Sambuc   const int NumOfCommands = llvm::array_lengthof(Commands);
79*f4a2713aSLionel Sambuc   for (int i = 0; i < NumOfCommands; i++)
80*f4a2713aSLionel Sambuc     HelperTypoCorrectCommandInfo(BestCommand, Typo, &Commands[i]);
81*f4a2713aSLionel Sambuc 
82*f4a2713aSLionel Sambuc   for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i)
83*f4a2713aSLionel Sambuc     if (!RegisteredCommands[i]->IsUnknownCommand)
84*f4a2713aSLionel Sambuc       HelperTypoCorrectCommandInfo(BestCommand, Typo, RegisteredCommands[i]);
85*f4a2713aSLionel Sambuc 
86*f4a2713aSLionel Sambuc   return (BestCommand.size() != 1) ? NULL : BestCommand[0];
87*f4a2713aSLionel Sambuc }
88*f4a2713aSLionel Sambuc 
89*f4a2713aSLionel Sambuc CommandInfo *CommandTraits::createCommandInfoWithName(StringRef CommandName) {
90*f4a2713aSLionel Sambuc   char *Name = Allocator.Allocate<char>(CommandName.size() + 1);
91*f4a2713aSLionel Sambuc   memcpy(Name, CommandName.data(), CommandName.size());
92*f4a2713aSLionel Sambuc   Name[CommandName.size()] = '\0';
93*f4a2713aSLionel Sambuc 
94*f4a2713aSLionel Sambuc   // Value-initialize (=zero-initialize in this case) a new CommandInfo.
95*f4a2713aSLionel Sambuc   CommandInfo *Info = new (Allocator) CommandInfo();
96*f4a2713aSLionel Sambuc   Info->Name = Name;
97*f4a2713aSLionel Sambuc   Info->ID = NextID++;
98*f4a2713aSLionel Sambuc 
99*f4a2713aSLionel Sambuc   RegisteredCommands.push_back(Info);
100*f4a2713aSLionel Sambuc 
101*f4a2713aSLionel Sambuc   return Info;
102*f4a2713aSLionel Sambuc }
103*f4a2713aSLionel Sambuc 
104*f4a2713aSLionel Sambuc const CommandInfo *CommandTraits::registerUnknownCommand(
105*f4a2713aSLionel Sambuc                                                   StringRef CommandName) {
106*f4a2713aSLionel Sambuc   CommandInfo *Info = createCommandInfoWithName(CommandName);
107*f4a2713aSLionel Sambuc   Info->IsUnknownCommand = true;
108*f4a2713aSLionel Sambuc   return Info;
109*f4a2713aSLionel Sambuc }
110*f4a2713aSLionel Sambuc 
111*f4a2713aSLionel Sambuc const CommandInfo *CommandTraits::registerBlockCommand(StringRef CommandName) {
112*f4a2713aSLionel Sambuc   CommandInfo *Info = createCommandInfoWithName(CommandName);
113*f4a2713aSLionel Sambuc   Info->IsBlockCommand = true;
114*f4a2713aSLionel Sambuc   return Info;
115*f4a2713aSLionel Sambuc }
116*f4a2713aSLionel Sambuc 
117*f4a2713aSLionel Sambuc const CommandInfo *CommandTraits::getBuiltinCommandInfo(
118*f4a2713aSLionel Sambuc                                                   unsigned CommandID) {
119*f4a2713aSLionel Sambuc   if (CommandID < llvm::array_lengthof(Commands))
120*f4a2713aSLionel Sambuc     return &Commands[CommandID];
121*f4a2713aSLionel Sambuc   return NULL;
122*f4a2713aSLionel Sambuc }
123*f4a2713aSLionel Sambuc 
124*f4a2713aSLionel Sambuc const CommandInfo *CommandTraits::getRegisteredCommandInfo(
125*f4a2713aSLionel Sambuc                                                   StringRef Name) const {
126*f4a2713aSLionel Sambuc   for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) {
127*f4a2713aSLionel Sambuc     if (RegisteredCommands[i]->Name == Name)
128*f4a2713aSLionel Sambuc       return RegisteredCommands[i];
129*f4a2713aSLionel Sambuc   }
130*f4a2713aSLionel Sambuc   return NULL;
131*f4a2713aSLionel Sambuc }
132*f4a2713aSLionel Sambuc 
133*f4a2713aSLionel Sambuc const CommandInfo *CommandTraits::getRegisteredCommandInfo(
134*f4a2713aSLionel Sambuc                                                   unsigned CommandID) const {
135*f4a2713aSLionel Sambuc   return RegisteredCommands[CommandID - llvm::array_lengthof(Commands)];
136*f4a2713aSLionel Sambuc }
137*f4a2713aSLionel Sambuc 
138*f4a2713aSLionel Sambuc } // end namespace comments
139*f4a2713aSLionel Sambuc } // end namespace clang
140*f4a2713aSLionel Sambuc 
141