mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-08 02:18:43 +00:00
[Comment parsing] Add support for recognizing
\headerfile command and representing it in an xml document. Patch reviewed by Dmitri Gribenko. // rdar://12397511 llvm-svn: 174109
This commit is contained in:
parent
f47dc0ba93
commit
1a0cf80533
@ -24,6 +24,9 @@
|
||||
<optional>
|
||||
<ref name="USR" />
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="Headerfile" />
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="Declaration" />
|
||||
</optional>
|
||||
@ -73,6 +76,9 @@
|
||||
<ref name="USR" />
|
||||
</optional>
|
||||
<!-- TODO: Add exception specification. -->
|
||||
<optional>
|
||||
<ref name="Headerfile" />
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="Declaration" />
|
||||
</optional>
|
||||
@ -120,6 +126,9 @@
|
||||
<optional>
|
||||
<ref name="USR" />
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="Headerfile" />
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="Declaration" />
|
||||
</optional>
|
||||
@ -152,6 +161,9 @@
|
||||
<optional>
|
||||
<ref name="USR" />
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="Headerfile" />
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="Declaration" />
|
||||
</optional>
|
||||
@ -185,6 +197,9 @@
|
||||
<optional>
|
||||
<ref name="USR" />
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="Headerfile" />
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="Declaration" />
|
||||
</optional>
|
||||
@ -218,6 +233,9 @@
|
||||
<optional>
|
||||
<ref name="USR" />
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="Headerfile" />
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="Declaration" />
|
||||
</optional>
|
||||
@ -251,6 +269,9 @@
|
||||
<optional>
|
||||
<ref name="USR" />
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="Headerfile" />
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="Declaration" />
|
||||
</optional>
|
||||
@ -329,6 +350,14 @@
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="Headerfile">
|
||||
<element name="Headerfile">
|
||||
<oneOrMore>
|
||||
<ref name="TextBlockContent" />
|
||||
</oneOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="Discussion">
|
||||
<element name="Discussion">
|
||||
<zeroOrMore>
|
||||
|
@ -68,6 +68,9 @@ struct CommandInfo {
|
||||
|
||||
/// True if this command is \\deprecated or an alias.
|
||||
unsigned IsDeprecatedCommand : 1;
|
||||
|
||||
/// \brief True if this is a \headerfile-like documentation
|
||||
unsigned IsHeaderfileCommand : 1;
|
||||
|
||||
/// True if we don't want to warn about this command being passed an empty
|
||||
/// paragraph. Meaningful only for block commands.
|
||||
|
@ -12,6 +12,7 @@ class Command<string name> {
|
||||
bit IsParamCommand = 0;
|
||||
bit IsTParamCommand = 0;
|
||||
bit IsDeprecatedCommand = 0;
|
||||
bit IsHeaderfileCommand = 0;
|
||||
|
||||
bit IsEmptyParagraphAllowed = 0;
|
||||
|
||||
@ -80,7 +81,7 @@ def Deprecated : BlockCommand<"deprecated"> {
|
||||
let IsEmptyParagraphAllowed = 1;
|
||||
let IsDeprecatedCommand = 1;
|
||||
}
|
||||
|
||||
def Headerfile : BlockCommand<"headerfile"> { let IsHeaderfileCommand = 1; }
|
||||
def Author : BlockCommand<"author">;
|
||||
def Authors : BlockCommand<"authors">;
|
||||
def Bug : BlockCommand<"bug">;
|
||||
|
@ -60,6 +60,9 @@ class Sema {
|
||||
|
||||
/// AST node for the \\returns command and its aliases.
|
||||
const BlockCommandComment *ReturnsCommand;
|
||||
|
||||
/// AST node for the \\headerfile command.
|
||||
const BlockCommandComment *HeaderfileCommand;
|
||||
|
||||
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
|
||||
return Diags.Report(Loc, DiagID);
|
||||
|
@ -29,7 +29,8 @@ Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
|
||||
DiagnosticsEngine &Diags, CommandTraits &Traits,
|
||||
const Preprocessor *PP) :
|
||||
Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits),
|
||||
PP(PP), ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL) {
|
||||
PP(PP), ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL),
|
||||
HeaderfileCommand(NULL) {
|
||||
}
|
||||
|
||||
void Sema::setDecl(const Decl *D) {
|
||||
@ -485,6 +486,12 @@ void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) {
|
||||
return;
|
||||
}
|
||||
PrevCommand = ReturnsCommand;
|
||||
} else if (Info->IsHeaderfileCommand) {
|
||||
if (!HeaderfileCommand) {
|
||||
HeaderfileCommand = Command;
|
||||
return;
|
||||
}
|
||||
PrevCommand = HeaderfileCommand;
|
||||
} else {
|
||||
// We don't want to check this command for duplicates.
|
||||
return;
|
||||
|
111
clang/test/Index/headerfile-comment-to-html.m
Normal file
111
clang/test/Index/headerfile-comment-to-html.m
Normal file
@ -0,0 +1,111 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: mkdir %t
|
||||
// RUN: c-index-test -test-load-source all -comments-xml-schema=%S/../../bindings/xml/comment-xml-schema.rng %s > %t/out
|
||||
// RUN: FileCheck %s < %t/out
|
||||
// rdar://13067629
|
||||
|
||||
// Ensure that XML we generate is not invalid.
|
||||
// RUN: FileCheck %s -check-prefix=WRONG < %t/out
|
||||
// WRONG-NOT: CommentXMLInvalid
|
||||
|
||||
// rdar://12397511
|
||||
|
||||
/*!
|
||||
\headerfile Device.h <Foundation/Device.h>
|
||||
|
||||
A Device represents a remote or local computer or device with which the Developer Tools can interact. Each Device supports blah blah blah from doing blah blah blah.
|
||||
*/
|
||||
@interface Device
|
||||
@end
|
||||
// CHECK: headerfile-comment-to-html.m:[[@LINE-2]]:12: ObjCInterfaceDecl=Device:{{.*}} FullCommentAsXML=[<Other file="{{[^"]+}}headerfile-comment-to-html.m" line="[[@LINE-2]]" column="12"><Name>Device</Name><USR>c:objc(cs)Device</USR><Headerfile><Para> Device.h <Foundation/Device.h></Para></Headerfile><Declaration>@interface Device\n@end</Declaration><Abstract><Para> A Device represents a remote or local computer or device with which the Developer Tools can interact. Each Device supports blah blah blah from doing blah blah blah.</Para></Abstract></Other>] CommentXMLValid
|
||||
// CHECK-NEXT: CommentAST=[
|
||||
// CHECK-NEXT: (CXComment_FullComment
|
||||
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
|
||||
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[headerfile]
|
||||
// CHECK-NEXT: (CXComment_Paragraph
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ Device.h ])
|
||||
// CHECK-NEXT: (CXComment_Text Text=[<Foundation])
|
||||
// CHECK-NEXT: (CXComment_Text Text=[/Device.h>])))
|
||||
// CHECK-NEXT: (CXComment_Paragraph
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ A Device represents a remote or local computer or device with which the Developer Tools can interact. Each Device supports blah blah blah from doing blah blah blah.])))]
|
||||
|
||||
/*!
|
||||
\headerfile Sensor.h "Sensor.h"
|
||||
|
||||
\brief This is Sensor on the Device.
|
||||
Its purpose is not to Sense Device's heat.
|
||||
*/
|
||||
|
||||
@interface Sensor
|
||||
@end
|
||||
// CHECK: headerfile-comment-to-html.m:[[@LINE-2]]:12: ObjCInterfaceDecl=Sensor:{{.*}} FullCommentAsXML=[<Other file="{{[^"]+}}headerfile-comment-to-html.m" line="[[@LINE-2]]" column="12"><Name>Sensor</Name><USR>c:objc(cs)Sensor</USR><Headerfile><Para> Sensor.h "Sensor.h"</Para></Headerfile><Declaration>@interface Sensor\n@end</Declaration><Abstract><Para> This is Sensor on the Device. Its purpose is not to Sense Device's heat.</Para></Abstract></Other>] CommentXMLValid
|
||||
// CHECK-NEXT: CommentAST=[
|
||||
// CHECK-NEXT: (CXComment_FullComment
|
||||
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
|
||||
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[headerfile]
|
||||
// CHECK-NEXT: (CXComment_Paragraph
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ Sensor.h "Sensor.h"])))
|
||||
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
|
||||
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[brief]
|
||||
// CHECK-NEXT: (CXComment_Paragraph
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ This is Sensor on the Device.] HasTrailingNewline)
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ Its purpose is not to Sense Device's heat.]))))]
|
||||
|
||||
/*!
|
||||
\brief Test that headerfile can come after brief.
|
||||
\headerfile VTDevice.h <VTFoundation/VTDevice.h>
|
||||
|
||||
More property decription goes here.
|
||||
*/
|
||||
@interface VTDevice : Device
|
||||
@end
|
||||
// CHECK: headerfile-comment-to-html.m:[[@LINE-2]]:12: ObjCInterfaceDecl=VTDevice:{{.*}} FullCommentAsXML=[<Other file="{{[^"]+}}headerfile-comment-to-html.m" line="[[@LINE-2]]" column="12"><Name>VTDevice</Name><USR>c:objc(cs)VTDevice</USR><Headerfile><Para> VTDevice.h <VTFoundation/VTDevice.h></Para></Headerfile><Declaration>@interface VTDevice : Device\n@end</Declaration><Abstract><Para> Test that headerfile can come after brief. </Para></Abstract><Discussion><Para> More property decription goes here.</Para></Discussion></Other>] CommentXMLValid
|
||||
// CHECK-NEXT: CommentAST=[
|
||||
// CHECK-NEXT: (CXComment_FullComment
|
||||
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
|
||||
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[brief]
|
||||
// CHECK-NEXT: (CXComment_Paragraph
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ Test that headerfile can come after brief.] HasTrailingNewline)
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)))
|
||||
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[headerfile]
|
||||
// CHECK-NEXT: (CXComment_Paragraph
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ VTDevice.h ])
|
||||
// CHECK-NEXT: (CXComment_Text Text=[<VTFoundation])
|
||||
// CHECK-NEXT: (CXComment_Text Text=[/VTDevice.h>])))
|
||||
// CHECK-NEXT: (CXComment_Paragraph
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ More property decription goes here.])))]
|
||||
|
||||
/*!
|
||||
\headerfile <stdio.h>
|
||||
*/
|
||||
extern void uses_stdio_h();
|
||||
// CHECK: headerfile-comment-to-html.m:[[@LINE-1]]:13: FunctionDecl=uses_stdio_h:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}headerfile-comment-to-html.m" line="[[@LINE-1]]" column="13"><Name>uses_stdio_h</Name><USR>c:@F@uses_stdio_h</USR><Headerfile><Para> <stdio.h></Para></Headerfile><Declaration>extern void uses_stdio_h()</Declaration></Function>] CommentXMLValid
|
||||
// CHECK-NEXT: CommentAST=[
|
||||
// CHECK-NEXT: (CXComment_FullComment
|
||||
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
|
||||
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[headerfile]
|
||||
// CHECK-NEXT: (CXComment_Paragraph
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)
|
||||
// CHECK-NEXT: (CXComment_Text Text=[<stdio])
|
||||
// CHECK-NEXT: (CXComment_Text Text=[.h>]))))]
|
||||
|
||||
|
||||
/*!
|
||||
\headerfile <algorithm>
|
||||
*/
|
||||
extern void uses_argorithm();
|
||||
// CHECK: headerfile-comment-to-html.m:[[@LINE-1]]:13: FunctionDecl=uses_argorithm:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}headerfile-comment-to-html.m" line="[[@LINE-1]]" column="13"><Name>uses_argorithm</Name><USR>c:@F@uses_argorithm</USR><Headerfile><Para> <algorithm></Para></Headerfile><Declaration>extern void uses_argorithm()</Declaration></Function>] CommentXMLValid
|
||||
// CHECK-NEXT: CommentAST=[
|
||||
// CHECK-NEXT: (CXComment_FullComment
|
||||
// CHECK-NEXT: (CXComment_Paragraph IsWhitespace
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))
|
||||
// CHECK-NEXT: (CXComment_BlockCommand CommandName=[headerfile]
|
||||
// CHECK-NEXT: (CXComment_Paragraph
|
||||
// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)
|
||||
// CHECK-NEXT: (CXComment_Text Text=[<algorithm])
|
||||
// CHECK-NEXT: (CXComment_Text Text=[>]))))]
|
@ -887,3 +887,11 @@ int test_nocrash12();
|
||||
///@param x@param y
|
||||
int test_nocrash13(int x, int y);
|
||||
|
||||
// rdar://12397511
|
||||
|
||||
// expected-note@+2 {{previous command '\headerfile' here}}
|
||||
// expected-warning@+2 {{duplicated command '\headerfile'}}
|
||||
/// \headerfile ""
|
||||
/// \headerfile foo.h
|
||||
int test_duplicate_headerfile1(int);
|
||||
|
||||
|
@ -411,6 +411,7 @@ struct FullCommentParts {
|
||||
const CommandTraits &Traits);
|
||||
|
||||
const BlockContentComment *Brief;
|
||||
const BlockContentComment *Headerfile;
|
||||
const ParagraphComment *FirstParagraph;
|
||||
const BlockCommandComment *Returns;
|
||||
SmallVector<const ParamCommandComment *, 8> Params;
|
||||
@ -420,7 +421,7 @@ struct FullCommentParts {
|
||||
|
||||
FullCommentParts::FullCommentParts(const FullComment *C,
|
||||
const CommandTraits &Traits) :
|
||||
Brief(NULL), FirstParagraph(NULL), Returns(NULL) {
|
||||
Brief(NULL), Headerfile(NULL), FirstParagraph(NULL), Returns(NULL) {
|
||||
for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
|
||||
I != E; ++I) {
|
||||
const Comment *Child = *I;
|
||||
@ -448,6 +449,10 @@ FullCommentParts::FullCommentParts(const FullComment *C,
|
||||
Brief = BCC;
|
||||
break;
|
||||
}
|
||||
if (!Headerfile && Info->IsHeaderfileCommand) {
|
||||
Headerfile = BCC;
|
||||
break;
|
||||
}
|
||||
if (!Returns && Info->IsReturnsCommand) {
|
||||
Returns = BCC;
|
||||
break;
|
||||
@ -750,6 +755,8 @@ void CommentASTToHTMLConverter::visitFullComment(const FullComment *C) {
|
||||
FullCommentParts Parts(C, Traits);
|
||||
|
||||
bool FirstParagraphIsBrief = false;
|
||||
if (Parts.Headerfile)
|
||||
visit(Parts.Headerfile);
|
||||
if (Parts.Brief)
|
||||
visit(Parts.Brief);
|
||||
else if (Parts.FirstParagraph) {
|
||||
@ -1202,6 +1209,12 @@ void CommentASTToXMLConverter::visitFullComment(const FullComment *C) {
|
||||
RootEndTag = "</Other>";
|
||||
Result << "<Other><Name>unknown</Name>";
|
||||
}
|
||||
|
||||
if (Parts.Headerfile) {
|
||||
Result << "<Headerfile>";
|
||||
visit(Parts.Headerfile);
|
||||
Result << "</Headerfile>";
|
||||
}
|
||||
|
||||
{
|
||||
// Pretty-print the declaration.
|
||||
@ -1225,7 +1238,7 @@ void CommentASTToXMLConverter::visitFullComment(const FullComment *C) {
|
||||
Result << "</Abstract>";
|
||||
FirstParagraphIsBrief = true;
|
||||
}
|
||||
|
||||
|
||||
if (Parts.TParams.size() != 0) {
|
||||
Result << "<TemplateParameters>";
|
||||
for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i)
|
||||
|
@ -41,6 +41,7 @@ void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) {
|
||||
<< Tag.getValueAsBit("IsParamCommand") << ", "
|
||||
<< Tag.getValueAsBit("IsTParamCommand") << ", "
|
||||
<< Tag.getValueAsBit("IsDeprecatedCommand") << ", "
|
||||
<< Tag.getValueAsBit("IsHeaderfileCommand") << ", "
|
||||
<< Tag.getValueAsBit("IsEmptyParagraphAllowed") << ", "
|
||||
<< Tag.getValueAsBit("IsVerbatimBlockCommand") << ", "
|
||||
<< Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", "
|
||||
|
Loading…
x
Reference in New Issue
Block a user