Skip to content

Add support for Doxygen abstract tag #227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Sources/Markdown/Base/Markup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ func makeMarkup(_ data: _MarkupData) -> Markup {
return DoxygenDiscussion(data)
case .doxygenNote:
return DoxygenNote(data)
case .doxygenAbstract:
return DoxygenAbstract(data)
case .doxygenParam:
return DoxygenParameter(data)
case .doxygenReturns:
Expand Down
5 changes: 5 additions & 0 deletions Sources/Markdown/Base/RawMarkup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ enum RawMarkupData: Equatable {

case doxygenDiscussion
case doxygenNote
case doxygenAbstract
case doxygenParam(name: String)
case doxygenReturns
}
Expand Down Expand Up @@ -352,6 +353,10 @@ final class RawMarkup: ManagedBuffer<RawMarkupHeader, RawMarkup> {
return .create(data: .doxygenNote, parsedRange: parsedRange, children: children)
}

static func doxygenAbstract(parsedRange: SourceRange?, _ children: [RawMarkup]) -> RawMarkup {
return .create(data: .doxygenAbstract, parsedRange: parsedRange, children: children)
}

static func doxygenParam(name: String, parsedRange: SourceRange?, _ children: [RawMarkup]) -> RawMarkup {
return .create(data: .doxygenParam(name: name), parsedRange: parsedRange, children: children)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2025 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

import Foundation

/// A parsed Doxygen `\abstract` command.
///
/// The Doxygen support in Swift-Markdown parses `\abstract` commands of the form
/// `\abstract description`, where `description` continues until the next blank
/// line or parsed command.
///
/// ```markdown
/// \abstract This object can give other objects in your program magical powers.
/// ```
public struct DoxygenAbstract: BlockContainer {
public var _data: _MarkupData

init(_ raw: RawMarkup) throws {
guard case .doxygenAbstract = raw.data else {
throw RawMarkup.Error.concreteConversionError(from: raw, to: DoxygenAbstract.self)
}
let absoluteRaw = AbsoluteRawMarkup(markup: raw, metadata: MarkupMetadata(id: .newRoot(), indexInParent: 0))
self.init(_MarkupData(absoluteRaw))
}

init(_ data: _MarkupData) {
self._data = data
}

public func accept<V: MarkupVisitor>(_ visitor: inout V) -> V.Result {
return visitor.visitDoxygenAbstract(self)
}
}

public extension DoxygenAbstract {
/// Create a new Doxygen abstract definition.
///
/// - Parameter children: Block child elements.
init<Children: Sequence>(children: Children) where Children.Element == BlockMarkup {
try! self.init(.doxygenAbstract(parsedRange: nil, children.map({ $0.raw.markup })))
}

/// Create a new Doxygen abstract definition.
///
/// - Parameter children: Block child elements.
init(children: BlockMarkup...) {
self.init(children: children)
}
}

1 change: 1 addition & 0 deletions Sources/Markdown/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ add_library(Markdown
Base/RawMarkup.swift
"Block Nodes/Block Container Blocks/Doxygen Commands/DoxygenDiscussion.swift"
"Block Nodes/Block Container Blocks/Doxygen Commands/DoxygenNote.swift"
"Block Nodes/Block Container Blocks/Doxygen Commands/DoxygenAbstract.swift"
"Block Nodes/Block Container Blocks/Doxygen Commands/DoxygenParameter.swift"
"Block Nodes/Block Container Blocks/Doxygen Commands/DoxygenReturns.swift"
"Block Nodes/Block Container Blocks/BlockDirective.swift"
Expand Down
1 change: 1 addition & 0 deletions Sources/Markdown/Markdown.docc/Markdown/DoxygenCommands.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Doxygen commands are not parsed within code blocks or block directive content.

### Commands

- ``DoxygenAbstract``
- ``DoxygenDiscussion``
- ``DoxygenNote``
- ``DoxygenParameter``
Expand Down
7 changes: 7 additions & 0 deletions Sources/Markdown/Parser/BlockDirectiveParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ struct PendingDoxygenCommand {
enum CommandKind {
case discussion
case note
case abstract
case param(name: Substring)
case returns

Expand All @@ -235,6 +236,8 @@ struct PendingDoxygenCommand {
return "'discussion'"
case .note:
return "'note'"
case .abstract:
return "'abstract'"
case .param(name: let name):
return "'param' Argument: '\(name)'"
case .returns:
Expand Down Expand Up @@ -755,6 +758,8 @@ private enum ParseContainer: CustomStringConvertible {
return [.doxygenDiscussion(parsedRange: range, children)]
case .note:
return [.doxygenNote(parsedRange: range, children)]
case .abstract:
return [.doxygenAbstract(parsedRange: range, children)]
case .param(let name):
return [.doxygenParam(name: String(name), parsedRange: range, children)]
case .returns:
Expand Down Expand Up @@ -887,6 +892,8 @@ struct ParseContainerStack {
kind = .discussion
case "note":
kind = .note
case "abstract":
kind = .abstract
case "param":
guard let paramName = remainder.lex(until: { ch in
if ch.isWhitespace {
Expand Down
11 changes: 11 additions & 0 deletions Sources/Markdown/Visitor/MarkupVisitor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,14 @@ public protocol MarkupVisitor<Result> {
*/
mutating func visitDoxygenNote(_ doxygenNote: DoxygenNote) -> Result

/**
Visit a `DoxygenAbstract` element and return the result.

- parameter doxygenAbstract: A `DoxygenAbstract` element.
- returns: The result of the visit.
*/
mutating func visitDoxygenAbstract(_ doxygenAbstract: DoxygenAbstract) -> Result

/**
Visit a `DoxygenParam` element and return the result.

Expand Down Expand Up @@ -411,6 +419,9 @@ extension MarkupVisitor {
public mutating func visitDoxygenNote(_ doxygenNote: DoxygenNote) -> Result {
return defaultVisit(doxygenNote)
}
public mutating func visitDoxygenAbstract(_ doxygenAbstract: DoxygenAbstract) -> Result {
return defaultVisit(doxygenAbstract)
}
public mutating func visitDoxygenParameter(_ doxygenParam: DoxygenParameter) -> Result {
return defaultVisit(doxygenParam)
}
Expand Down
8 changes: 7 additions & 1 deletion Sources/Markdown/Walker/Walkers/MarkupFormatter.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2021-2024 Apple Inc. and the Swift project authors
Copyright (c) 2021-2025 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
Expand Down Expand Up @@ -1178,6 +1178,11 @@ public struct MarkupFormatter: MarkupWalker {
descendInto(doxygenDiscussion)
}

public mutating func visitDoxygenAbstract(_ doxygenAbstract: DoxygenAbstract) {
printDoxygenStart("abstract", for: doxygenAbstract)
descendInto(doxygenAbstract)
}

public mutating func visitDoxygenNote(_ doxygenNote: DoxygenNote) {
printDoxygenStart("note", for: doxygenNote)
descendInto(doxygenNote)
Expand All @@ -1194,4 +1199,5 @@ public struct MarkupFormatter: MarkupWalker {
printDoxygenStart("returns", for: doxygenReturns)
descendInto(doxygenReturns)
}

}
22 changes: 21 additions & 1 deletion Tests/MarkdownTests/Parsing/DoxygenCommandParserTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,24 @@ class DoxygenCommandParserTests: XCTestCase {
assertValidParse(source: #"\discussion The thing."#)
}

func testParseAbstract() {
func assertValidParse(source: String) {
let document = Document(parsing: source, options: parseOptions)
XCTAssert(document.child(at: 0) is DoxygenAbstract)

let expectedDump = """
Document
└─ DoxygenAbstract
└─ Paragraph
└─ Text "The thing."
"""
XCTAssertEqual(document.debugDescription(), expectedDump)
}

assertValidParse(source: "@abstract The thing.")
assertValidParse(source: #"\abstract The thing."#)
}

func testParseNote() {
func assertValidParse(source: String) {
let document = Document(parsing: source, options: parseOptions)
Expand Down Expand Up @@ -451,7 +469,9 @@ class DoxygenCommandParserTests: XCTestCase {
let expectedDump = #"""
Document
├─ BlockDirective name: "method"
├─ BlockDirective name: "abstract"
├─ DoxygenAbstract
│ └─ Paragraph
│ └─ Text "Some brief description of this method"
├─ DoxygenParameter parameter: number
│ └─ Paragraph
│ └─ Text "Some description of the “number” parameter"
Expand Down
20 changes: 20 additions & 0 deletions Tests/MarkdownTests/Visitors/MarkupFormatterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,26 @@ class MarkupFormatterSingleElementTests: XCTestCase {
XCTAssertEqual(expectedAt, printedAt)
}

func testPrintDoxygenAbstract() {
let expected = #"\abstract Another thing."#
let printed = DoxygenAbstract(children: Paragraph(Text("Another thing."))).format()
print (printed)
XCTAssertEqual(expected, printed)
}

func testPrintDoxygenAbstractMultiline() {
let expected = #"""
\abstract Another thing.
This is an extended abstract.
"""#
let printed = DoxygenAbstract(children: Paragraph(
Text("Another thing."),
SoftBreak(),
Text("This is an extended abstract.")
)).format()
XCTAssertEqual(expected, printed)
}

func testPrintDoxygenDiscussion() {
let expected = #"\discussion Another thing."#
let printed = DoxygenDiscussion(children: Paragraph(Text("Another thing."))).format()
Expand Down