forked from OSchip/llvm-project
269 lines
10 KiB
C++
269 lines
10 KiB
C++
//===--- CommentSema.cpp - Doxygen comment semantic analysis --------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/AST/CommentSema.h"
|
|
#include "llvm/ADT/StringSwitch.h"
|
|
|
|
namespace clang {
|
|
namespace comments {
|
|
|
|
Sema::Sema(llvm::BumpPtrAllocator &Allocator) :
|
|
Allocator(Allocator) {
|
|
}
|
|
|
|
ParagraphComment *Sema::actOnParagraphComment(
|
|
ArrayRef<InlineContentComment *> Content) {
|
|
return new (Allocator) ParagraphComment(Content);
|
|
}
|
|
|
|
BlockCommandComment *Sema::actOnBlockCommandStart(SourceLocation LocBegin,
|
|
SourceLocation LocEnd,
|
|
StringRef Name) {
|
|
return new (Allocator) BlockCommandComment(LocBegin, LocEnd, Name);
|
|
}
|
|
|
|
BlockCommandComment *Sema::actOnBlockCommandArgs(
|
|
BlockCommandComment *Command,
|
|
ArrayRef<BlockCommandComment::Argument> Args) {
|
|
Command->setArgs(Args);
|
|
return Command;
|
|
}
|
|
|
|
BlockCommandComment *Sema::actOnBlockCommandFinish(
|
|
BlockCommandComment *Command,
|
|
ParagraphComment *Paragraph) {
|
|
Command->setParagraph(Paragraph);
|
|
return Command;
|
|
}
|
|
|
|
ParamCommandComment *Sema::actOnParamCommandStart(SourceLocation LocBegin,
|
|
SourceLocation LocEnd,
|
|
StringRef Name) {
|
|
return new (Allocator) ParamCommandComment(LocBegin, LocEnd, Name);
|
|
}
|
|
|
|
ParamCommandComment *Sema::actOnParamCommandArg(ParamCommandComment *Command,
|
|
SourceLocation ArgLocBegin,
|
|
SourceLocation ArgLocEnd,
|
|
StringRef Arg,
|
|
bool IsDirection) {
|
|
if (IsDirection) {
|
|
ParamCommandComment::PassDirection Direction;
|
|
std::string ArgLower = Arg.lower();
|
|
// TODO: optimize: lower Name first (need an API in SmallString for that),
|
|
// after that StringSwitch.
|
|
if (ArgLower == "[in]")
|
|
Direction = ParamCommandComment::In;
|
|
else if (ArgLower == "[out]")
|
|
Direction = ParamCommandComment::Out;
|
|
else if (ArgLower == "[in,out]" || ArgLower == "[out,in]")
|
|
Direction = ParamCommandComment::InOut;
|
|
else {
|
|
// Remove spaces.
|
|
std::string::iterator O = ArgLower.begin();
|
|
for (std::string::iterator I = ArgLower.begin(), E = ArgLower.end();
|
|
I != E; ++I) {
|
|
const char C = *I;
|
|
if (C != ' ' && C != '\n' && C != '\r' &&
|
|
C != '\t' && C != '\v' && C != '\f')
|
|
*O++ = C;
|
|
}
|
|
ArgLower.resize(O - ArgLower.begin());
|
|
|
|
bool RemovingWhitespaceHelped = false;
|
|
if (ArgLower == "[in]") {
|
|
Direction = ParamCommandComment::In;
|
|
RemovingWhitespaceHelped = true;
|
|
} else if (ArgLower == "[out]") {
|
|
Direction = ParamCommandComment::Out;
|
|
RemovingWhitespaceHelped = true;
|
|
} else if (ArgLower == "[in,out]" || ArgLower == "[out,in]") {
|
|
Direction = ParamCommandComment::InOut;
|
|
RemovingWhitespaceHelped = true;
|
|
} else {
|
|
Direction = ParamCommandComment::In;
|
|
RemovingWhitespaceHelped = false;
|
|
}
|
|
// Diag() unrecognized parameter passing direction, valid directions are ...
|
|
// if (RemovingWhitespaceHelped) FixIt
|
|
}
|
|
Command->setDirection(Direction, /* Explicit = */ true);
|
|
} else {
|
|
if (Command->getArgCount() == 0) {
|
|
if (!Command->isDirectionExplicit()) {
|
|
// User didn't provide a direction argument.
|
|
Command->setDirection(ParamCommandComment::In, /* Explicit = */ false);
|
|
}
|
|
typedef BlockCommandComment::Argument Argument;
|
|
Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
|
|
ArgLocEnd),
|
|
Arg);
|
|
Command->setArgs(llvm::makeArrayRef(A, 1));
|
|
// if (...) Diag() unrecognized parameter name
|
|
} else {
|
|
// Diag() \\param command requires at most 2 arguments
|
|
}
|
|
}
|
|
return Command;
|
|
}
|
|
|
|
ParamCommandComment *Sema::actOnParamCommandFinish(ParamCommandComment *Command,
|
|
ParagraphComment *Paragraph) {
|
|
Command->setParagraph(Paragraph);
|
|
return Command;
|
|
}
|
|
|
|
InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
|
|
SourceLocation CommandLocEnd,
|
|
StringRef CommandName) {
|
|
ArrayRef<InlineCommandComment::Argument> Args;
|
|
return new (Allocator) InlineCommandComment(CommandLocBegin,
|
|
CommandLocEnd,
|
|
CommandName,
|
|
Args);
|
|
}
|
|
|
|
InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
|
|
SourceLocation CommandLocEnd,
|
|
StringRef CommandName,
|
|
SourceLocation ArgLocBegin,
|
|
SourceLocation ArgLocEnd,
|
|
StringRef Arg) {
|
|
typedef InlineCommandComment::Argument Argument;
|
|
Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
|
|
ArgLocEnd),
|
|
Arg);
|
|
|
|
return new (Allocator) InlineCommandComment(CommandLocBegin,
|
|
CommandLocEnd,
|
|
CommandName,
|
|
llvm::makeArrayRef(A, 1));
|
|
}
|
|
|
|
InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin,
|
|
SourceLocation LocEnd,
|
|
StringRef Name) {
|
|
ArrayRef<InlineCommandComment::Argument> Args;
|
|
return new (Allocator) InlineCommandComment(LocBegin, LocEnd, Name, Args);
|
|
}
|
|
|
|
TextComment *Sema::actOnText(SourceLocation LocBegin,
|
|
SourceLocation LocEnd,
|
|
StringRef Text) {
|
|
return new (Allocator) TextComment(LocBegin, LocEnd, Text);
|
|
}
|
|
|
|
VerbatimBlockComment *Sema::actOnVerbatimBlockStart(SourceLocation Loc,
|
|
StringRef Name) {
|
|
return new (Allocator) VerbatimBlockComment(
|
|
Loc,
|
|
Loc.getLocWithOffset(1 + Name.size()),
|
|
Name);
|
|
}
|
|
|
|
VerbatimBlockLineComment *Sema::actOnVerbatimBlockLine(SourceLocation Loc,
|
|
StringRef Text) {
|
|
return new (Allocator) VerbatimBlockLineComment(Loc, Text);
|
|
}
|
|
|
|
VerbatimBlockComment *Sema::actOnVerbatimBlockFinish(
|
|
VerbatimBlockComment *Block,
|
|
SourceLocation CloseNameLocBegin,
|
|
StringRef CloseName,
|
|
ArrayRef<VerbatimBlockLineComment *> Lines) {
|
|
Block->setCloseName(CloseName, CloseNameLocBegin);
|
|
Block->setLines(Lines);
|
|
return Block;
|
|
}
|
|
|
|
VerbatimLineComment *Sema::actOnVerbatimLine(SourceLocation LocBegin,
|
|
StringRef Name,
|
|
SourceLocation TextBegin,
|
|
StringRef Text) {
|
|
return new (Allocator) VerbatimLineComment(
|
|
LocBegin,
|
|
TextBegin.getLocWithOffset(Text.size()),
|
|
Name,
|
|
TextBegin,
|
|
Text);
|
|
}
|
|
|
|
HTMLOpenTagComment *Sema::actOnHTMLOpenTagStart(SourceLocation LocBegin,
|
|
StringRef TagName) {
|
|
return new (Allocator) HTMLOpenTagComment(LocBegin, TagName);
|
|
}
|
|
|
|
HTMLOpenTagComment *Sema::actOnHTMLOpenTagFinish(
|
|
HTMLOpenTagComment *Tag,
|
|
ArrayRef<HTMLOpenTagComment::Attribute> Attrs,
|
|
SourceLocation GreaterLoc) {
|
|
Tag->setAttrs(Attrs);
|
|
Tag->setGreaterLoc(GreaterLoc);
|
|
return Tag;
|
|
}
|
|
|
|
HTMLCloseTagComment *Sema::actOnHTMLCloseTag(SourceLocation LocBegin,
|
|
SourceLocation LocEnd,
|
|
StringRef TagName) {
|
|
return new (Allocator) HTMLCloseTagComment(LocBegin, LocEnd, TagName);
|
|
}
|
|
|
|
FullComment *Sema::actOnFullComment(
|
|
ArrayRef<BlockContentComment *> Blocks) {
|
|
return new (Allocator) FullComment(Blocks);
|
|
}
|
|
|
|
// TODO: tablegen
|
|
bool Sema::isBlockCommand(StringRef Name) {
|
|
return llvm::StringSwitch<bool>(Name)
|
|
.Case("brief", true)
|
|
.Case("result", true)
|
|
.Case("return", true)
|
|
.Case("returns", true)
|
|
.Case("author", true)
|
|
.Case("authors", true)
|
|
.Case("pre", true)
|
|
.Case("post", true)
|
|
.Default(false) || isParamCommand(Name);
|
|
}
|
|
|
|
bool Sema::isParamCommand(StringRef Name) {
|
|
return llvm::StringSwitch<bool>(Name)
|
|
.Case("param", true)
|
|
.Case("arg", true)
|
|
.Default(false);
|
|
}
|
|
|
|
unsigned Sema::getBlockCommandNumArgs(StringRef Name) {
|
|
return llvm::StringSwitch<unsigned>(Name)
|
|
.Case("brief", 0)
|
|
.Case("pre", 0)
|
|
.Case("post", 0)
|
|
.Case("author", 0)
|
|
.Case("authors", 0)
|
|
.Default(0);
|
|
}
|
|
|
|
bool Sema::isInlineCommand(StringRef Name) {
|
|
return llvm::StringSwitch<bool>(Name)
|
|
.Case("c", true)
|
|
.Case("em", true)
|
|
.Default(false);
|
|
}
|
|
|
|
bool Sema::HTMLOpenTagNeedsClosing(StringRef Name) {
|
|
return llvm::StringSwitch<bool>(Name)
|
|
.Case("br", true)
|
|
.Default(true);
|
|
}
|
|
|
|
} // end namespace comments
|
|
} // end namespace clang
|
|
|