mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Comment parsing: put more information into the generated XML documents
This commit adds infrastructure for conversion and testing it. The conversion is still incomplete, pending discussion about which tags should we use in the XML documents. I copied the RelaxNG schema from Clang, and will edit it accordingly. Swift SVN r16451
This commit is contained in:
@@ -206,6 +206,12 @@ else()
|
|||||||
set(SWIFT_COMPILER "${PATH_TO_SWIFT_BUILD}/${CMAKE_CFG_INTDIR}/bin/swift")
|
set(SWIFT_COMPILER "${PATH_TO_SWIFT_BUILD}/${CMAKE_CFG_INTDIR}/bin/swift")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# FIXME: unify with CLANG_HAVE_LIBXML, which is set in LLVM anyway.
|
||||||
|
find_package(LibXml2)
|
||||||
|
if(LIBXML2_FOUND)
|
||||||
|
set(SWIFT_HAVE_LIBXML 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Xcode: use libc++ and c++11 using proper build settings.
|
# Xcode: use libc++ and c++11 using proper build settings.
|
||||||
if ( XCODE )
|
if ( XCODE )
|
||||||
# Force usage of Clang.
|
# Force usage of Clang.
|
||||||
|
|||||||
592
bindings/xml/comment-xml-schema.rng
Normal file
592
bindings/xml/comment-xml-schema.rng
Normal file
@@ -0,0 +1,592 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
|
||||||
|
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
|
||||||
|
|
||||||
|
<start>
|
||||||
|
<choice>
|
||||||
|
<!-- Everything else not explicitly mentioned below. -->
|
||||||
|
<ref name="Other" />
|
||||||
|
|
||||||
|
<ref name="Function" />
|
||||||
|
<ref name="Class" />
|
||||||
|
<ref name="Variable" />
|
||||||
|
<ref name="Namespace" />
|
||||||
|
<ref name="Typedef" />
|
||||||
|
<ref name="Enum" />
|
||||||
|
</choice>
|
||||||
|
</start>
|
||||||
|
|
||||||
|
<define name="Other">
|
||||||
|
<element name="Other">
|
||||||
|
<ref name="attrSourceLocation" />
|
||||||
|
<ref name="Name" />
|
||||||
|
<optional>
|
||||||
|
<ref name="USR" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Headerfile" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Declaration" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Abstract" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="TemplateParameters" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Parameters" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="ResultDiscussion" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Discussion" />
|
||||||
|
</optional>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Function">
|
||||||
|
<element name="Function">
|
||||||
|
<optional>
|
||||||
|
<attribute name="templateKind">
|
||||||
|
<choice>
|
||||||
|
<value>template</value>
|
||||||
|
<value>specialization</value>
|
||||||
|
</choice>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
<ref name="attrSourceLocation" />
|
||||||
|
|
||||||
|
<optional>
|
||||||
|
<attribute name="isInstanceMethod">
|
||||||
|
<data type="boolean" />
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="isClassMethod">
|
||||||
|
<data type="boolean" />
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
|
||||||
|
<ref name="Name" />
|
||||||
|
<optional>
|
||||||
|
<ref name="USR" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Headerfile" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Declaration" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Abstract" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="TemplateParameters" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Parameters" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Exceptions" />
|
||||||
|
</optional>
|
||||||
|
<zeroOrMore>
|
||||||
|
<ref name="Availability" />
|
||||||
|
</zeroOrMore>
|
||||||
|
<zeroOrMore>
|
||||||
|
<ref name="Deprecated" />
|
||||||
|
</zeroOrMore>
|
||||||
|
<zeroOrMore>
|
||||||
|
<ref name="Unavailable" />
|
||||||
|
</zeroOrMore>
|
||||||
|
<optional>
|
||||||
|
<ref name="ResultDiscussion" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Discussion" />
|
||||||
|
</optional>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Class">
|
||||||
|
<element name="Class">
|
||||||
|
<optional>
|
||||||
|
<attribute name="templateKind">
|
||||||
|
<choice>
|
||||||
|
<value>template</value>
|
||||||
|
<value>specialization</value>
|
||||||
|
<value>partialSpecialization</value>
|
||||||
|
</choice>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
<ref name="attrSourceLocation" />
|
||||||
|
|
||||||
|
<ref name="Name" />
|
||||||
|
<optional>
|
||||||
|
<ref name="USR" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Headerfile" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Declaration" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Abstract" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="TemplateParameters" />
|
||||||
|
</optional>
|
||||||
|
|
||||||
|
<!-- Parameters and results don't make sense for classes, but the user
|
||||||
|
can specify \param or \returns in a comment anyway. -->
|
||||||
|
<optional>
|
||||||
|
<ref name="Parameters" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="ResultDiscussion" />
|
||||||
|
</optional>
|
||||||
|
|
||||||
|
<optional>
|
||||||
|
<ref name="Discussion" />
|
||||||
|
</optional>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Variable">
|
||||||
|
<element name="Variable">
|
||||||
|
<ref name="attrSourceLocation" />
|
||||||
|
<ref name="Name" />
|
||||||
|
<optional>
|
||||||
|
<ref name="USR" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Headerfile" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Declaration" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Abstract" />
|
||||||
|
</optional>
|
||||||
|
|
||||||
|
<!-- Template parameters, parameters and results don't make sense for
|
||||||
|
variables, but the user can specify \tparam \param or \returns
|
||||||
|
in a comment anyway. -->
|
||||||
|
<optional>
|
||||||
|
<ref name="TemplateParameters" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Parameters" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="ResultDiscussion" />
|
||||||
|
</optional>
|
||||||
|
|
||||||
|
<optional>
|
||||||
|
<ref name="Discussion" />
|
||||||
|
</optional>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Namespace">
|
||||||
|
<element name="Namespace">
|
||||||
|
<ref name="attrSourceLocation" />
|
||||||
|
<ref name="Name" />
|
||||||
|
<optional>
|
||||||
|
<ref name="USR" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Headerfile" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Declaration" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Abstract" />
|
||||||
|
</optional>
|
||||||
|
|
||||||
|
<!-- Template parameters, parameters and results don't make sense for
|
||||||
|
namespaces, but the user can specify \tparam, \param or \returns
|
||||||
|
in a comment anyway. -->
|
||||||
|
<optional>
|
||||||
|
<ref name="TemplateParameters" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Parameters" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="ResultDiscussion" />
|
||||||
|
</optional>
|
||||||
|
|
||||||
|
<optional>
|
||||||
|
<ref name="Discussion" />
|
||||||
|
</optional>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Typedef">
|
||||||
|
<element name="Typedef">
|
||||||
|
<ref name="attrSourceLocation" />
|
||||||
|
<ref name="Name" />
|
||||||
|
<optional>
|
||||||
|
<ref name="USR" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Headerfile" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Declaration" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Abstract" />
|
||||||
|
</optional>
|
||||||
|
|
||||||
|
<optional>
|
||||||
|
<ref name="TemplateParameters" />
|
||||||
|
</optional>
|
||||||
|
|
||||||
|
<!-- Parameters and results might make sense for typedefs if the type is
|
||||||
|
a function pointer type. -->
|
||||||
|
<optional>
|
||||||
|
<ref name="Parameters" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="ResultDiscussion" />
|
||||||
|
</optional>
|
||||||
|
|
||||||
|
<optional>
|
||||||
|
<ref name="Discussion" />
|
||||||
|
</optional>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Enum">
|
||||||
|
<element name="Enum">
|
||||||
|
<ref name="attrSourceLocation" />
|
||||||
|
<ref name="Name" />
|
||||||
|
<optional>
|
||||||
|
<ref name="USR" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Headerfile" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Declaration" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Abstract" />
|
||||||
|
</optional>
|
||||||
|
|
||||||
|
<!-- Template parameters, parameters and results don't make sense for
|
||||||
|
enums, but the user can specify \tparam \param or \returns in a
|
||||||
|
comment anyway. -->
|
||||||
|
<optional>
|
||||||
|
<ref name="TemplateParameters" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Parameters" />
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="ResultDiscussion" />
|
||||||
|
</optional>
|
||||||
|
|
||||||
|
<optional>
|
||||||
|
<ref name="Discussion" />
|
||||||
|
</optional>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="attrSourceLocation">
|
||||||
|
<optional>
|
||||||
|
<attribute name="file">
|
||||||
|
<!-- Non-empty text content. -->
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">.*\S.*</param>
|
||||||
|
</data>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="line">
|
||||||
|
<data type="positiveInteger" />
|
||||||
|
</attribute>
|
||||||
|
<attribute name="column">
|
||||||
|
<data type="positiveInteger" />
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Name">
|
||||||
|
<element name="Name">
|
||||||
|
<!-- Non-empty text content. -->
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">.*\S.*</param>
|
||||||
|
</data>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="USR">
|
||||||
|
<element name="USR">
|
||||||
|
<!-- Non-empty text content. -->
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">.*\S.*</param>
|
||||||
|
</data>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Abstract">
|
||||||
|
<element name="Abstract">
|
||||||
|
<zeroOrMore>
|
||||||
|
<ref name="TextBlockContent" />
|
||||||
|
</zeroOrMore>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Declaration">
|
||||||
|
<element name="Declaration">
|
||||||
|
<!-- Non-empty text content. -->
|
||||||
|
<data type="string"/>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Headerfile">
|
||||||
|
<element name="Headerfile">
|
||||||
|
<oneOrMore>
|
||||||
|
<ref name="TextBlockContent" />
|
||||||
|
</oneOrMore>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Discussion">
|
||||||
|
<element name="Discussion">
|
||||||
|
<zeroOrMore>
|
||||||
|
<ref name="TextBlockContent" />
|
||||||
|
</zeroOrMore>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="TemplateParameters">
|
||||||
|
<element name="TemplateParameters">
|
||||||
|
<!-- Parameter elements should be sorted according to position. -->
|
||||||
|
<oneOrMore>
|
||||||
|
<element name="Parameter">
|
||||||
|
<element name="Name">
|
||||||
|
<!-- Non-empty text content. -->
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">.*\S.*</param>
|
||||||
|
</data>
|
||||||
|
</element>
|
||||||
|
<optional>
|
||||||
|
<!-- This is index at depth 0. libclang API can return more
|
||||||
|
information about position, but we expose only essential
|
||||||
|
information here, since "Parameter" elements are already
|
||||||
|
sorted.
|
||||||
|
|
||||||
|
"Position" element could be added in future if needed. -->
|
||||||
|
<element name="Index">
|
||||||
|
<data type="nonNegativeInteger" />
|
||||||
|
</element>
|
||||||
|
</optional>
|
||||||
|
<!-- In general, template parameters with whitespace discussion
|
||||||
|
should not be emitted. Schema might be more strict here. -->
|
||||||
|
<element name="Discussion">
|
||||||
|
<ref name="TextBlockContent" />
|
||||||
|
</element>
|
||||||
|
</element>
|
||||||
|
</oneOrMore>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Parameters">
|
||||||
|
<element name="Parameters">
|
||||||
|
<!-- Parameter elements should be sorted according to index. -->
|
||||||
|
<oneOrMore>
|
||||||
|
<element name="Parameter">
|
||||||
|
<element name="Name">
|
||||||
|
<!-- Non-empty text content. -->
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">.*\S.*</param>
|
||||||
|
</data>
|
||||||
|
</element>
|
||||||
|
<optional>
|
||||||
|
<choice>
|
||||||
|
<element name="Index">
|
||||||
|
<data type="nonNegativeInteger" />
|
||||||
|
</element>
|
||||||
|
<element name="IsVarArg">
|
||||||
|
<empty />
|
||||||
|
</element>
|
||||||
|
</choice>
|
||||||
|
</optional>
|
||||||
|
<element name="Direction">
|
||||||
|
<attribute name="isExplicit">
|
||||||
|
<data type="boolean" />
|
||||||
|
</attribute>
|
||||||
|
<choice>
|
||||||
|
<value>in</value>
|
||||||
|
<value>out</value>
|
||||||
|
<value>in,out</value>
|
||||||
|
</choice>
|
||||||
|
</element>
|
||||||
|
<!-- In general, template parameters with whitespace discussion
|
||||||
|
should not be emitted, unless direction is explicitly specified.
|
||||||
|
Schema might be more strict here. -->
|
||||||
|
<element name="Discussion">
|
||||||
|
<ref name="TextBlockContent" />
|
||||||
|
</element>
|
||||||
|
</element>
|
||||||
|
</oneOrMore>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Exceptions">
|
||||||
|
<element name="Exceptions">
|
||||||
|
<oneOrMore>
|
||||||
|
<ref name="TextBlockContent" />
|
||||||
|
</oneOrMore>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Availability">
|
||||||
|
<element name="Availability">
|
||||||
|
<attribute name="distribution">
|
||||||
|
<data type="string" />
|
||||||
|
</attribute>
|
||||||
|
<optional>
|
||||||
|
<element name="IntroducedInVersion">
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">\d+|\d+\.\d+|\d+\.\d+.\d+</param>
|
||||||
|
</data>
|
||||||
|
</element>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<element name="DeprecatedInVersion">
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">\d+|\d+\.\d+|\d+\.\d+.\d+</param>
|
||||||
|
</data>
|
||||||
|
</element>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<element name="RemovedAfterVersion">
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">\d+|\d+\.\d+|\d+\.\d+.\d+</param>
|
||||||
|
</data>
|
||||||
|
</element>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<element name="DeprecationSummary">
|
||||||
|
<data type="string" />
|
||||||
|
</element>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="Unavailable" />
|
||||||
|
</optional>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Deprecated">
|
||||||
|
<element name="Deprecated">
|
||||||
|
<optional>
|
||||||
|
<data type="string" />
|
||||||
|
</optional>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="Unavailable">
|
||||||
|
<element name="Unavailable">
|
||||||
|
<optional>
|
||||||
|
<data type="string" />
|
||||||
|
</optional>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="ResultDiscussion">
|
||||||
|
<element name="ResultDiscussion">
|
||||||
|
<zeroOrMore>
|
||||||
|
<ref name="TextBlockContent" />
|
||||||
|
</zeroOrMore>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="TextBlockContent">
|
||||||
|
<choice>
|
||||||
|
<element name="Para">
|
||||||
|
<optional>
|
||||||
|
<attribute name="kind">
|
||||||
|
<choice>
|
||||||
|
<value>attention</value>
|
||||||
|
<value>author</value>
|
||||||
|
<value>authors</value>
|
||||||
|
<value>bug</value>
|
||||||
|
<value>copyright</value>
|
||||||
|
<value>date</value>
|
||||||
|
<value>invariant</value>
|
||||||
|
<value>note</value>
|
||||||
|
<value>post</value>
|
||||||
|
<value>pre</value>
|
||||||
|
<value>remark</value>
|
||||||
|
<value>remarks</value>
|
||||||
|
<value>sa</value>
|
||||||
|
<value>see</value>
|
||||||
|
<value>since</value>
|
||||||
|
<value>todo</value>
|
||||||
|
<value>version</value>
|
||||||
|
<value>warning</value>
|
||||||
|
</choice>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
<zeroOrMore>
|
||||||
|
<ref name="TextInlineContent" />
|
||||||
|
</zeroOrMore>
|
||||||
|
</element>
|
||||||
|
<element name="Verbatim">
|
||||||
|
<attribute name="xml:space">
|
||||||
|
<value>preserve</value>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="kind">
|
||||||
|
<!-- TODO: add all Doxygen verbatim kinds -->
|
||||||
|
<choice>
|
||||||
|
<value>code</value>
|
||||||
|
<value>verbatim</value>
|
||||||
|
</choice>
|
||||||
|
</attribute>
|
||||||
|
<text />
|
||||||
|
</element>
|
||||||
|
</choice>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name="TextInlineContent">
|
||||||
|
<choice>
|
||||||
|
<text />
|
||||||
|
<element name="bold">
|
||||||
|
<!-- Non-empty text content. -->
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">.*\S.*</param>
|
||||||
|
</data>
|
||||||
|
</element>
|
||||||
|
<element name="monospaced">
|
||||||
|
<!-- Non-empty text content. -->
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">.*\S.*</param>
|
||||||
|
</data>
|
||||||
|
</element>
|
||||||
|
<element name="emphasized">
|
||||||
|
<!-- Non-empty text content. -->
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">.*\S.*</param>
|
||||||
|
</data>
|
||||||
|
</element>
|
||||||
|
<element name="rawHTML">
|
||||||
|
<!-- Non-empty text content. -->
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">.*\S.*</param>
|
||||||
|
</data>
|
||||||
|
</element>
|
||||||
|
</choice>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
</grammar>
|
||||||
|
|
||||||
@@ -38,6 +38,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
SmallVector<const llvm::rest::Field *, 8> Params;
|
SmallVector<const llvm::rest::Field *, 8> Params;
|
||||||
SmallVector<const llvm::rest::Field *, 4> Returns;
|
SmallVector<const llvm::rest::Field *, 4> Returns;
|
||||||
|
const llvm::rest::Paragraph *Brief = nullptr;
|
||||||
SmallVector<const llvm::rest::ReSTASTNode *, 4> MiscTopLevelNodes;
|
SmallVector<const llvm::rest::ReSTASTNode *, 4> MiscTopLevelNodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
38
include/swift/IDE/CommentConversion.h
Normal file
38
include/swift/IDE/CommentConversion.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
//===--- CommentConversion.h - Conversion of comments to other formats ----===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See http://swift.org/LICENSE.txt for license information
|
||||||
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef SWIFT_IDE_COMMENT_CONVERSION_H
|
||||||
|
#define SWIFT_IDE_COMMENT_CONVERSION_H
|
||||||
|
|
||||||
|
#include "swift/Basic/LLVM.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace swift {
|
||||||
|
class Decl;
|
||||||
|
class FullComment;
|
||||||
|
|
||||||
|
namespace ide {
|
||||||
|
|
||||||
|
/// If the declaration has a documentation comment, prints the comment to \p OS
|
||||||
|
/// in Clang-like XML format.
|
||||||
|
///
|
||||||
|
/// \returns true if the declaration has a documentation comment.
|
||||||
|
bool getDocumentationCommentAsXML(const Decl *D, raw_ostream &OS);
|
||||||
|
|
||||||
|
/// Converts the given comment to Doxygen.
|
||||||
|
void getDocumentationCommentAsDoxygen(const FullComment *FC, raw_ostream &OS);
|
||||||
|
|
||||||
|
} // namespace ide
|
||||||
|
} // namespace swift
|
||||||
|
|
||||||
|
#endif // SWIFT_IDE_COMMENT_CONVERSION_H
|
||||||
|
|
||||||
@@ -21,8 +21,6 @@ namespace llvm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
class Decl;
|
|
||||||
|
|
||||||
namespace ide {
|
namespace ide {
|
||||||
|
|
||||||
/// Returns true if the input source is fully formed, or false if, for example,
|
/// Returns true if the input source is fully formed, or false if, for example,
|
||||||
@@ -30,13 +28,8 @@ namespace ide {
|
|||||||
bool isSourceInputComplete(std::unique_ptr<llvm::MemoryBuffer> MemBuf);
|
bool isSourceInputComplete(std::unique_ptr<llvm::MemoryBuffer> MemBuf);
|
||||||
bool isSourceInputComplete(StringRef Text);
|
bool isSourceInputComplete(StringRef Text);
|
||||||
|
|
||||||
/// If the declaration has a documentation comment, prints the comment to \p OS
|
|
||||||
/// in Clang-like XML format.
|
|
||||||
///
|
|
||||||
/// \returns true if the declaration has a documentation comment.
|
|
||||||
bool getDocumentationCommentAsXML(const Decl *D, raw_ostream &OS);
|
|
||||||
|
|
||||||
} // namespace ide
|
} // namespace ide
|
||||||
} // namespace swift
|
} // namespace swift
|
||||||
|
|
||||||
#endif // SWIFT_IDE_UTILS_H
|
#endif // SWIFT_IDE_UTILS_H
|
||||||
|
|
||||||
|
|||||||
53
include/swift/ReST/XMLUtils.h
Normal file
53
include/swift/ReST/XMLUtils.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
//===--- XMLUtils.h - Various XML utility routines ------------------------===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See http://swift.org/LICENSE.txt for license information
|
||||||
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_REST_XML_UTILS_H
|
||||||
|
#define LLVM_REST_XML_UTILS_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
namespace rest {
|
||||||
|
|
||||||
|
// FIXME: copied from Clang's
|
||||||
|
// CommentASTToXMLConverter::appendToResultWithXMLEscaping
|
||||||
|
static inline void appendWithXMLEscaping(raw_ostream &OS, StringRef S) {
|
||||||
|
for (const char C : S) {
|
||||||
|
switch (C) {
|
||||||
|
case '&':
|
||||||
|
OS << "&";
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
OS << "<";
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
OS << ">";
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
OS << """;
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
OS << "'";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
OS << C;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace rest
|
||||||
|
} // namespace llvm
|
||||||
|
|
||||||
|
#endif // LLVM_REST_XML_UTILS_H
|
||||||
|
|
||||||
@@ -281,7 +281,17 @@ const FullComment::CommentParts &FullComment::getParts() const {
|
|||||||
return Parts.getValue();
|
return Parts.getValue();
|
||||||
|
|
||||||
Parts = CommentParts();
|
Parts = CommentParts();
|
||||||
|
bool IsFirstChild = true;
|
||||||
for (const auto *N : Doc->getChildren()) {
|
for (const auto *N : Doc->getChildren()) {
|
||||||
|
// If the first document child is a paragraph, consider it a brief
|
||||||
|
// description.
|
||||||
|
if (IsFirstChild) {
|
||||||
|
IsFirstChild = false;
|
||||||
|
if (const auto *P = dyn_cast<llvm::rest::Paragraph>(N)) {
|
||||||
|
Parts->Brief = P;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (const auto *FL = dyn_cast<llvm::rest::FieldList>(N)) {
|
if (const auto *FL = dyn_cast<llvm::rest::FieldList>(N)) {
|
||||||
for (const auto *F : FL->getChildren()) {
|
for (const auto *F : FL->getChildren()) {
|
||||||
if (isFieldNamed(F, "param"))
|
if (isFieldNamed(F, "param"))
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
add_swift_library(swiftIDE
|
add_swift_library(swiftIDE
|
||||||
CodeCompletion.cpp
|
CodeCompletion.cpp
|
||||||
|
CommentConversion.cpp
|
||||||
ModuleInterfacePrinting.cpp
|
ModuleInterfacePrinting.cpp
|
||||||
REPLCodeCompletion.cpp
|
REPLCodeCompletion.cpp
|
||||||
SourceEntityWalker.cpp
|
SourceEntityWalker.cpp
|
||||||
|
|||||||
550
lib/IDE/CommentConversion.cpp
Normal file
550
lib/IDE/CommentConversion.cpp
Normal file
@@ -0,0 +1,550 @@
|
|||||||
|
//===--- CommentConversion.cpp - Conversion of comments to other formats --===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See http://swift.org/LICENSE.txt for license information
|
||||||
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "swift/IDE/CommentConversion.h"
|
||||||
|
#include "swift/AST/ASTContext.h"
|
||||||
|
#include "swift/AST/Comment.h"
|
||||||
|
#include "swift/AST/Decl.h"
|
||||||
|
#include "swift/AST/USRGeneration.h"
|
||||||
|
#include "swift/Basic/SourceManager.h"
|
||||||
|
#include "swift/ReST/AST.h"
|
||||||
|
#include "swift/ReST/XMLUtils.h"
|
||||||
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
#include "clang/AST/ASTContext.h"
|
||||||
|
#include "clang/AST/Decl.h"
|
||||||
|
#include "clang/Index/CommentToXML.h"
|
||||||
|
|
||||||
|
using namespace llvm::rest;
|
||||||
|
using namespace swift;
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Conversion to XML.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct CommentToXMLConverter {
|
||||||
|
raw_ostream &OS;
|
||||||
|
|
||||||
|
CommentToXMLConverter(raw_ostream &OS) : OS(OS) {}
|
||||||
|
|
||||||
|
void printASTNode(const ReSTASTNode *N) {
|
||||||
|
switch (N->getKind()) {
|
||||||
|
case ASTNodeKind::Document:
|
||||||
|
llvm_unreachable("should never happen");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ASTNodeKind::Section:
|
||||||
|
case ASTNodeKind::Topic:
|
||||||
|
case ASTNodeKind::Sidebar:
|
||||||
|
case ASTNodeKind::Title:
|
||||||
|
case ASTNodeKind::Subtitle:
|
||||||
|
case ASTNodeKind::Transition:
|
||||||
|
llvm_unreachable("implement");
|
||||||
|
|
||||||
|
case ASTNodeKind::Paragraph:
|
||||||
|
printParagraph(cast<Paragraph>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::BulletList:
|
||||||
|
printBulletList(cast<BulletList>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::EnumeratedList:
|
||||||
|
printEnumeratedList(cast<EnumeratedList>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::DefinitionListItem:
|
||||||
|
printDefinitionListItem(cast<DefinitionListItem>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::DefinitionList:
|
||||||
|
printDefinitionList(cast<DefinitionList>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::Field:
|
||||||
|
printField(cast<Field>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::FieldList:
|
||||||
|
printFieldList(cast<FieldList>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::BlockQuote:
|
||||||
|
printBlockQuote(cast<BlockQuote>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::TextAndInline:
|
||||||
|
printTextAndInline(cast<TextAndInline>(N));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printParagraph(const Paragraph *P) {
|
||||||
|
OS << "<Para>";
|
||||||
|
printTextAndInline(P->getContent());
|
||||||
|
OS << "</Para>";
|
||||||
|
}
|
||||||
|
|
||||||
|
void printBulletList(const BulletList *BL) {
|
||||||
|
// FIXME: print block markup.
|
||||||
|
for (unsigned i = 0, e = BL->getNumItems(); i != e; ++i) {
|
||||||
|
for (const auto *N : BL->getItemChildren(i)) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printEnumeratedList(const EnumeratedList *EL) {
|
||||||
|
// FIXME: print block markup.
|
||||||
|
for (unsigned i = 0, e = EL->getNumItems(); i != e; ++i) {
|
||||||
|
for (const auto *N : EL->getItemChildren(i)) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printDefinitionListItem(const DefinitionListItem *DLI) {
|
||||||
|
// FIXME: print real block markup.
|
||||||
|
OS << "<Para>";
|
||||||
|
printASTNode(DLI->getTerm());
|
||||||
|
OS << "</Para>";
|
||||||
|
for (const auto *N : DLI->getClassifiers()) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto *N : DLI->getDefinitionChildren()) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printDefinitionList(const DefinitionList *DL) {
|
||||||
|
// FIXME: print block markup.
|
||||||
|
for (const auto *N : DL->getChildren()) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printField(const Field *F) {
|
||||||
|
// FIXME: print real block markup.
|
||||||
|
OS << "<Para>";
|
||||||
|
printASTNode(F->getName());
|
||||||
|
OS << "</Para>";
|
||||||
|
for (const auto *N : F->getBodyChildren()) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printFieldList(const FieldList *FL) {
|
||||||
|
// FIXME: print block markup.
|
||||||
|
for (const auto *F : FL->getChildren()) {
|
||||||
|
printASTNode(F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printBlockQuote(const BlockQuote *BQ) {
|
||||||
|
// FIXME: print block markup.
|
||||||
|
for (const auto *N : BQ->getChildren()) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printTextAndInline(const TextAndInline *T) {
|
||||||
|
if (T->isLinePart()) {
|
||||||
|
LinePart LP = T->getLinePart();
|
||||||
|
appendWithXMLEscaping(OS, LP.Text);
|
||||||
|
} else {
|
||||||
|
LineListRef LL = T->getLines();
|
||||||
|
for (unsigned i = 0, e = LL.size(); i != e; ++i) {
|
||||||
|
appendWithXMLEscaping(OS, LL[i].Text.drop_front(LL[i].FirstTextByte));
|
||||||
|
if (i != e - 1)
|
||||||
|
OS << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printOrphanField(const Field *F) {
|
||||||
|
// FIXME: print block markup.
|
||||||
|
printField(F);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printAsParameter(const Field *F) {
|
||||||
|
OS << "<Parameter><Name>";
|
||||||
|
// FIXME: extract parameter name.
|
||||||
|
OS << "x";
|
||||||
|
OS << "</Name><Direction isExplicit=\"0\">in</Direction><Discussion>";
|
||||||
|
for (const auto *N : F->getBodyChildren()) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
OS << "</Discussion></Parameter>";
|
||||||
|
}
|
||||||
|
|
||||||
|
void printAsReturns(const Field *F) {
|
||||||
|
for (const auto *N : F->getBodyChildren()) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitFullComment(const FullComment *FC);
|
||||||
|
};
|
||||||
|
} // unnamed namespace
|
||||||
|
|
||||||
|
void CommentToXMLConverter::visitFullComment(const FullComment *FC) {
|
||||||
|
const Decl *D = FC->getDecl();
|
||||||
|
const auto &Parts = FC->getParts();
|
||||||
|
|
||||||
|
StringRef RootEndTag;
|
||||||
|
if (isa<AbstractFunctionDecl>(D)) {
|
||||||
|
OS << "<Function";
|
||||||
|
RootEndTag = "</Function>";
|
||||||
|
} else {
|
||||||
|
OS << "<Other";
|
||||||
|
RootEndTag = "</Other>";
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Print line and column number.
|
||||||
|
auto Loc = D->getLoc();
|
||||||
|
if (Loc.isValid()) {
|
||||||
|
const auto &SM = D->getASTContext().SourceMgr;
|
||||||
|
unsigned BufferID = SM.findBufferContainingLoc(Loc);
|
||||||
|
StringRef FileName = SM->getMemoryBuffer(BufferID)->getBufferIdentifier();
|
||||||
|
auto LineAndColumn = SM.getLineAndColumn(Loc);
|
||||||
|
OS << " file=\"";
|
||||||
|
appendWithXMLEscaping(OS, FileName);
|
||||||
|
OS << "\"";
|
||||||
|
OS << " line=\"" << LineAndColumn.first << "\" column=\""
|
||||||
|
<< LineAndColumn.second << "\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish the root tag.
|
||||||
|
OS << ">";
|
||||||
|
|
||||||
|
auto *VD = dyn_cast<ValueDecl>(D);
|
||||||
|
|
||||||
|
OS << "<Name>";
|
||||||
|
if (VD && VD->hasName())
|
||||||
|
OS << VD->getFullName();
|
||||||
|
OS << "</Name>";
|
||||||
|
|
||||||
|
if (VD) {
|
||||||
|
llvm::SmallString<64> SS;
|
||||||
|
bool Failed;
|
||||||
|
{
|
||||||
|
llvm::raw_svector_ostream OS(SS);
|
||||||
|
Failed = ide::printDeclUSR(VD, OS);
|
||||||
|
}
|
||||||
|
if (!Failed && !SS.empty()) {
|
||||||
|
OS << "<USR>" << SS << "</USR>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: <Declaration>
|
||||||
|
if (Parts.Brief) {
|
||||||
|
OS << "<Abstract>";
|
||||||
|
printASTNode(Parts.Brief);
|
||||||
|
OS << "</Abstract>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Parts.MiscTopLevelNodes.empty()) {
|
||||||
|
OS << "<Discussion>";
|
||||||
|
for (const auto *N : Parts.MiscTopLevelNodes) {
|
||||||
|
if (const auto *F = dyn_cast<Field>(N)) {
|
||||||
|
printOrphanField(F);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
OS << "</Discussion>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Parts.Params.empty()) {
|
||||||
|
OS << "<Parameters>";
|
||||||
|
for (const auto *N : Parts.Params) {
|
||||||
|
printAsParameter(N);
|
||||||
|
}
|
||||||
|
OS << "</Parameters>";
|
||||||
|
}
|
||||||
|
if (!Parts.Returns.empty()) {
|
||||||
|
OS << "<ResultDiscussion>";
|
||||||
|
for (const auto *N : Parts.Returns) {
|
||||||
|
printAsReturns(N);
|
||||||
|
}
|
||||||
|
OS << "</ResultDiscussion>";
|
||||||
|
}
|
||||||
|
|
||||||
|
OS << RootEndTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool getClangDocumentationCommentAsXML(const clang::Decl *D,
|
||||||
|
raw_ostream &OS) {
|
||||||
|
const auto &ClangContext = D->getASTContext();
|
||||||
|
const clang::comments::FullComment *FC =
|
||||||
|
ClangContext.getCommentForDecl(D, /*PP=*/nullptr);
|
||||||
|
if (!FC)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// FIXME: hang the converter object somewhere so that it is persistent
|
||||||
|
// between requests to this AST.
|
||||||
|
clang::index::CommentToXMLConverter Converter;
|
||||||
|
|
||||||
|
llvm::SmallString<1024> XML;
|
||||||
|
Converter.convertCommentToXML(FC, XML, ClangContext);
|
||||||
|
OS << XML;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ide::getDocumentationCommentAsXML(const Decl *D, raw_ostream &OS) {
|
||||||
|
auto MaybeClangNode = D->getClangNode();
|
||||||
|
if (MaybeClangNode) {
|
||||||
|
if (auto *CD = MaybeClangNode.getAsDecl())
|
||||||
|
return getClangDocumentationCommentAsXML(CD, OS);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommentContext TheCommentContext;
|
||||||
|
auto *FC = getFullComment(TheCommentContext, D);
|
||||||
|
if (!FC)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CommentToXMLConverter Converter(OS);
|
||||||
|
Converter.visitFullComment(FC);
|
||||||
|
|
||||||
|
OS.flush();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Conversion to Doxygen.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct CommentToDoxygenConverter {
|
||||||
|
raw_ostream &OS;
|
||||||
|
unsigned PendingNewlines = 1;
|
||||||
|
|
||||||
|
CommentToDoxygenConverter(raw_ostream &OS) : OS(OS) {}
|
||||||
|
|
||||||
|
void print(StringRef Text) {
|
||||||
|
for (unsigned i = 0; i != PendingNewlines; ++i) {
|
||||||
|
OS << "\n///";
|
||||||
|
if (i == PendingNewlines - 1)
|
||||||
|
OS << " ";
|
||||||
|
}
|
||||||
|
PendingNewlines = 0;
|
||||||
|
OS << Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printNewline() {
|
||||||
|
PendingNewlines++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printASTNode(const ReSTASTNode *N) {
|
||||||
|
switch (N->getKind()) {
|
||||||
|
case ASTNodeKind::Document:
|
||||||
|
llvm_unreachable("should never happen");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ASTNodeKind::Section:
|
||||||
|
case ASTNodeKind::Topic:
|
||||||
|
case ASTNodeKind::Sidebar:
|
||||||
|
case ASTNodeKind::Title:
|
||||||
|
case ASTNodeKind::Subtitle:
|
||||||
|
case ASTNodeKind::Transition:
|
||||||
|
llvm_unreachable("implement");
|
||||||
|
|
||||||
|
case ASTNodeKind::Paragraph:
|
||||||
|
printParagraph(cast<Paragraph>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::BulletList:
|
||||||
|
printBulletList(cast<BulletList>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::EnumeratedList:
|
||||||
|
printEnumeratedList(cast<EnumeratedList>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::DefinitionListItem:
|
||||||
|
printDefinitionListItem(cast<DefinitionListItem>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::DefinitionList:
|
||||||
|
printDefinitionList(cast<DefinitionList>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::Field:
|
||||||
|
printField(cast<Field>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::FieldList:
|
||||||
|
printFieldList(cast<FieldList>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::BlockQuote:
|
||||||
|
printBlockQuote(cast<BlockQuote>(N));
|
||||||
|
break;
|
||||||
|
case ASTNodeKind::TextAndInline:
|
||||||
|
printTextAndInline(cast<TextAndInline>(N));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printParagraph(const Paragraph *P) {
|
||||||
|
print("<p>");
|
||||||
|
printTextAndInline(P->getContent());
|
||||||
|
print("</p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void printBulletList(const BulletList *BL) {
|
||||||
|
print("<ul>");
|
||||||
|
for (unsigned i = 0, e = BL->getNumItems(); i != e; ++i) {
|
||||||
|
print("<li>");
|
||||||
|
for (const auto *N : BL->getItemChildren(i)) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
print("</li>");
|
||||||
|
}
|
||||||
|
print("</ul>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void printEnumeratedList(const EnumeratedList *EL) {
|
||||||
|
print("<ol>");
|
||||||
|
for (unsigned i = 0, e = EL->getNumItems(); i != e; ++i) {
|
||||||
|
print("<li>");
|
||||||
|
for (const auto *N : EL->getItemChildren(i)) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
print("</li>");
|
||||||
|
}
|
||||||
|
print("</ol>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void printDefinitionListItem(const DefinitionListItem *DLI) {
|
||||||
|
print("<dt>");
|
||||||
|
printASTNode(DLI->getTerm());
|
||||||
|
for (const auto *N : DLI->getClassifiers()) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
print("</dt>");
|
||||||
|
|
||||||
|
print("<dd>");
|
||||||
|
for (const auto *N : DLI->getDefinitionChildren()) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
print("</dd>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void printDefinitionList(const DefinitionList *DL) {
|
||||||
|
print("<dl>");
|
||||||
|
for (const auto *N : DL->getChildren()) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
print("</dl>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void printField(const Field *F) {
|
||||||
|
print("<dt>");
|
||||||
|
printASTNode(F->getName());
|
||||||
|
print("</dt>");
|
||||||
|
print("<dd>");
|
||||||
|
for (const auto *N : F->getBodyChildren()) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
print("</dd>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void printFieldList(const FieldList *FL) {
|
||||||
|
print("<dl>");
|
||||||
|
for (const auto *F : FL->getChildren()) {
|
||||||
|
printASTNode(F);
|
||||||
|
}
|
||||||
|
print("</dl>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void printBlockQuote(const BlockQuote *BQ) {
|
||||||
|
print("<blockquote>");
|
||||||
|
for (const auto *N : BQ->getChildren()) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
print("</blockquote>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void printTextAndInline(const TextAndInline *T) {
|
||||||
|
if (T->isLinePart()) {
|
||||||
|
LinePart LP = T->getLinePart();
|
||||||
|
print(LP.Text);
|
||||||
|
} else {
|
||||||
|
LineListRef LL = T->getLines();
|
||||||
|
for (unsigned i = 0, e = LL.size(); i != e; ++i) {
|
||||||
|
print(LL[i].Text.drop_front(LL[i].FirstTextByte));
|
||||||
|
if (i != e - 1)
|
||||||
|
printNewline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printOrphanField(const Field *F) {
|
||||||
|
print("<dl>");
|
||||||
|
printField(F);
|
||||||
|
print("</dl>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void printBlockCommandContent(ArrayRef<const ReSTASTNode *> Nodes) {
|
||||||
|
if (Nodes.size() == 1) {
|
||||||
|
if (const auto *P = dyn_cast<Paragraph>(Nodes[0])) {
|
||||||
|
printTextAndInline(P->getContent());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto *N : Nodes) {
|
||||||
|
printASTNode(N);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printAsDoxygenParam(const Field *F) {
|
||||||
|
print("\\param ");
|
||||||
|
printBlockCommandContent(F->getBodyChildren());
|
||||||
|
printNewline();
|
||||||
|
}
|
||||||
|
|
||||||
|
void printAsDoxygenReturns(const Field *F) {
|
||||||
|
print("\\returns ");
|
||||||
|
printBlockCommandContent(F->getBodyChildren());
|
||||||
|
printNewline();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // unnamed namespace
|
||||||
|
|
||||||
|
void ide::getDocumentationCommentAsDoxygen(const FullComment *FC, raw_ostream &OS) {
|
||||||
|
CommentToDoxygenConverter Converter(OS);
|
||||||
|
const auto &Parts = FC->getParts();
|
||||||
|
|
||||||
|
if (Parts.Brief) {
|
||||||
|
Converter.printTextAndInline(Parts.Brief->getContent());
|
||||||
|
Converter.printNewline();
|
||||||
|
Converter.printNewline();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto *N : Parts.MiscTopLevelNodes) {
|
||||||
|
if (const auto *F = dyn_cast<Field>(N)) {
|
||||||
|
Converter.printOrphanField(F);
|
||||||
|
Converter.printNewline();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (const auto *P = dyn_cast<Paragraph>(N)) {
|
||||||
|
Converter.printTextAndInline(P->getContent());
|
||||||
|
Converter.printNewline();
|
||||||
|
Converter.printNewline();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Converter.printASTNode(N);
|
||||||
|
Converter.printNewline();
|
||||||
|
}
|
||||||
|
for (const auto *N : Parts.Params) {
|
||||||
|
Converter.printAsDoxygenParam(N);
|
||||||
|
Converter.printNewline();
|
||||||
|
}
|
||||||
|
for (const auto *N : Parts.Returns) {
|
||||||
|
Converter.printAsDoxygenReturns(N);
|
||||||
|
Converter.printNewline();
|
||||||
|
}
|
||||||
|
if (Converter.PendingNewlines != 0)
|
||||||
|
OS << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
//===- Utils.cpp - Misc utilities -----------------------------------------===//
|
//===--- Utils.cpp - Misc utilities ---------------------------------------===//
|
||||||
//
|
//
|
||||||
// This source file is part of the Swift.org open source project
|
// This source file is part of the Swift.org open source project
|
||||||
//
|
//
|
||||||
@@ -17,14 +17,9 @@
|
|||||||
#include "swift/AST/DiagnosticEngine.h"
|
#include "swift/AST/DiagnosticEngine.h"
|
||||||
#include "swift/AST/Module.h"
|
#include "swift/AST/Module.h"
|
||||||
#include "swift/AST/SearchPathOptions.h"
|
#include "swift/AST/SearchPathOptions.h"
|
||||||
#include "swift/AST/USRGeneration.h"
|
|
||||||
#include "swift/Parse/Parser.h"
|
#include "swift/Parse/Parser.h"
|
||||||
#include "swift/Parse/PersistentParserState.h"
|
#include "swift/Parse/PersistentParserState.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
|
||||||
#include "clang/AST/ASTContext.h"
|
|
||||||
#include "clang/AST/Decl.h"
|
|
||||||
#include "clang/Index/CommentToXML.h"
|
|
||||||
|
|
||||||
using namespace swift;
|
using namespace swift;
|
||||||
using namespace ide;
|
using namespace ide;
|
||||||
@@ -59,116 +54,3 @@ bool ide::isSourceInputComplete(StringRef Text) {
|
|||||||
return ide::isSourceInputComplete(std::move(InputBuf));
|
return ide::isSourceInputComplete(std::move(InputBuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: copied from Clang's
|
|
||||||
// CommentASTToXMLConverter::appendToResultWithXMLEscaping
|
|
||||||
static void appendWithXMLEscaping(raw_ostream &OS, StringRef S) {
|
|
||||||
for (const char C : S) {
|
|
||||||
switch (C) {
|
|
||||||
case '&':
|
|
||||||
OS << "&";
|
|
||||||
break;
|
|
||||||
case '<':
|
|
||||||
OS << "<";
|
|
||||||
break;
|
|
||||||
case '>':
|
|
||||||
OS << ">";
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
OS << """;
|
|
||||||
break;
|
|
||||||
case '\'':
|
|
||||||
OS << "'";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
OS << C;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool getClangDocumentationCommentAsXML(const clang::Decl *D,
|
|
||||||
raw_ostream &OS) {
|
|
||||||
const auto &ClangContext = D->getASTContext();
|
|
||||||
const clang::comments::FullComment *FC =
|
|
||||||
ClangContext.getCommentForDecl(D, /*PP=*/nullptr);
|
|
||||||
if (!FC)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// FIXME: hang the converter object somewhere so that it is persistent
|
|
||||||
// between requests to this AST.
|
|
||||||
clang::index::CommentToXMLConverter Converter;
|
|
||||||
|
|
||||||
llvm::SmallString<1024> XML;
|
|
||||||
Converter.convertCommentToXML(FC, XML, ClangContext);
|
|
||||||
OS << XML;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ide::getDocumentationCommentAsXML(const Decl *D, raw_ostream &OS) {
|
|
||||||
auto MaybeClangNode = D->getClangNode();
|
|
||||||
if (MaybeClangNode) {
|
|
||||||
if (auto *CD = MaybeClangNode.getAsDecl())
|
|
||||||
return getClangDocumentationCommentAsXML(CD, OS);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringRef BriefComment = D->getBriefComment();
|
|
||||||
if (BriefComment.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
StringRef RootEndTag;
|
|
||||||
if (isa<AbstractFunctionDecl>(D)) {
|
|
||||||
OS << "<Function";
|
|
||||||
RootEndTag = "</Function>";
|
|
||||||
} else {
|
|
||||||
OS << "<Other";
|
|
||||||
RootEndTag = "</Other>";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print line and column number.
|
|
||||||
SourceLoc Loc = D->getLoc();
|
|
||||||
if (Loc.isValid()) {
|
|
||||||
const auto &SM = D->getASTContext().SourceMgr;
|
|
||||||
unsigned BufferID = SM.findBufferContainingLoc(Loc);
|
|
||||||
StringRef FileName = SM->getMemoryBuffer(BufferID)->getBufferIdentifier();
|
|
||||||
auto LineAndColumn = SM.getLineAndColumn(Loc);
|
|
||||||
OS << " file=\"";
|
|
||||||
appendWithXMLEscaping(OS, FileName);
|
|
||||||
OS << "\"";
|
|
||||||
OS << " line=\"" << LineAndColumn.first
|
|
||||||
<< "\" column=\"" << LineAndColumn.second << "\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finish the root tag.
|
|
||||||
OS << ">";
|
|
||||||
|
|
||||||
auto *VD = dyn_cast<ValueDecl>(D);
|
|
||||||
|
|
||||||
OS << "<Name>";
|
|
||||||
if (VD && VD->hasName())
|
|
||||||
OS << VD->getFullName();
|
|
||||||
OS << "</Name>";
|
|
||||||
|
|
||||||
if (VD) {
|
|
||||||
llvm::SmallString<64> SS;
|
|
||||||
bool Failed;
|
|
||||||
{
|
|
||||||
llvm::raw_svector_ostream OS(SS);
|
|
||||||
Failed = ide::printDeclUSR(VD, OS);
|
|
||||||
}
|
|
||||||
if (!Failed && !SS.empty()) {
|
|
||||||
OS << "<USR>" << SS << "</USR>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: <Declaration>
|
|
||||||
OS << "<Abstract><Para>";
|
|
||||||
appendWithXMLEscaping(OS, BriefComment);
|
|
||||||
OS << "</Para></Abstract>";
|
|
||||||
|
|
||||||
OS << RootEndTag;
|
|
||||||
|
|
||||||
OS.flush();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,237 +19,15 @@
|
|||||||
#include "swift/Basic/Version.h"
|
#include "swift/Basic/Version.h"
|
||||||
#include "swift/Frontend/Frontend.h"
|
#include "swift/Frontend/Frontend.h"
|
||||||
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
|
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
|
||||||
#include "swift/ReST/AST.h"
|
#include "swift/IDE/CommentConversion.h"
|
||||||
#include "clang/AST/Decl.h"
|
#include "clang/AST/Decl.h"
|
||||||
#include "llvm/ADT/SetVector.h"
|
#include "llvm/ADT/SetVector.h"
|
||||||
#include "llvm/Support/Path.h"
|
#include "llvm/Support/Path.h"
|
||||||
#include "llvm/ADT/StringSwitch.h"
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
using namespace llvm::rest;
|
|
||||||
using namespace swift;
|
using namespace swift;
|
||||||
|
|
||||||
namespace {
|
|
||||||
struct CommentToDoxygenConverter {
|
|
||||||
raw_ostream &OS;
|
|
||||||
unsigned PendingNewlines = 1;
|
|
||||||
|
|
||||||
CommentToDoxygenConverter(raw_ostream &OS) : OS(OS) {}
|
|
||||||
|
|
||||||
void print(StringRef Text) {
|
|
||||||
for (unsigned i = 0; i != PendingNewlines; ++i) {
|
|
||||||
OS << "\n///";
|
|
||||||
if (i == PendingNewlines - 1)
|
|
||||||
OS << " ";
|
|
||||||
}
|
|
||||||
PendingNewlines = 0;
|
|
||||||
OS << Text;
|
|
||||||
}
|
|
||||||
|
|
||||||
void printNewline() {
|
|
||||||
PendingNewlines++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void printASTNode(const ReSTASTNode *N) {
|
|
||||||
switch (N->getKind()) {
|
|
||||||
case ASTNodeKind::Document:
|
|
||||||
llvm_unreachable("should never happen");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ASTNodeKind::Section:
|
|
||||||
case ASTNodeKind::Topic:
|
|
||||||
case ASTNodeKind::Sidebar:
|
|
||||||
case ASTNodeKind::Title:
|
|
||||||
case ASTNodeKind::Subtitle:
|
|
||||||
case ASTNodeKind::Transition:
|
|
||||||
llvm_unreachable("implement");
|
|
||||||
|
|
||||||
case ASTNodeKind::Paragraph:
|
|
||||||
printParagraph(cast<Paragraph>(N));
|
|
||||||
break;
|
|
||||||
case ASTNodeKind::BulletList:
|
|
||||||
printBulletList(cast<BulletList>(N));
|
|
||||||
break;
|
|
||||||
case ASTNodeKind::EnumeratedList:
|
|
||||||
printEnumeratedList(cast<EnumeratedList>(N));
|
|
||||||
break;
|
|
||||||
case ASTNodeKind::DefinitionListItem:
|
|
||||||
printDefinitionListItem(cast<DefinitionListItem>(N));
|
|
||||||
break;
|
|
||||||
case ASTNodeKind::DefinitionList:
|
|
||||||
printDefinitionList(cast<DefinitionList>(N));
|
|
||||||
break;
|
|
||||||
case ASTNodeKind::Field:
|
|
||||||
printField(cast<Field>(N));
|
|
||||||
break;
|
|
||||||
case ASTNodeKind::FieldList:
|
|
||||||
printFieldList(cast<FieldList>(N));
|
|
||||||
break;
|
|
||||||
case ASTNodeKind::BlockQuote:
|
|
||||||
printBlockQuote(cast<BlockQuote>(N));
|
|
||||||
break;
|
|
||||||
case ASTNodeKind::TextAndInline:
|
|
||||||
printTextAndInline(cast<TextAndInline>(N));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void printParagraph(const Paragraph *P) {
|
|
||||||
print("<p>");
|
|
||||||
printTextAndInline(P->getContent());
|
|
||||||
print("</p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
void printBulletList(const BulletList *BL) {
|
|
||||||
print("<ul>");
|
|
||||||
for (unsigned i = 0, e = BL->getNumItems(); i != e; ++i) {
|
|
||||||
print("<li>");
|
|
||||||
for (const auto *N : BL->getItemChildren(i)) {
|
|
||||||
printASTNode(N);
|
|
||||||
}
|
|
||||||
print("</li>");
|
|
||||||
}
|
|
||||||
print("</ul>");
|
|
||||||
}
|
|
||||||
|
|
||||||
void printEnumeratedList(const EnumeratedList *EL) {
|
|
||||||
print("<ol>");
|
|
||||||
for (unsigned i = 0, e = EL->getNumItems(); i != e; ++i) {
|
|
||||||
print("<li>");
|
|
||||||
for (const auto *N : EL->getItemChildren(i)) {
|
|
||||||
printASTNode(N);
|
|
||||||
}
|
|
||||||
print("</li>");
|
|
||||||
}
|
|
||||||
print("</ol>");
|
|
||||||
}
|
|
||||||
|
|
||||||
void printDefinitionListItem(const DefinitionListItem *DLI) {
|
|
||||||
print("<dt>");
|
|
||||||
printASTNode(DLI->getTerm());
|
|
||||||
for (const auto *N : DLI->getClassifiers()) {
|
|
||||||
printASTNode(N);
|
|
||||||
}
|
|
||||||
print("</dt>");
|
|
||||||
|
|
||||||
print("<dd>");
|
|
||||||
for (const auto *N : DLI->getDefinitionChildren()) {
|
|
||||||
printASTNode(N);
|
|
||||||
}
|
|
||||||
print("</dd>");
|
|
||||||
}
|
|
||||||
|
|
||||||
void printDefinitionList(const DefinitionList *DL) {
|
|
||||||
print("<dl>");
|
|
||||||
for (const auto *N : DL->getChildren()) {
|
|
||||||
printASTNode(N);
|
|
||||||
}
|
|
||||||
print("</dl>");
|
|
||||||
}
|
|
||||||
|
|
||||||
void printField(const Field *F) {
|
|
||||||
print("<dt>");
|
|
||||||
printASTNode(F->getName());
|
|
||||||
print("</dt>");
|
|
||||||
print("<dd>");
|
|
||||||
for (const auto *N : F->getBodyChildren()) {
|
|
||||||
printASTNode(N);
|
|
||||||
}
|
|
||||||
print("</dd>");
|
|
||||||
}
|
|
||||||
|
|
||||||
void printFieldList(const FieldList *FL) {
|
|
||||||
print("<dl>");
|
|
||||||
for (const auto *F : FL->getChildren()) {
|
|
||||||
printASTNode(F);
|
|
||||||
}
|
|
||||||
print("</dl>");
|
|
||||||
}
|
|
||||||
|
|
||||||
void printBlockQuote(const BlockQuote *BQ) {
|
|
||||||
print("<blockquote>");
|
|
||||||
for (const auto *N : BQ->getChildren()) {
|
|
||||||
printASTNode(N);
|
|
||||||
}
|
|
||||||
print("</blockquote>");
|
|
||||||
}
|
|
||||||
|
|
||||||
void printTextAndInline(const TextAndInline *T) {
|
|
||||||
if (T->isLinePart()) {
|
|
||||||
LinePart LP = T->getLinePart();
|
|
||||||
print(LP.Text);
|
|
||||||
} else {
|
|
||||||
LineListRef LL = T->getLines();
|
|
||||||
for (unsigned i = 0, e = LL.size(); i != e; ++i) {
|
|
||||||
print(LL[i].Text.drop_front(LL[i].FirstTextByte));
|
|
||||||
if (i != e - 1)
|
|
||||||
printNewline();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void printOrphanField(const Field *F) {
|
|
||||||
print("<dl>");
|
|
||||||
printField(F);
|
|
||||||
print("</dl>");
|
|
||||||
}
|
|
||||||
|
|
||||||
void printBlockCommandContent(ArrayRef<const ReSTASTNode *> Nodes) {
|
|
||||||
if (Nodes.size() == 1) {
|
|
||||||
if (const auto *P = dyn_cast<Paragraph>(Nodes[0])) {
|
|
||||||
printTextAndInline(P->getContent());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const auto *N : Nodes) {
|
|
||||||
printASTNode(N);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void printAsDoxygenParam(const Field *F) {
|
|
||||||
print("\\param ");
|
|
||||||
printBlockCommandContent(F->getBodyChildren());
|
|
||||||
printNewline();
|
|
||||||
}
|
|
||||||
|
|
||||||
void printAsDoxygenReturns(const Field *F) {
|
|
||||||
print("\\returns ");
|
|
||||||
printBlockCommandContent(F->getBodyChildren());
|
|
||||||
printNewline();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // unnamed namespace
|
|
||||||
|
|
||||||
static void convertCommentToDoxygen(const FullComment *FC, raw_ostream &OS) {
|
|
||||||
CommentToDoxygenConverter Converter(OS);
|
|
||||||
auto &Parts = FC->getParts();
|
|
||||||
for (const auto *N : Parts.MiscTopLevelNodes) {
|
|
||||||
if (const auto *F = dyn_cast<Field>(N)) {
|
|
||||||
Converter.printOrphanField(F);
|
|
||||||
Converter.printNewline();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (const auto *P = dyn_cast<Paragraph>(N)) {
|
|
||||||
Converter.printTextAndInline(P->getContent());
|
|
||||||
Converter.printNewline();
|
|
||||||
Converter.printNewline();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Converter.printASTNode(N);
|
|
||||||
Converter.printNewline();
|
|
||||||
}
|
|
||||||
for (const auto *N : Parts.Params) {
|
|
||||||
Converter.printAsDoxygenParam(N);
|
|
||||||
Converter.printNewline();
|
|
||||||
}
|
|
||||||
for (const auto *N : Parts.Returns) {
|
|
||||||
Converter.printAsDoxygenReturns(N);
|
|
||||||
Converter.printNewline();
|
|
||||||
}
|
|
||||||
if (Converter.PendingNewlines != 0)
|
|
||||||
OS << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
|
class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
|
||||||
private TypeVisitor<ObjCPrinter> {
|
private TypeVisitor<ObjCPrinter> {
|
||||||
@@ -336,7 +114,7 @@ private:
|
|||||||
void printDocumentationComment(Decl *D) {
|
void printDocumentationComment(Decl *D) {
|
||||||
CommentContext TheCommentContext;
|
CommentContext TheCommentContext;
|
||||||
if (auto *FC = getFullComment(TheCommentContext, D))
|
if (auto *FC = getFullComment(TheCommentContext, D))
|
||||||
convertCommentToDoxygen(FC, os);
|
ide::getDocumentationCommentAsDoxygen(FC, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitClassDecl(ClassDecl *CD) {
|
void visitClassDecl(ClassDecl *CD) {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "swift/ReST/Parser.h"
|
#include "swift/ReST/Parser.h"
|
||||||
#include "Detail.h"
|
#include "Detail.h"
|
||||||
#include "swift/ReST/LineList.h"
|
#include "swift/ReST/LineList.h"
|
||||||
|
#include "swift/ReST/XMLUtils.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "clang/Basic/CharInfo.h"
|
#include "clang/Basic/CharInfo.h"
|
||||||
|
|
||||||
@@ -950,11 +951,11 @@ struct CommentToDocutilsXMLConverter {
|
|||||||
void printTextAndInline(const TextAndInline *T) {
|
void printTextAndInline(const TextAndInline *T) {
|
||||||
if (T->isLinePart()) {
|
if (T->isLinePart()) {
|
||||||
LinePart LP = T->getLinePart();
|
LinePart LP = T->getLinePart();
|
||||||
OS << LP.Text;
|
appendWithXMLEscaping(OS, LP.Text);
|
||||||
} else {
|
} else {
|
||||||
LineListRef LL = T->getLines();
|
LineListRef LL = T->getLines();
|
||||||
for (unsigned i = 0, e = LL.size(); i != e; ++i) {
|
for (unsigned i = 0, e = LL.size(); i != e; ++i) {
|
||||||
OS << LL[i].Text.drop_front(LL[i].FirstTextByte);
|
appendWithXMLEscaping(OS, LL[i].Text.drop_front(LL[i].FirstTextByte));
|
||||||
if (i != e - 1)
|
if (i != e - 1)
|
||||||
OS << '\n';
|
OS << '\n';
|
||||||
}
|
}
|
||||||
|
|||||||
9
test/IDE/comment_to_xml.swift
Normal file
9
test/IDE/comment_to_xml.swift
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
//===--- Check that we convert comments to XML correctly.
|
||||||
|
|
||||||
|
// RUN: %swift -parse -verify %S/../Inputs/comment_to_something_conversion.swift
|
||||||
|
// RUN: %swift-ide-test -print-comments -source-filename %S/../Inputs/comment_to_something_conversion.swift -comments-xml-schema %S/../../bindings/xml/comment-xml-schema.rng > %t.txt
|
||||||
|
// RUN: FileCheck %S/../Inputs/comment_to_something_conversion.swift < %t.txt
|
||||||
|
// RUN: FileCheck %s -check-prefix=WRONG < %t.txt
|
||||||
|
|
||||||
|
// WRONG-NOT: CommentXMLInvalid
|
||||||
|
|
||||||
183
test/Inputs/comment_to_something_conversion.swift
Normal file
183
test/Inputs/comment_to_something_conversion.swift
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
// This is an input file for comment-to-{XML,Doxygen} conversion tests.
|
||||||
|
//
|
||||||
|
// Please keep this file in alphabetical order!
|
||||||
|
|
||||||
|
@objc class A000 {}
|
||||||
|
// CHECK:.swift:[[@LINE-1]]:13: Class/A000 {{.*}} FullCommentAsXML=none
|
||||||
|
|
||||||
|
/// Aaa. A010. Bbb.
|
||||||
|
@objc class A010_AttachToEntities {
|
||||||
|
// CHECK: swift:[[@LINE-1]]:13: Class/A010_AttachToEntities {{.*}} FullCommentAsXML=[<Other file="{{[^"]+}}swift" line="[[@LINE-1]]" column="13"><Name>A010_AttachToEntities</Name><USR>s:C14swift_ide_test21A010_AttachToEntities</USR><Abstract><Para>Aaa. A010. Bbb.</Para></Abstract></Other>]
|
||||||
|
|
||||||
|
/// Aaa. init().
|
||||||
|
init() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:3: Constructor/A010_AttachToEntities.init {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="3"><Name>init()</Name><USR>s:FC14swift_ide_test21A010_AttachToEntitiescFMS0_FT_S0_</USR><Abstract><Para>Aaa. init().</Para></Abstract></Function>]
|
||||||
|
|
||||||
|
/// Aaa. subscript(i: Int).
|
||||||
|
subscript(i: Int) -> Int {
|
||||||
|
// CHECK: swift:[[@LINE-1]]:3: Subscript/A010_AttachToEntities.subscript {{.*}} FullCommentAsXML=[<Other file="{{[^"]+}}swift" line="[[@LINE-1]]" column="3"><Name>subscript</Name><USR>s:sC14swift_ide_test21A010_AttachToEntities9subscriptFT1iSi_Si</USR><Abstract><Para>Aaa. subscript(i: Int).</Para></Abstract></Other>]
|
||||||
|
get {
|
||||||
|
// CHECK: swift:[[@LINE-1]]:5: Func/A010_AttachToEntities.<getter for A010_AttachToEntities.subscript> {{.*}} FullCommentAsXML=none
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
set {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:5: Func/A010_AttachToEntities.<setter for A010_AttachToEntities.subscript> {{.*}} FullCommentAsXML=none
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Aaa. v1.
|
||||||
|
var v1: Int = 0
|
||||||
|
// CHECK: swift:[[@LINE-1]]:7: Var/A010_AttachToEntities.v1 {{.*}} FullCommentAsXML=[<Other file="{{[^"]+}}swift" line="[[@LINE-1]]" column="7"><Name>v1</Name><USR>s:vC14swift_ide_test21A010_AttachToEntities2v1Si</USR><Abstract><Para>Aaa. v1.</Para></Abstract></Other>]
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc class A100_EmptyComments {
|
||||||
|
///
|
||||||
|
func f0() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A100_EmptyComments.f0 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f0()</Name><USR>s:FC14swift_ide_test18A100_EmptyComments2f0FS0_FT_T_</USR></Function>]
|
||||||
|
|
||||||
|
/// Aaa.
|
||||||
|
func f1() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A100_EmptyComments.f1 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f1()</Name><USR>s:FC14swift_ide_test18A100_EmptyComments2f1FS0_FT_T_</USR><Abstract><Para>Aaa.</Para></Abstract></Function>]
|
||||||
|
|
||||||
|
/** */
|
||||||
|
func f2() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A100_EmptyComments.f2 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f2()</Name><USR>s:FC14swift_ide_test18A100_EmptyComments2f2FS0_FT_T_</USR></Function>]
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
func f3() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A100_EmptyComments.f3 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f3()</Name><USR>s:FC14swift_ide_test18A100_EmptyComments2f3FS0_FT_T_</USR></Function>]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aaa.
|
||||||
|
*/
|
||||||
|
func f4() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A100_EmptyComments.f4 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f4()</Name><USR>s:FC14swift_ide_test18A100_EmptyComments2f4FS0_FT_T_</USR><Discussion><Para>Aaa.</Para></Discussion></Function>]
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc class A110_Escaping {
|
||||||
|
/// & < > " '
|
||||||
|
func f0() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A110_Escaping.f0 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f0()</Name><USR>s:FC14swift_ide_test13A110_Escaping2f0FS0_FT_T_</USR><Abstract><Para>& < > " '</Para></Abstract></Function>]
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc class A120_Brief {
|
||||||
|
/// Aaa.
|
||||||
|
func f0() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A120_Brief.f0 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f0()</Name><USR>s:FC14swift_ide_test10A120_Brief2f0FS0_FT_T_</USR><Abstract><Para>Aaa.</Para></Abstract></Function>]
|
||||||
|
|
||||||
|
/// Aaa.
|
||||||
|
///
|
||||||
|
/// Bbb.
|
||||||
|
func f1() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A120_Brief.f1 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f1()</Name><USR>s:FC14swift_ide_test10A120_Brief2f1FS0_FT_T_</USR><Abstract><Para>Aaa.</Para></Abstract><Discussion><Para>Bbb.</Para></Discussion></Function>]
|
||||||
|
|
||||||
|
///Aaa.
|
||||||
|
///
|
||||||
|
/// Bbb.
|
||||||
|
func f2() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A120_Brief.f2 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f2()</Name><USR>s:FC14swift_ide_test10A120_Brief2f2FS0_FT_T_</USR><Abstract><Para>Aaa.</Para></Abstract><Discussion><Para>Bbb.</Para></Discussion></Function>]
|
||||||
|
|
||||||
|
///Aaa.
|
||||||
|
///
|
||||||
|
///Bbb.
|
||||||
|
func f3() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A120_Brief.f3 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f3()</Name><USR>s:FC14swift_ide_test10A120_Brief2f3FS0_FT_T_</USR><Abstract><Para>Aaa.</Para></Abstract><Discussion><Para>Bbb.</Para></Discussion></Function>]
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc class A200_ParamAndReturns {
|
||||||
|
/// Aaa. f0.
|
||||||
|
///
|
||||||
|
/// :param: first Bbb.
|
||||||
|
///
|
||||||
|
/// :param: second Ccc. Ddd.
|
||||||
|
/// Eee.
|
||||||
|
func f0(first: Int, second: Double) {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A200_ParamAndReturns.f0 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f0(first:second:)</Name><USR>s:FC14swift_ide_test20A200_ParamAndReturns2f0FS0_FT5firstSi6secondSd_T_</USR><Abstract><Para>Aaa. f0.</Para></Abstract><Parameters><Parameter><Name>x</Name><Direction isExplicit="0">in</Direction><Discussion><Para>first Bbb.</Para></Discussion></Parameter><Parameter><Name>x</Name><Direction isExplicit="0">in</Direction><Discussion><Para>second Ccc. Ddd. Eee.</Para></Discussion></Parameter></Parameters></Function>]
|
||||||
|
|
||||||
|
/// Aaa. f1.
|
||||||
|
///
|
||||||
|
/// :param: first Bbb.
|
||||||
|
///
|
||||||
|
/// :returns: Ccc.
|
||||||
|
/// Ddd.
|
||||||
|
func f1(first: Int) {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A200_ParamAndReturns.f1 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f1(first:)</Name><USR>s:FC14swift_ide_test20A200_ParamAndReturns2f1FS0_FT5firstSi_T_</USR><Abstract><Para>Aaa. f1.</Para></Abstract><Parameters><Parameter><Name>x</Name><Direction isExplicit="0">in</Direction><Discussion><Para>first Bbb.</Para></Discussion></Parameter></Parameters><ResultDiscussion><Para>Ccc. Ddd.</Para></ResultDiscussion></Function>]
|
||||||
|
|
||||||
|
/// Aaa. f2.
|
||||||
|
///
|
||||||
|
/// :returns: Ccc.
|
||||||
|
/// Ddd.
|
||||||
|
///
|
||||||
|
/// :returns: Eee.
|
||||||
|
/// Fff.
|
||||||
|
func f2() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A200_ParamAndReturns.f2 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f2()</Name><USR>s:FC14swift_ide_test20A200_ParamAndReturns2f2FS0_FT_T_</USR><Abstract><Para>Aaa. f2.</Para></Abstract><ResultDiscussion><Para>Ccc. Ddd.</Para><Para>Eee. Fff.</Para></ResultDiscussion></Function>]
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc class A210_BulletList {
|
||||||
|
/// * Aaa.
|
||||||
|
///
|
||||||
|
/// * Bbb.
|
||||||
|
/// Ccc.
|
||||||
|
func f0() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A210_BulletList.f0 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f0()</Name><USR>s:FC14swift_ide_test15A210_BulletList2f0FS0_FT_T_</USR><Discussion><Para>Aaa.</Para><Para>Bbb. Ccc.</Para></Discussion></Function>]
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc class A220_EnumeratedList {
|
||||||
|
/// 1. Aaa.
|
||||||
|
///
|
||||||
|
/// 2. Bbb.
|
||||||
|
/// Ccc.
|
||||||
|
func f0() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A220_EnumeratedList.f0 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f0()</Name><USR>s:FC14swift_ide_test19A220_EnumeratedList2f0FS0_FT_T_</USR><Discussion><Para>Aaa.</Para><Para>Bbb. Ccc.</Para></Discussion></Function>]
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc class A230_DefinitionList {
|
||||||
|
/// Aaa
|
||||||
|
/// Bbb.
|
||||||
|
///
|
||||||
|
/// Ccc
|
||||||
|
/// Ddd.
|
||||||
|
///
|
||||||
|
/// Eee : Fff
|
||||||
|
/// Ggg.
|
||||||
|
///
|
||||||
|
/// ``Hhh``
|
||||||
|
/// Jjj.
|
||||||
|
func f0() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A230_DefinitionList.f0 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f0()</Name><USR>s:FC14swift_ide_test19A230_DefinitionList2f0FS0_FT_T_</USR><Discussion><Para>Aaa</Para><Para>Bbb.</Para><Para>Ccc</Para><Para>Ddd.</Para><Para>Eee : Fff</Para><Para>Ggg.</Para><Para>``Hhh``</Para><Para>Jjj.</Para></Discussion></Function>]
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc class A240_FieldList {
|
||||||
|
/// :unknown: Aaa.
|
||||||
|
/// Bbb.
|
||||||
|
func f0() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A240_FieldList.f0 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f0()</Name><USR>s:FC14swift_ide_test14A240_FieldList2f0FS0_FT_T_</USR><Discussion><Para>unknown</Para><Para>Aaa. Bbb.</Para></Discussion></Function>]
|
||||||
|
|
||||||
|
/// * Aaa.
|
||||||
|
///
|
||||||
|
/// :param: Aaa.
|
||||||
|
/// :returns: Bbb.
|
||||||
|
/// :unknown: Ccc.
|
||||||
|
func f1() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A240_FieldList.f1 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f1()</Name><USR>s:FC14swift_ide_test14A240_FieldList2f1FS0_FT_T_</USR><Discussion><Para>Aaa.</Para><Para>param</Para><Para>Aaa. :returns: Bbb. :unknown: Ccc.</Para></Discussion></Function>]
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc class A250_OptionList {
|
||||||
|
/// -a Aaa.
|
||||||
|
/// -b Bbb.
|
||||||
|
/// Ccc.
|
||||||
|
func f0() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A250_OptionList.f0 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f0()</Name><USR>s:FC14swift_ide_test15A250_OptionList2f0FS0_FT_T_</USR><Abstract><Para>-a Aaa. -b Bbb.</Para></Abstract><Discussion><Para>Ccc.</Para></Discussion></Function>]
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc class A260_BlockQuote {
|
||||||
|
/// Aaa.
|
||||||
|
///
|
||||||
|
/// Bbb.
|
||||||
|
///
|
||||||
|
/// Ccc.
|
||||||
|
func f0() {}
|
||||||
|
// CHECK: swift:[[@LINE-1]]:8: Func/A260_BlockQuote.f0 {{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}swift" line="[[@LINE-1]]" column="8"><Name>f0()</Name><USR>s:FC14swift_ide_test15A260_BlockQuote2f0FS0_FT_T_</USR><Abstract><Para>Aaa.</Para></Abstract><Discussion><Para>Bbb.</Para><Para>Ccc.</Para></Discussion></Function>]
|
||||||
|
}
|
||||||
|
|
||||||
@@ -5,9 +5,22 @@ SWIFT_CLASS("_TtC8comments4A000")
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Aaa. A10. Bbb.
|
/// Aaa. A010. Bbb.
|
||||||
SWIFT_CLASS("_TtC8comments4A010")
|
SWIFT_CLASS("_TtC8comments21A010_AttachToEntities")
|
||||||
@interface A010
|
@interface A010_AttachToEntities
|
||||||
|
|
||||||
|
/// Aaa. init().
|
||||||
|
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
|
||||||
|
- (NSInteger)objectAtIndexedSubscript:(NSInteger)i;
|
||||||
|
- (void)setObject:(NSInteger)newValue atIndexedSubscript:(NSInteger)i;
|
||||||
|
|
||||||
|
/// Aaa. v1.
|
||||||
|
@property (nonatomic) NSInteger v1;
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
SWIFT_CLASS("_TtC8comments18A100_EmptyComments")
|
||||||
|
@interface A100_EmptyComments
|
||||||
|
|
||||||
- (void)f0;
|
- (void)f0;
|
||||||
|
|
||||||
@@ -20,44 +33,76 @@ SWIFT_CLASS("_TtC8comments4A010")
|
|||||||
|
|
||||||
/// <ul><li><p>Aaa.</p></li></ul>
|
/// <ul><li><p>Aaa.</p></li></ul>
|
||||||
- (void)f4;
|
- (void)f4;
|
||||||
|
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
|
||||||
|
@end
|
||||||
|
|
||||||
/// Aaa. f5.
|
|
||||||
|
SWIFT_CLASS("_TtC8comments13A110_Escaping")
|
||||||
|
@interface A110_Escaping
|
||||||
|
|
||||||
|
/// & < > " '
|
||||||
|
- (void)f0;
|
||||||
|
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
SWIFT_CLASS("_TtC8comments10A120_Brief")
|
||||||
|
@interface A120_Brief
|
||||||
|
|
||||||
|
/// Aaa.
|
||||||
|
- (void)f0;
|
||||||
|
|
||||||
|
/// Aaa.
|
||||||
|
///
|
||||||
|
/// Bbb.
|
||||||
|
- (void)f1;
|
||||||
|
|
||||||
|
/// Aaa.
|
||||||
|
///
|
||||||
|
/// <blockquote><p>Bbb.</p></blockquote>
|
||||||
|
- (void)f2;
|
||||||
|
|
||||||
|
/// Aaa.
|
||||||
|
///
|
||||||
|
/// Bbb.
|
||||||
|
- (void)f3;
|
||||||
|
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
SWIFT_CLASS("_TtC8comments20A200_ParamAndReturns")
|
||||||
|
@interface A200_ParamAndReturns
|
||||||
|
|
||||||
|
/// Aaa. f0.
|
||||||
///
|
///
|
||||||
/// \param first Bbb.
|
/// \param first Bbb.
|
||||||
///
|
///
|
||||||
/// \param second Ccc. Ddd.
|
/// \param second Ccc. Ddd.
|
||||||
/// Eee.
|
/// Eee.
|
||||||
- (void)f5:(NSInteger)first second:(double)second;
|
- (void)f0:(NSInteger)first second:(double)second;
|
||||||
|
|
||||||
/// Aaa. f6.
|
/// Aaa. f1.
|
||||||
///
|
///
|
||||||
/// \param first Bbb.
|
/// \param first Bbb.
|
||||||
///
|
///
|
||||||
/// \returns Ccc.
|
/// \returns Ccc.
|
||||||
/// Ddd.
|
/// Ddd.
|
||||||
- (void)f6:(NSInteger)first;
|
- (void)f1:(NSInteger)first;
|
||||||
|
|
||||||
/// Aaa. f7.
|
/// Aaa. f2.
|
||||||
///
|
///
|
||||||
/// \returns Ccc.
|
/// \returns Ccc.
|
||||||
/// Ddd.
|
/// Ddd.
|
||||||
///
|
///
|
||||||
/// \returns Eee.
|
/// \returns Eee.
|
||||||
/// Fff.
|
/// Fff.
|
||||||
- (void)f7;
|
- (void)f2;
|
||||||
|
|
||||||
/// Aaa. init().
|
|
||||||
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
|
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
|
||||||
- (NSInteger)objectAtIndexedSubscript:(NSInteger)i;
|
|
||||||
- (void)setObject:(NSInteger)newValue atIndexedSubscript:(NSInteger)i;
|
|
||||||
|
|
||||||
/// Aaa. v1.
|
|
||||||
@property (nonatomic) NSInteger v1;
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
SWIFT_CLASS("_TtC8comments15A020_BulletList")
|
SWIFT_CLASS("_TtC8comments15A210_BulletList")
|
||||||
@interface A020_BulletList
|
@interface A210_BulletList
|
||||||
|
|
||||||
/// <ul><li><p>Aaa.</p></li><li><p>Bbb.
|
/// <ul><li><p>Aaa.</p></li><li><p>Bbb.
|
||||||
/// Ccc.</p></li></ul>
|
/// Ccc.</p></li></ul>
|
||||||
@@ -66,8 +111,8 @@ SWIFT_CLASS("_TtC8comments15A020_BulletList")
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
SWIFT_CLASS("_TtC8comments19A030_EnumeratedList")
|
SWIFT_CLASS("_TtC8comments19A220_EnumeratedList")
|
||||||
@interface A030_EnumeratedList
|
@interface A220_EnumeratedList
|
||||||
|
|
||||||
/// <ol><li><p>Aaa.</p></li><li><p>Bbb.
|
/// <ol><li><p>Aaa.</p></li><li><p>Bbb.
|
||||||
/// Ccc.</p></li></ol>
|
/// Ccc.</p></li></ol>
|
||||||
@@ -76,8 +121,8 @@ SWIFT_CLASS("_TtC8comments19A030_EnumeratedList")
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
SWIFT_CLASS("_TtC8comments19A040_DefinitionList")
|
SWIFT_CLASS("_TtC8comments19A230_DefinitionList")
|
||||||
@interface A040_DefinitionList
|
@interface A230_DefinitionList
|
||||||
|
|
||||||
/// <dl><dt>Aaa</dt><dd><p>Bbb.</p></dd><dt>Ccc</dt><dd><p>Ddd.</p></dd><dt>Eee : Fff</dt><dd><p>Ggg.</p></dd><dt>``Hhh``</dt><dd><p>Jjj.</p></dd></dl>
|
/// <dl><dt>Aaa</dt><dd><p>Bbb.</p></dd><dt>Ccc</dt><dd><p>Ddd.</p></dd><dt>Eee : Fff</dt><dd><p>Ggg.</p></dd><dt>``Hhh``</dt><dd><p>Jjj.</p></dd></dl>
|
||||||
- (void)f0;
|
- (void)f0;
|
||||||
@@ -85,18 +130,23 @@ SWIFT_CLASS("_TtC8comments19A040_DefinitionList")
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
SWIFT_CLASS("_TtC8comments14A050_FieldList")
|
SWIFT_CLASS("_TtC8comments14A240_FieldList")
|
||||||
@interface A050_FieldList
|
@interface A240_FieldList
|
||||||
|
|
||||||
/// <dl><dt>unknown</dt><dd><p>Aaa.
|
/// <dl><dt>unknown</dt><dd><p>Aaa.
|
||||||
/// Bbb.</p></dd></dl>
|
/// Bbb.</p></dd></dl>
|
||||||
- (void)f0;
|
- (void)f0;
|
||||||
|
|
||||||
|
/// <ul><li><p>Aaa.</p><dl><dt>param</dt><dd><p>Aaa.
|
||||||
|
/// :returns: Bbb.
|
||||||
|
/// :unknown: Ccc.</p></dd></dl></li></ul>
|
||||||
|
- (void)f1;
|
||||||
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
|
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
SWIFT_CLASS("_TtC8comments15A060_OptionList")
|
SWIFT_CLASS("_TtC8comments15A250_OptionList")
|
||||||
@interface A060_OptionList
|
@interface A250_OptionList
|
||||||
|
|
||||||
/// -a Aaa.
|
/// -a Aaa.
|
||||||
/// -b Bbb.
|
/// -b Bbb.
|
||||||
@@ -107,8 +157,8 @@ SWIFT_CLASS("_TtC8comments15A060_OptionList")
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
SWIFT_CLASS("_TtC8comments15A070_BlockQuote")
|
SWIFT_CLASS("_TtC8comments15A260_BlockQuote")
|
||||||
@interface A070_BlockQuote
|
@interface A260_BlockQuote
|
||||||
|
|
||||||
/// Aaa.
|
/// Aaa.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
add_swift_executable(swift-ide-test
|
add_swift_executable(swift-ide-test
|
||||||
swift-ide-test.cpp
|
swift-ide-test.cpp
|
||||||
|
XMLValidator.cpp
|
||||||
DEPENDS swiftFrontend swiftIDE
|
DEPENDS swiftFrontend swiftIDE
|
||||||
COMPONENT_DEPENDS bitreader bitwriter support ${LLVM_TARGETS_TO_BUILD})
|
COMPONENT_DEPENDS bitreader bitwriter support ${LLVM_TARGETS_TO_BUILD})
|
||||||
|
|
||||||
@@ -7,6 +8,13 @@ if(MODULES_SDK)
|
|||||||
add_definitions( -DSWIFT_MODULES_SDK="${MODULES_SDK}" )
|
add_definitions( -DSWIFT_MODULES_SDK="${MODULES_SDK}" )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# If libxml2 is available, make it available for swift-ide-test.
|
||||||
|
if (SWIFT_HAVE_LIBXML)
|
||||||
|
include_directories(SYSTEM ${LIBXML2_INCLUDE_DIR})
|
||||||
|
target_link_libraries(swift-ide-test ${LIBXML2_LIBRARIES})
|
||||||
|
add_definitions( -DSWIFT_HAVE_LIBXML="1" )
|
||||||
|
endif()
|
||||||
|
|
||||||
install(TARGETS swift-ide-test
|
install(TARGETS swift-ide-test
|
||||||
RUNTIME DESTINATION bin)
|
RUNTIME DESTINATION bin)
|
||||||
|
|
||||||
|
|||||||
96
tools/swift-ide-test/XMLValidator.cpp
Normal file
96
tools/swift-ide-test/XMLValidator.cpp
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
//===-- XMLValidator.cpp - XML validation ---------------------------------===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See http://swift.org/LICENSE.txt for license information
|
||||||
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "XMLValidator.h"
|
||||||
|
|
||||||
|
#ifdef SWIFT_HAVE_LIBXML
|
||||||
|
|
||||||
|
// libxml headers use their own variant of documentation comments that Clang
|
||||||
|
// does not understand well.
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdocumentation"
|
||||||
|
|
||||||
|
#include <libxml/parser.h>
|
||||||
|
#include <libxml/relaxng.h>
|
||||||
|
#include <libxml/xmlerror.h>
|
||||||
|
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
|
using namespace swift;
|
||||||
|
|
||||||
|
struct XMLValidator::Implementation {
|
||||||
|
std::string SchemaFileName;
|
||||||
|
xmlRelaxNGParserCtxtPtr RNGParser;
|
||||||
|
xmlRelaxNGPtr Schema;
|
||||||
|
};
|
||||||
|
|
||||||
|
XMLValidator::XMLValidator() : Impl(new Implementation()) {}
|
||||||
|
|
||||||
|
XMLValidator::~XMLValidator() { delete Impl; }
|
||||||
|
|
||||||
|
void XMLValidator::setSchema(StringRef FileName) {
|
||||||
|
assert(Impl->SchemaFileName.empty());
|
||||||
|
Impl->SchemaFileName = FileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLValidator::Status XMLValidator::validate(const std::string &XML) {
|
||||||
|
if (Impl->SchemaFileName.empty())
|
||||||
|
return Status{ErrorCode::NoSchema, ""};
|
||||||
|
|
||||||
|
if (!Impl->RNGParser) {
|
||||||
|
Impl->RNGParser = xmlRelaxNGNewParserCtxt(Impl->SchemaFileName.c_str());
|
||||||
|
Impl->Schema = xmlRelaxNGParse(Impl->RNGParser);
|
||||||
|
}
|
||||||
|
if (!Impl->RNGParser)
|
||||||
|
return Status{ErrorCode::InternalError, ""};
|
||||||
|
|
||||||
|
if (!Impl->Schema)
|
||||||
|
return Status{ErrorCode::BadSchema, ""};
|
||||||
|
|
||||||
|
xmlDocPtr Doc = xmlParseDoc(reinterpret_cast<const xmlChar *>(XML.data()));
|
||||||
|
if (!Doc)
|
||||||
|
return Status{ErrorCode::NotWellFormed, xmlGetLastError()->message};
|
||||||
|
|
||||||
|
xmlRelaxNGValidCtxtPtr ValidationCtxt = xmlRelaxNGNewValidCtxt(Impl->Schema);
|
||||||
|
int ValidationStatus = xmlRelaxNGValidateDoc(ValidationCtxt, Doc);
|
||||||
|
Status Result;
|
||||||
|
if (ValidationStatus == 0) {
|
||||||
|
Result = Status{ErrorCode::Valid, ""};
|
||||||
|
} else if (ValidationStatus > 0) {
|
||||||
|
Result = Status{ErrorCode::NotValid, xmlGetLastError()->message};
|
||||||
|
} else
|
||||||
|
Result = Status{ErrorCode::InternalError, ""};
|
||||||
|
|
||||||
|
xmlRelaxNGFreeValidCtxt(ValidationCtxt);
|
||||||
|
xmlFreeDoc(Doc);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // !SWIFT_HAVE_LIBXML
|
||||||
|
|
||||||
|
using namespace swift;
|
||||||
|
|
||||||
|
struct XMLValidator::Implementation {};
|
||||||
|
|
||||||
|
XMLValidator::XMLValidator() : Impl(new Implementation()) {}
|
||||||
|
|
||||||
|
XMLValidator::~XMLValidator() { delete Impl; }
|
||||||
|
|
||||||
|
void XMLValidator::setSchema(StringRef FileName) {}
|
||||||
|
|
||||||
|
XMLValidator::Status XMLValidator::validate(const std::string &XML) {
|
||||||
|
return Status{ErrorCode::NotCompiledIn, ""};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SWIFT_HAVE_LIBXML
|
||||||
|
|
||||||
51
tools/swift-ide-test/XMLValidator.h
Normal file
51
tools/swift-ide-test/XMLValidator.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
//===-- XMLValidator.h - XML validation -----------------------------------===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See http://swift.org/LICENSE.txt for license information
|
||||||
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef SWIFT_IDE_TEST_XML_VALIDATOR_H
|
||||||
|
#define SWIFT_IDE_TEST_XML_VALIDATOR_H
|
||||||
|
|
||||||
|
#include "swift/Basic/LLVM.h"
|
||||||
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
|
||||||
|
namespace swift {
|
||||||
|
|
||||||
|
class XMLValidator {
|
||||||
|
struct Implementation;
|
||||||
|
Implementation *Impl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
XMLValidator();
|
||||||
|
~XMLValidator();
|
||||||
|
|
||||||
|
void setSchema(StringRef FileName);
|
||||||
|
|
||||||
|
enum class ErrorCode {
|
||||||
|
Valid,
|
||||||
|
NotCompiledIn,
|
||||||
|
NoSchema,
|
||||||
|
BadSchema,
|
||||||
|
NotWellFormed,
|
||||||
|
NotValid,
|
||||||
|
InternalError,
|
||||||
|
};
|
||||||
|
struct Status {
|
||||||
|
ErrorCode Code;
|
||||||
|
std::string Message;
|
||||||
|
};
|
||||||
|
|
||||||
|
Status validate(const std::string &XML);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace swift
|
||||||
|
|
||||||
|
#endif // SWIFT_IDE_TEST_XML_VALIDATOR_H
|
||||||
|
|
||||||
@@ -492,6 +492,9 @@ struct ExtractBriefTestData ExtractBriefTests[] = {
|
|||||||
{ { "aaa", "bbb" },
|
{ { "aaa", "bbb" },
|
||||||
"aaa bbb",
|
"aaa bbb",
|
||||||
"<paragraph>aaa\nbbb</paragraph>" }, // Correct.
|
"<paragraph>aaa\nbbb</paragraph>" }, // Correct.
|
||||||
|
{ { "& < > \" '" },
|
||||||
|
"& < > \" '",
|
||||||
|
"<paragraph>& < > " '</paragraph>" }, // Correct.
|
||||||
{ { "aaa", " " },
|
{ { "aaa", " " },
|
||||||
"aaa",
|
"aaa",
|
||||||
"<paragraph>aaa</paragraph>" }, // Correct.
|
"<paragraph>aaa</paragraph>" }, // Correct.
|
||||||
@@ -1248,6 +1251,33 @@ struct ExtractBriefTestData ExtractBriefTests[] = {
|
|||||||
"<list_item><paragraph>bbb</paragraph></list_item>"
|
"<list_item><paragraph>bbb</paragraph></list_item>"
|
||||||
"</enumerated_list>"
|
"</enumerated_list>"
|
||||||
}, // Correct.
|
}, // Correct.
|
||||||
|
{ { "* aaa",
|
||||||
|
" :bbb: ccc",
|
||||||
|
" :ddd: eee",
|
||||||
|
" :fff: ggg" }, "",
|
||||||
|
"<bullet_list>"
|
||||||
|
"<list_item>"
|
||||||
|
"<paragraph>aaa\n:bbb: ccc\n:ddd: eee\n:fff: ggg</paragraph>"
|
||||||
|
"</list_item>"
|
||||||
|
"</bullet_list>" }, // Correct.
|
||||||
|
{ { "* aaa",
|
||||||
|
"",
|
||||||
|
" :bbb: ccc",
|
||||||
|
" :ddd: eee",
|
||||||
|
" :fff: ggg" }, "",
|
||||||
|
"<bullet_list>"
|
||||||
|
"<list_item>"
|
||||||
|
"<paragraph>aaa</paragraph>"
|
||||||
|
"<field_list>"
|
||||||
|
"<field>"
|
||||||
|
"<field_name>bbb</field_name>"
|
||||||
|
"<field_body>"
|
||||||
|
"<paragraph>ccc\n:ddd: eee\n:fff: ggg</paragraph>"
|
||||||
|
"</field_body>"
|
||||||
|
"</field>"
|
||||||
|
"</field_list>"
|
||||||
|
"</list_item>"
|
||||||
|
"</bullet_list>" }, // FIXME: WRONG
|
||||||
|
|
||||||
// Definition lists.
|
// Definition lists.
|
||||||
{ { "aaa",
|
{ { "aaa",
|
||||||
@@ -1543,10 +1573,10 @@ struct ExtractBriefTestData ExtractBriefTests[] = {
|
|||||||
{ { "`aaa`__" }, "`aaa`__", "<paragraph>`aaa`__</paragraph>" },
|
{ { "`aaa`__" }, "`aaa`__", "<paragraph>`aaa`__</paragraph>" },
|
||||||
{ { "`aaa <http://example.org/>`_" },
|
{ { "`aaa <http://example.org/>`_" },
|
||||||
"`aaa <http://example.org/>`_",
|
"`aaa <http://example.org/>`_",
|
||||||
"<paragraph>`aaa <http://example.org/>`_</paragraph>"},
|
"<paragraph>`aaa <http://example.org/>`_</paragraph>"},
|
||||||
{ { "`aaa <foo.txt\\_>`__" },
|
{ { "`aaa <foo.txt\\_>`__" },
|
||||||
"`aaa <foo.txt\\_>`__",
|
"`aaa <foo.txt\\_>`__",
|
||||||
"<paragraph>`aaa <foo.txt\\_>`__</paragraph>" },
|
"<paragraph>`aaa <foo.txt\\_>`__</paragraph>" },
|
||||||
};
|
};
|
||||||
INSTANTIATE_TEST_CASE_P(
|
INSTANTIATE_TEST_CASE_P(
|
||||||
ReSTTest, ExtractBriefTest,
|
ReSTTest, ExtractBriefTest,
|
||||||
|
|||||||
Reference in New Issue
Block a user