blob: 1193e0404a0ffa21256b18be592aee55c5b0ef71 [file] [log] [blame]
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +00001//===--- CommentSema.cpp - Doxygen comment semantic analysis --------------===//
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/CommentSema.h"
11#include "llvm/ADT/StringSwitch.h"
12
13namespace clang {
14namespace comments {
15
16Sema::Sema(llvm::BumpPtrAllocator &Allocator) :
17 Allocator(Allocator) {
18}
19
20ParagraphComment *Sema::actOnParagraphComment(
21 ArrayRef<InlineContentComment *> Content) {
22 return new (Allocator) ParagraphComment(Content);
23}
24
25BlockCommandComment *Sema::actOnBlockCommandStart(SourceLocation LocBegin,
26 SourceLocation LocEnd,
27 StringRef Name) {
28 return new (Allocator) BlockCommandComment(LocBegin, LocEnd, Name);
29}
30
31BlockCommandComment *Sema::actOnBlockCommandArgs(
32 BlockCommandComment *Command,
33 ArrayRef<BlockCommandComment::Argument> Args) {
34 Command->setArgs(Args);
35 return Command;
36}
37
38BlockCommandComment *Sema::actOnBlockCommandFinish(
39 BlockCommandComment *Command,
40 ParagraphComment *Paragraph) {
41 Command->setParagraph(Paragraph);
42 return Command;
43}
44
45ParamCommandComment *Sema::actOnParamCommandStart(SourceLocation LocBegin,
46 SourceLocation LocEnd,
47 StringRef Name) {
48 return new (Allocator) ParamCommandComment(LocBegin, LocEnd, Name);
49}
50
51ParamCommandComment *Sema::actOnParamCommandArg(ParamCommandComment *Command,
52 SourceLocation ArgLocBegin,
53 SourceLocation ArgLocEnd,
54 StringRef Arg,
55 bool IsDirection) {
56 if (IsDirection) {
57 ParamCommandComment::PassDirection Direction;
58 std::string ArgLower = Arg.lower();
59 // TODO: optimize: lower Name first (need an API in SmallString for that),
60 // after that StringSwitch.
61 if (ArgLower == "[in]")
62 Direction = ParamCommandComment::In;
63 else if (ArgLower == "[out]")
64 Direction = ParamCommandComment::Out;
65 else if (ArgLower == "[in,out]" || ArgLower == "[out,in]")
66 Direction = ParamCommandComment::InOut;
67 else {
68 // Remove spaces.
69 std::string::iterator O = ArgLower.begin();
70 for (std::string::iterator I = ArgLower.begin(), E = ArgLower.end();
71 I != E; ++I) {
72 const char C = *I;
73 if (C != ' ' && C != '\n' && C != '\r' &&
74 C != '\t' && C != '\v' && C != '\f')
75 *O++ = C;
76 }
77 ArgLower.resize(O - ArgLower.begin());
78
79 bool RemovingWhitespaceHelped = false;
80 if (ArgLower == "[in]") {
81 Direction = ParamCommandComment::In;
82 RemovingWhitespaceHelped = true;
83 } else if (ArgLower == "[out]") {
84 Direction = ParamCommandComment::Out;
85 RemovingWhitespaceHelped = true;
86 } else if (ArgLower == "[in,out]" || ArgLower == "[out,in]") {
87 Direction = ParamCommandComment::InOut;
88 RemovingWhitespaceHelped = true;
89 } else {
90 Direction = ParamCommandComment::In;
91 RemovingWhitespaceHelped = false;
92 }
93 // Diag() unrecognized parameter passing direction, valid directions are ...
94 // if (RemovingWhitespaceHelped) FixIt
95 }
96 Command->setDirection(Direction, /* Explicit = */ true);
97 } else {
98 if (Command->getArgCount() == 0) {
99 if (!Command->isDirectionExplicit()) {
100 // User didn't provide a direction argument.
101 Command->setDirection(ParamCommandComment::In, /* Explicit = */ false);
102 }
103 typedef BlockCommandComment::Argument Argument;
104 Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
105 ArgLocEnd),
106 Arg);
107 Command->setArgs(llvm::makeArrayRef(A, 1));
108 // if (...) Diag() unrecognized parameter name
109 } else {
110 // Diag() \\param command requires at most 2 arguments
111 }
112 }
113 return Command;
114}
115
116ParamCommandComment *Sema::actOnParamCommandFinish(ParamCommandComment *Command,
117 ParagraphComment *Paragraph) {
118 Command->setParagraph(Paragraph);
119 return Command;
120}
121
122InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
123 SourceLocation CommandLocEnd,
124 StringRef CommandName) {
125 ArrayRef<InlineCommandComment::Argument> Args;
126 return new (Allocator) InlineCommandComment(CommandLocBegin,
127 CommandLocEnd,
128 CommandName,
129 Args);
130}
131
132InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
133 SourceLocation CommandLocEnd,
134 StringRef CommandName,
135 SourceLocation ArgLocBegin,
136 SourceLocation ArgLocEnd,
137 StringRef Arg) {
138 typedef InlineCommandComment::Argument Argument;
139 Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
140 ArgLocEnd),
141 Arg);
142
143 return new (Allocator) InlineCommandComment(CommandLocBegin,
144 CommandLocEnd,
145 CommandName,
146 llvm::makeArrayRef(A, 1));
147}
148
149InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin,
150 SourceLocation LocEnd,
151 StringRef Name) {
152 ArrayRef<InlineCommandComment::Argument> Args;
153 return new (Allocator) InlineCommandComment(LocBegin, LocEnd, Name, Args);
154}
155
156TextComment *Sema::actOnText(SourceLocation LocBegin,
157 SourceLocation LocEnd,
158 StringRef Text) {
159 return new (Allocator) TextComment(LocBegin, LocEnd, Text);
160}
161
162VerbatimBlockComment *Sema::actOnVerbatimBlockStart(SourceLocation Loc,
163 StringRef Name) {
164 return new (Allocator) VerbatimBlockComment(
165 Loc,
166 Loc.getLocWithOffset(1 + Name.size()),
167 Name);
168}
169
170VerbatimBlockLineComment *Sema::actOnVerbatimBlockLine(SourceLocation Loc,
171 StringRef Text) {
172 return new (Allocator) VerbatimBlockLineComment(Loc, Text);
173}
174
175VerbatimBlockComment *Sema::actOnVerbatimBlockFinish(
176 VerbatimBlockComment *Block,
177 SourceLocation CloseNameLocBegin,
178 StringRef CloseName,
179 ArrayRef<VerbatimBlockLineComment *> Lines) {
180 Block->setCloseName(CloseName, CloseNameLocBegin);
181 Block->setLines(Lines);
182 return Block;
183}
184
185VerbatimLineComment *Sema::actOnVerbatimLine(SourceLocation LocBegin,
186 StringRef Name,
187 SourceLocation TextBegin,
188 StringRef Text) {
189 return new (Allocator) VerbatimLineComment(
190 LocBegin,
191 TextBegin.getLocWithOffset(Text.size()),
192 Name,
193 TextBegin,
194 Text);
195}
196
197HTMLOpenTagComment *Sema::actOnHTMLOpenTagStart(SourceLocation LocBegin,
198 StringRef TagName) {
199 return new (Allocator) HTMLOpenTagComment(LocBegin, TagName);
200}
201
202HTMLOpenTagComment *Sema::actOnHTMLOpenTagFinish(
203 HTMLOpenTagComment *Tag,
204 ArrayRef<HTMLOpenTagComment::Attribute> Attrs,
205 SourceLocation GreaterLoc) {
206 Tag->setAttrs(Attrs);
207 Tag->setGreaterLoc(GreaterLoc);
208 return Tag;
209}
210
211HTMLCloseTagComment *Sema::actOnHTMLCloseTag(SourceLocation LocBegin,
212 SourceLocation LocEnd,
213 StringRef TagName) {
214 return new (Allocator) HTMLCloseTagComment(LocBegin, LocEnd, TagName);
215}
216
217FullComment *Sema::actOnFullComment(
218 ArrayRef<BlockContentComment *> Blocks) {
219 return new (Allocator) FullComment(Blocks);
220}
221
222// TODO: tablegen
223bool Sema::isBlockCommand(StringRef Name) {
224 return llvm::StringSwitch<bool>(Name)
225 .Case("brief", true)
226 .Case("result", true)
227 .Case("return", true)
228 .Case("returns", true)
229 .Case("author", true)
230 .Case("authors", true)
231 .Case("pre", true)
232 .Case("post", true)
233 .Default(false) || isParamCommand(Name);
234}
235
236bool Sema::isParamCommand(StringRef Name) {
237 return llvm::StringSwitch<bool>(Name)
238 .Case("param", true)
239 .Case("arg", true)
240 .Default(false);
241}
242
243unsigned Sema::getBlockCommandNumArgs(StringRef Name) {
244 return llvm::StringSwitch<unsigned>(Name)
245 .Case("brief", 0)
246 .Case("pre", 0)
247 .Case("post", 0)
248 .Case("author", 0)
249 .Case("authors", 0)
250 .Default(0);
251}
252
253bool Sema::isInlineCommand(StringRef Name) {
254 return llvm::StringSwitch<bool>(Name)
255 .Case("c", true)
256 .Case("em", true)
257 .Default(false);
258}
259
260bool Sema::HTMLOpenTagNeedsClosing(StringRef Name) {
261 return llvm::StringSwitch<bool>(Name)
262 .Case("br", true)
263 .Default(true);
264}
265
266} // end namespace comments
267} // end namespace clang
268