diff --git a/bindings/xml/comment-xml-schema.rng b/bindings/xml/comment-xml-schema.rng index 468efa04253..43300c7c3c3 100644 --- a/bindings/xml/comment-xml-schema.rng +++ b/bindings/xml/comment-xml-schema.rng @@ -650,9 +650,28 @@ - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/include/swift/AST/Comment.h b/include/swift/AST/Comment.h index 6317ddea361..35c42e6aa02 100644 --- a/include/swift/AST/Comment.h +++ b/include/swift/AST/Comment.h @@ -22,34 +22,20 @@ class DocComment; struct RawComment; class DocComment { -public: - struct CommentParts { - OptionalBrief; - ArrayRef BodyNodes; - ArrayRef ParamFields; - Optional ReturnsField; - Optional ThrowsField; - - bool isEmpty() const { - return !Brief.hasValue() && !ReturnsField.hasValue() && !ThrowsField.hasValue() && BodyNodes.empty() && ParamFields.empty(); - } - }; - -private: const Decl *D; const swift::markup::Document *Doc = nullptr; - const CommentParts Parts; + const swift::markup::CommentParts Parts; public: DocComment(const Decl *D, swift::markup::Document *Doc, - CommentParts Parts) + swift::markup::CommentParts Parts) : D(D), Doc(Doc), Parts(Parts) {} const Decl *getDecl() const { return D; } const swift::markup::Document *getDocument() const { return Doc; } - CommentParts getParts() const { + swift::markup::CommentParts getParts() const { return Parts; } diff --git a/include/swift/Markup/AST.h b/include/swift/Markup/AST.h index fe60ddc2b4e..e8d0ae75640 100644 --- a/include/swift/Markup/AST.h +++ b/include/swift/Markup/AST.h @@ -22,6 +22,35 @@ namespace swift { namespace markup { class MarkupContext; +class MarkupASTNode; +class Paragraph; +class ParamField; +class ReturnsField; +class ThrowsField; + +/// The basic structure of a doc comment attached to a Swift +/// declaration. +struct CommentParts { + Optional Brief; + ArrayRef BodyNodes; + ArrayRef ParamFields; + Optional ReturnsField; + Optional ThrowsField; + + bool isEmpty() const { + return !Brief.hasValue() && + !ReturnsField.hasValue() && + !ThrowsField.hasValue() && + BodyNodes.empty() && + ParamFields.empty(); + } + + bool hasFunctionDocumentation() const { + return !ParamFields.empty() || + ReturnsField.hasValue() || + ThrowsField.hasValue(); + } +}; #define MARKUP_AST_NODE(Id, Parent) class Id; #define ABSTRACT_MARKUP_AST_NODE(Id, Parent) class Id; @@ -585,6 +614,10 @@ class ParamField final : public PrivateExtension, StringRef Name; + // Parameter fields can contain a substructure describing a + // function or closure parameter. + llvm::Optional Parts; + ParamField(StringRef Name, ArrayRef Children); public: @@ -596,6 +629,21 @@ public: return Name; } + llvm::Optional getParts() const { + return Parts; + } + + void setParts(CommentParts P) { + Parts = P; + } + + bool isClosureParameter() const { + if (!Parts.hasValue()) + return false; + + return Parts.getValue().hasFunctionDocumentation(); + } + ArrayRef getChildren() { return {getTrailingObjects(), NumChildren}; } diff --git a/lib/AST/DocComment.cpp b/lib/AST/DocComment.cpp index d79c3c740a7..f3dc97f048a 100644 --- a/lib/AST/DocComment.cpp +++ b/lib/AST/DocComment.cpp @@ -70,7 +70,7 @@ Optional extractParamOutlineItem( bool extractParameterOutline( swift::markup::MarkupContext &MC, swift::markup::List *L, - SmallVectorImpl &ParamFields) { + SmallVectorImpl &ParamFields) { SmallVector NormalItems; auto Children = L->getChildren(); if (Children.empty()) @@ -145,7 +145,7 @@ bool extractParameterOutline( bool extractSeparatedParams( swift::markup::MarkupContext &MC, swift::markup::List *L, - SmallVectorImpl &ParamFields) { + SmallVectorImpl &ParamFields) { SmallVector NormalItems; auto Children = L->getChildren(); @@ -209,7 +209,7 @@ bool extractSeparatedParams( bool extractSimpleField( swift::markup::MarkupContext &MC, swift::markup::List *L, - DocComment::CommentParts &Parts, + swift::markup::CommentParts &Parts, SmallVectorImpl &BodyNodes) { auto Children = L->getChildren(); SmallVector NormalItems; @@ -274,11 +274,11 @@ bool extractSimpleField( return NormalItems.size() == 0; } -static DocComment::CommentParts +static swift::markup::CommentParts extractCommentParts(swift::markup::MarkupContext &MC, swift::markup::MarkupASTNode *Node) { - DocComment::CommentParts Parts; + swift::markup::CommentParts Parts; auto Children = Node->getChildren(); if (Children.empty()) return Parts; @@ -289,7 +289,7 @@ extractCommentParts(swift::markup::MarkupContext &MC, Parts.Brief = FirstParagraph; SmallVector BodyNodes; - SmallVector ParamFields; + SmallVector ParamFields; // Look for special top-level lists size_t StartOffset = FirstParagraph == nullptr ? 0 : 1; @@ -317,6 +317,11 @@ extractCommentParts(swift::markup::MarkupContext &MC, Parts.BodyNodes = MC.allocateCopy(llvm::makeArrayRef(BodyNodes)); Parts.ParamFields = MC.allocateCopy(llvm::makeArrayRef(ParamFields)); + for (auto Param : Parts.ParamFields) { + auto ParamParts = extractCommentParts(MC, Param); + Param->setParts(ParamParts); + } + return Parts; } diff --git a/lib/IDE/CommentConversion.cpp b/lib/IDE/CommentConversion.cpp index 6ff845f6425..36135666e20 100644 --- a/lib/IDE/CommentConversion.cpp +++ b/lib/IDE/CommentConversion.cpp @@ -211,13 +211,24 @@ struct CommentToXMLConverter { } void printParamField(const ParamField *PF) { - OS << ""; + OS << ""; + OS << ""; OS << PF->getName(); - OS << "in"; - for (auto Child : PF->getChildren()) - printASTNode(Child); + OS << ""; + OS << "in"; - OS << ""; + if (PF->isClosureParameter()) { + OS << ""; + visitCommentParts(PF->getParts().getValue()); + OS << ""; + } else { + OS << ""; + for (auto Child : PF->getChildren()) { + printASTNode(Child); + } + OS << ""; + } + OS << ""; } void printResultDiscussion(const ReturnsField *RF) { @@ -235,9 +246,40 @@ struct CommentToXMLConverter { } void visitDocComment(const DocComment *DC); + void visitCommentParts(const swift::markup::CommentParts &Parts); }; } // unnamed namespace +void CommentToXMLConverter::visitCommentParts(const swift::markup::CommentParts &Parts) { + if (Parts.Brief.hasValue()) { + OS << ""; + printASTNode(Parts.Brief.getValue()); + OS << ""; + } + + if (!Parts.ParamFields.empty()) { + OS << ""; + for (const auto *PF : Parts.ParamFields) + printParamField(PF); + + OS << ""; + } + + if (Parts.ReturnsField.hasValue()) + printResultDiscussion(Parts.ReturnsField.getValue()); + + if (Parts.ThrowsField.hasValue()) + printThrowsDiscussion(Parts.ThrowsField.getValue()); + + if (!Parts.BodyNodes.empty()) { + OS << ""; + for (const auto *N : Parts.BodyNodes) + printASTNode(N); + + OS << ""; + } +} + void CommentToXMLConverter::visitDocComment(const DocComment *DC) { const Decl *D = DC->getDecl(); @@ -313,36 +355,7 @@ void CommentToXMLConverter::visitDocComment(const DocComment *DC) { OS << ""; } - auto Brief = DC->getBrief(); - if (Brief.hasValue()) { - OS << ""; - printASTNode(Brief.getValue()); - OS << ""; - } - - if (!DC->getParamFields().empty()) { - OS << ""; - for (const auto *PF : DC->getParamFields()) - printParamField(PF); - - OS << ""; - } - - auto RF = DC->getReturnsField(); - if (RF.hasValue()) - printResultDiscussion(RF.getValue()); - - auto TF = DC->getThrowsField(); - if (TF.hasValue()) - printThrowsDiscussion(TF.getValue()); - - if (!DC->getBodyNodes().empty()) { - OS << ""; - for (const auto *N : DC->getBodyNodes()) - printASTNode(N); - - OS << ""; - } + visitCommentParts(DC->getParts()); OS << RootEndTag; } diff --git a/lib/Markup/AST.cpp b/lib/Markup/AST.cpp index 406fa36bd00..72b78271b0b 100644 --- a/lib/Markup/AST.cpp +++ b/lib/Markup/AST.cpp @@ -205,7 +205,8 @@ Strong *Strong::create(MarkupContext &MC, ParamField::ParamField(StringRef Name, ArrayRef Children) : PrivateExtension(ASTNodeKind::ParamField), NumChildren(Children.size()), - Name(Name) { + Name(Name), + Parts(None) { std::uninitialized_copy(Children.begin(), Children.end(), getTrailingObjects()); } diff --git a/test/Inputs/comment_to_something_conversion.swift b/test/Inputs/comment_to_something_conversion.swift index c93b3a03541..e5663b6da15 100644 --- a/test/Inputs/comment_to_something_conversion.swift +++ b/test/Inputs/comment_to_something_conversion.swift @@ -422,3 +422,39 @@ public func codeListingWithDefaultLanguage() {} /// ``` public func codeListingWithOtherLanguage() {} // CHECK: DocCommentAsXML=[codeListingWithOtherLanguage()s:F14swift_ide_test28codeListingWithOtherLanguageFT_T_public func codeListingWithOtherLanguage()Brief.] + +/// Partially applies a binary operator. +/// +/// - Parameter a: The left-hand side to partially apply. +/// - Parameter combine: A binary operator. +/// - Parameter lhs: The left-hand side of the operator +/// - Parameter rhs: The right-hand side of the operator +/// - Returns: A result. +/// - Throws: Nothing. +public func closureParameterExplodedExploded(a: T, combine: (lhs: T, rhs: T) -> T) {} +// CHECK: DocCommentAsXML=[closureParameterExplodedExploded(a:combine:)s:F14swift_ide_test32closureParameterExplodedExplodedurFT1ax7combineFT3lhsx3rhsx_x_T_public func closureParameterExplodedExploded<T>(a: T, combine: (lhs: T, rhs: T) -> T)Partially applies a binary operator.ainThe left-hand side to partially apply.combineinA binary operator.lhsinThe left-hand side of the operatorrhsinThe right-hand side of the operatorA result.Nothing.] CommentXMLValid + +/// Partially applies a binary operator. +/// +/// - Parameters: +/// - a: The left-hand side to partially apply. +/// - combine: A binary operator. +/// - Parameter lhs: The left-hand side of the operator +/// - Parameter rhs: The right-hand side of the operator +/// - Returns: A result. +/// - Throws: Nothing. +public func closureParameterOutlineExploded(a: T, combine: (lhs: T, rhs: T) -> T) {} +// CHECK: DocCommentAsXML=[closureParameterOutlineExploded(a:combine:)s:F14swift_ide_test31closureParameterOutlineExplodedurFT1ax7combineFT3lhsx3rhsx_x_T_public func closureParameterOutlineExploded<T>(a: T, combine: (lhs: T, rhs: T) -> T)Partially applies a binary operator.ainThe left-hand side to partially apply.combineinA binary operator.lhsinThe left-hand side of the operatorrhsinThe right-hand side of the operatorA result.Nothing.] CommentXMLValid + +/// Partially applies a binary operator. +/// +/// - Parameters: +/// - a: The left-hand side to partially apply. +/// - combine: A binary operator. +/// - Parameters: +/// - lhs: The left-hand side of the operator +/// - rhs: The right-hand side of the operator +/// - Returns: A result. +/// - Throws: Nothing. +public func closureParameterOutlineOutline(a: T, combine: (lhs: T, rhs: T) -> T) {} +// CHECK: {{.*}}DocCommentAsXML=[closureParameterOutlineOutline(a:combine:)s:F14swift_ide_test30closureParameterOutlineOutlineurFT1ax7combineFT3lhsx3rhsx_x_T_public func closureParameterOutlineOutline<T>(a: T, combine: (lhs: T, rhs: T) -> T)Partially applies a binary operator.ainThe left-hand side to partially apply.combineinA binary operator.lhsinThe left-hand side of the operatorrhsinThe right-hand side of the operatorA result.Nothing.]