Skip to content

Commit 5ad49ed

Browse files
authored
Add support for Doxygen abstract tag (#227)
* Adding support for abstract headerdoc tag so the methogs or properties with only an abstract retains its documentation * Adding support for abstract headerdoc tag so the methods or properties with abstract headerdoc tag retains documentation * adding brief to map to abstract tag
1 parent 5d4f6b8 commit 5ad49ed

File tree

10 files changed

+134
-2
lines changed

10 files changed

+134
-2
lines changed

Sources/Markdown/Base/Markup.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ func makeMarkup(_ data: _MarkupData) -> Markup {
7575
return DoxygenDiscussion(data)
7676
case .doxygenNote:
7777
return DoxygenNote(data)
78+
case .doxygenAbstract:
79+
return DoxygenAbstract(data)
7880
case .doxygenParam:
7981
return DoxygenParameter(data)
8082
case .doxygenReturns:

Sources/Markdown/Base/RawMarkup.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ enum RawMarkupData: Equatable {
5454

5555
case doxygenDiscussion
5656
case doxygenNote
57+
case doxygenAbstract
5758
case doxygenParam(name: String)
5859
case doxygenReturns
5960
}
@@ -352,6 +353,10 @@ final class RawMarkup: ManagedBuffer<RawMarkupHeader, RawMarkup> {
352353
return .create(data: .doxygenNote, parsedRange: parsedRange, children: children)
353354
}
354355

356+
static func doxygenAbstract(parsedRange: SourceRange?, _ children: [RawMarkup]) -> RawMarkup {
357+
return .create(data: .doxygenAbstract, parsedRange: parsedRange, children: children)
358+
}
359+
355360
static func doxygenParam(name: String, parsedRange: SourceRange?, _ children: [RawMarkup]) -> RawMarkup {
356361
return .create(data: .doxygenParam(name: name), parsedRange: parsedRange, children: children)
357362
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2025 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See https://swift.org/LICENSE.txt for license information
8+
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
import Foundation
12+
13+
/// A parsed Doxygen `\abstract` command.
14+
///
15+
/// The Doxygen support in Swift-Markdown parses `\abstract` commands of the form
16+
/// `\abstract description`, where `description` continues until the next blank
17+
/// line or parsed command.
18+
///
19+
/// ```markdown
20+
/// \abstract This object can give other objects in your program magical powers.
21+
/// ```
22+
public struct DoxygenAbstract: BlockContainer {
23+
public var _data: _MarkupData
24+
25+
init(_ raw: RawMarkup) throws {
26+
guard case .doxygenAbstract = raw.data else {
27+
throw RawMarkup.Error.concreteConversionError(from: raw, to: DoxygenAbstract.self)
28+
}
29+
let absoluteRaw = AbsoluteRawMarkup(markup: raw, metadata: MarkupMetadata(id: .newRoot(), indexInParent: 0))
30+
self.init(_MarkupData(absoluteRaw))
31+
}
32+
33+
init(_ data: _MarkupData) {
34+
self._data = data
35+
}
36+
37+
public func accept<V: MarkupVisitor>(_ visitor: inout V) -> V.Result {
38+
return visitor.visitDoxygenAbstract(self)
39+
}
40+
}
41+
42+
public extension DoxygenAbstract {
43+
/// Create a new Doxygen abstract definition.
44+
///
45+
/// - Parameter children: Block child elements.
46+
init<Children: Sequence>(children: Children) where Children.Element == BlockMarkup {
47+
try! self.init(.doxygenAbstract(parsedRange: nil, children.map({ $0.raw.markup })))
48+
}
49+
50+
/// Create a new Doxygen abstract definition.
51+
///
52+
/// - Parameter children: Block child elements.
53+
init(children: BlockMarkup...) {
54+
self.init(children: children)
55+
}
56+
}
57+

Sources/Markdown/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ add_library(Markdown
1919
Base/RawMarkup.swift
2020
"Block Nodes/Block Container Blocks/Doxygen Commands/DoxygenDiscussion.swift"
2121
"Block Nodes/Block Container Blocks/Doxygen Commands/DoxygenNote.swift"
22+
"Block Nodes/Block Container Blocks/Doxygen Commands/DoxygenAbstract.swift"
2223
"Block Nodes/Block Container Blocks/Doxygen Commands/DoxygenParameter.swift"
2324
"Block Nodes/Block Container Blocks/Doxygen Commands/DoxygenReturns.swift"
2425
"Block Nodes/Block Container Blocks/BlockDirective.swift"

Sources/Markdown/Markdown.docc/Markdown/DoxygenCommands.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Doxygen commands are not parsed within code blocks or block directive content.
4444

4545
### Commands
4646

47+
- ``DoxygenAbstract``
4748
- ``DoxygenDiscussion``
4849
- ``DoxygenNote``
4950
- ``DoxygenParameter``

Sources/Markdown/Parser/BlockDirectiveParser.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ struct PendingDoxygenCommand {
226226
enum CommandKind {
227227
case discussion
228228
case note
229+
case abstract
229230
case param(name: Substring)
230231
case returns
231232

@@ -235,6 +236,8 @@ struct PendingDoxygenCommand {
235236
return "'discussion'"
236237
case .note:
237238
return "'note'"
239+
case .abstract:
240+
return "'abstract'"
238241
case .param(name: let name):
239242
return "'param' Argument: '\(name)'"
240243
case .returns:
@@ -755,6 +758,8 @@ private enum ParseContainer: CustomStringConvertible {
755758
return [.doxygenDiscussion(parsedRange: range, children)]
756759
case .note:
757760
return [.doxygenNote(parsedRange: range, children)]
761+
case .abstract:
762+
return [.doxygenAbstract(parsedRange: range, children)]
758763
case .param(let name):
759764
return [.doxygenParam(name: String(name), parsedRange: range, children)]
760765
case .returns:
@@ -887,6 +892,8 @@ struct ParseContainerStack {
887892
kind = .discussion
888893
case "note":
889894
kind = .note
895+
case "brief", "abstract":
896+
kind = .abstract
890897
case "param":
891898
guard let paramName = remainder.lex(until: { ch in
892899
if ch.isWhitespace {

Sources/Markdown/Visitor/MarkupVisitor.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,14 @@ public protocol MarkupVisitor<Result> {
291291
*/
292292
mutating func visitDoxygenNote(_ doxygenNote: DoxygenNote) -> Result
293293

294+
/**
295+
Visit a `DoxygenAbstract` element and return the result.
296+
297+
- parameter doxygenAbstract: A `DoxygenAbstract` element.
298+
- returns: The result of the visit.
299+
*/
300+
mutating func visitDoxygenAbstract(_ doxygenAbstract: DoxygenAbstract) -> Result
301+
294302
/**
295303
Visit a `DoxygenParam` element and return the result.
296304

@@ -411,6 +419,9 @@ extension MarkupVisitor {
411419
public mutating func visitDoxygenNote(_ doxygenNote: DoxygenNote) -> Result {
412420
return defaultVisit(doxygenNote)
413421
}
422+
public mutating func visitDoxygenAbstract(_ doxygenAbstract: DoxygenAbstract) -> Result {
423+
return defaultVisit(doxygenAbstract)
424+
}
414425
public mutating func visitDoxygenParameter(_ doxygenParam: DoxygenParameter) -> Result {
415426
return defaultVisit(doxygenParam)
416427
}

Sources/Markdown/Walker/Walkers/MarkupFormatter.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This source file is part of the Swift.org open source project
33

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

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

1181+
public mutating func visitDoxygenAbstract(_ doxygenAbstract: DoxygenAbstract) {
1182+
printDoxygenStart("abstract", for: doxygenAbstract)
1183+
descendInto(doxygenAbstract)
1184+
}
1185+
11811186
public mutating func visitDoxygenNote(_ doxygenNote: DoxygenNote) {
11821187
printDoxygenStart("note", for: doxygenNote)
11831188
descendInto(doxygenNote)
@@ -1194,4 +1199,5 @@ public struct MarkupFormatter: MarkupWalker {
11941199
printDoxygenStart("returns", for: doxygenReturns)
11951200
descendInto(doxygenReturns)
11961201
}
1202+
11971203
}

Tests/MarkdownTests/Parsing/DoxygenCommandParserTests.swift

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,26 @@ class DoxygenCommandParserTests: XCTestCase {
3232
assertValidParse(source: #"\discussion The thing."#)
3333
}
3434

35+
func testParseAbstract() {
36+
func assertValidParse(source: String) {
37+
let document = Document(parsing: source, options: parseOptions)
38+
XCTAssert(document.child(at: 0) is DoxygenAbstract)
39+
40+
let expectedDump = """
41+
Document
42+
└─ DoxygenAbstract
43+
└─ Paragraph
44+
└─ Text "The thing."
45+
"""
46+
XCTAssertEqual(document.debugDescription(), expectedDump)
47+
}
48+
49+
assertValidParse(source: "@abstract The thing.")
50+
assertValidParse(source: #"\abstract The thing."#)
51+
assertValidParse(source: "@brief The thing.")
52+
assertValidParse(source: #"\brief The thing."#)
53+
}
54+
3555
func testParseNote() {
3656
func assertValidParse(source: String) {
3757
let document = Document(parsing: source, options: parseOptions)
@@ -451,7 +471,9 @@ class DoxygenCommandParserTests: XCTestCase {
451471
let expectedDump = #"""
452472
Document
453473
├─ BlockDirective name: "method"
454-
├─ BlockDirective name: "abstract"
474+
├─ DoxygenAbstract
475+
│ └─ Paragraph
476+
│ └─ Text "Some brief description of this method"
455477
├─ DoxygenParameter parameter: number
456478
│ └─ Paragraph
457479
│ └─ Text "Some description of the “number” parameter"

Tests/MarkdownTests/Visitors/MarkupFormatterTests.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,26 @@ class MarkupFormatterSingleElementTests: XCTestCase {
301301
XCTAssertEqual(expectedAt, printedAt)
302302
}
303303

304+
func testPrintDoxygenAbstract() {
305+
let expected = #"\abstract Another thing."#
306+
let printed = DoxygenAbstract(children: Paragraph(Text("Another thing."))).format()
307+
print (printed)
308+
XCTAssertEqual(expected, printed)
309+
}
310+
311+
func testPrintDoxygenAbstractMultiline() {
312+
let expected = #"""
313+
\abstract Another thing.
314+
This is an extended abstract.
315+
"""#
316+
let printed = DoxygenAbstract(children: Paragraph(
317+
Text("Another thing."),
318+
SoftBreak(),
319+
Text("This is an extended abstract.")
320+
)).format()
321+
XCTAssertEqual(expected, printed)
322+
}
323+
304324
func testPrintDoxygenDiscussion() {
305325
let expected = #"\discussion Another thing."#
306326
let printed = DoxygenDiscussion(children: Paragraph(Text("Another thing."))).format()

0 commit comments

Comments
 (0)