Skip to content

Commit c7d7a40

Browse files
committed
Control Doxygen commands preceding newline by formatter options
1 parent 52a75b8 commit c7d7a40

File tree

2 files changed

+75
-21
lines changed

2 files changed

+75
-21
lines changed

Sources/Markdown/Walker/Walkers/MarkupFormatter.swift

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,21 @@ fileprivate extension Markup {
3333
}
3434
return nil
3535
}
36+
37+
/// Previous sibling of this element in its parent, or `nil` if it's the first child.
38+
var previousSibling: Markup? {
39+
guard let parent, indexInParent > 0 else {
40+
return nil
41+
}
42+
43+
return parent.child(at: indexInParent - 1)
44+
}
45+
46+
/// Whether this element is a Doxygen command.
47+
var isDoxygenCommand: Bool {
48+
return self is DoxygenDiscussion || self is DoxygenNote || self is DoxygenAbstract
49+
|| self is DoxygenParameter || self is DoxygenReturns
50+
}
3651
}
3752

3853
fileprivate extension String {
@@ -239,6 +254,15 @@ public struct MarkupFormatter: MarkupWalker {
239254
case at = "@"
240255
}
241256

257+
/// The spacing to use when formatting adjacent Doxygen commands.
258+
public enum AdjacentDoxygenCommandsSpacing: String, CaseIterable {
259+
/// Separate adjacent Doxygen commands with a single newline.
260+
case singleNewline = "single-newline"
261+
262+
/// Keep a blank line between adjacent Doxygen commands creating separate paragraphs.
263+
case separateParagraphs = "separate-paragraphs"
264+
}
265+
242266
// MARK: Option Properties
243267

244268
var orderedListNumerals: OrderedListNumerals
@@ -253,6 +277,7 @@ public struct MarkupFormatter: MarkupWalker {
253277
var preferredLineLimit: PreferredLineLimit?
254278
var customLinePrefix: String
255279
var doxygenCommandPrefix: DoxygenCommandPrefix
280+
var adjacentDoxygenCommandsSpacing: AdjacentDoxygenCommandsSpacing
256281

257282
/**
258283
Create a set of formatting options to use when printing an element.
@@ -270,6 +295,7 @@ public struct MarkupFormatter: MarkupWalker {
270295
- preferredLineLimit: The preferred maximum line length and method for splitting ``Text`` elements in an attempt to maintain that line length.
271296
- customLinePrefix: An addition prefix to print at the start of each line, useful for adding documentation comment markers.
272297
- doxygenCommandPrefix: The command command prefix, which defaults to ``DoxygenCommandPrefix/backslash``.
298+
- adjacentDoxygenCommandsSpacing: The spacing to use when formatting adjacent Doxygen commands.
273299
*/
274300
public init(unorderedListMarker: UnorderedListMarker = .dash,
275301
orderedListNumerals: OrderedListNumerals = .allSame(1),
@@ -282,7 +308,8 @@ public struct MarkupFormatter: MarkupWalker {
282308
preferredHeadingStyle: PreferredHeadingStyle = .atx,
283309
preferredLineLimit: PreferredLineLimit? = nil,
284310
customLinePrefix: String = "",
285-
doxygenCommandPrefix: DoxygenCommandPrefix = .backslash) {
311+
doxygenCommandPrefix: DoxygenCommandPrefix = .backslash,
312+
adjacentDoxygenCommandsSpacing: AdjacentDoxygenCommandsSpacing = .singleNewline) {
286313
self.unorderedListMarker = unorderedListMarker
287314
self.orderedListNumerals = orderedListNumerals
288315
self.useCodeFence = useCodeFence
@@ -297,6 +324,7 @@ public struct MarkupFormatter: MarkupWalker {
297324
self.thematicBreakLength = max(3, thematicBreakLength)
298325
self.customLinePrefix = customLinePrefix
299326
self.doxygenCommandPrefix = doxygenCommandPrefix
327+
self.adjacentDoxygenCommandsSpacing = adjacentDoxygenCommandsSpacing
300328
}
301329

302330
/// The default set of formatting options.
@@ -1173,48 +1201,47 @@ public struct MarkupFormatter: MarkupWalker {
11731201
print(formattingOptions.doxygenCommandPrefix.rawValue + name + " ", for: element)
11741202
}
11751203

1176-
public mutating func visitDoxygenDiscussion(_ doxygenDiscussion: DoxygenDiscussion) {
1177-
if doxygenDiscussion.indexInParent > 0 {
1204+
private mutating func ensureDoxygenCommandPrecedingNewline(for element: Markup) {
1205+
guard let previousSibling = element.previousSibling else {
1206+
return
1207+
}
1208+
1209+
guard formattingOptions.adjacentDoxygenCommandsSpacing == .singleNewline else {
11781210
ensurePrecedingNewlineCount(atLeast: 2)
1211+
return
11791212
}
11801213

1214+
let newlineCount = previousSibling.isDoxygenCommand ? 1 : 2
1215+
ensurePrecedingNewlineCount(atLeast: newlineCount)
1216+
}
1217+
1218+
public mutating func visitDoxygenDiscussion(_ doxygenDiscussion: DoxygenDiscussion) {
1219+
ensureDoxygenCommandPrecedingNewline(for: doxygenDiscussion)
11811220
printDoxygenStart("discussion", for: doxygenDiscussion)
11821221
descendInto(doxygenDiscussion)
11831222
}
11841223

11851224
public mutating func visitDoxygenAbstract(_ doxygenAbstract: DoxygenAbstract) {
1186-
if doxygenAbstract.indexInParent > 0 {
1187-
ensurePrecedingNewlineCount(atLeast: 2)
1188-
}
1189-
1225+
ensureDoxygenCommandPrecedingNewline(for: doxygenAbstract)
11901226
printDoxygenStart("abstract", for: doxygenAbstract)
11911227
descendInto(doxygenAbstract)
11921228
}
11931229

11941230
public mutating func visitDoxygenNote(_ doxygenNote: DoxygenNote) {
1195-
if doxygenNote.indexInParent > 0 {
1196-
ensurePrecedingNewlineCount(atLeast: 2)
1197-
}
1198-
1231+
ensureDoxygenCommandPrecedingNewline(for: doxygenNote)
11991232
printDoxygenStart("note", for: doxygenNote)
12001233
descendInto(doxygenNote)
12011234
}
12021235

12031236
public mutating func visitDoxygenParameter(_ doxygenParam: DoxygenParameter) {
1204-
if doxygenParam.indexInParent > 0 {
1205-
ensurePrecedingNewlineCount(atLeast: 2)
1206-
}
1207-
1237+
ensureDoxygenCommandPrecedingNewline(for: doxygenParam)
12081238
printDoxygenStart("param", for: doxygenParam)
12091239
print("\(doxygenParam.name) ", for: doxygenParam)
12101240
descendInto(doxygenParam)
12111241
}
12121242

12131243
public mutating func visitDoxygenReturns(_ doxygenReturns: DoxygenReturns) {
1214-
if doxygenReturns.indexInParent > 0 {
1215-
ensurePrecedingNewlineCount(atLeast: 2)
1216-
}
1217-
1244+
ensureDoxygenCommandPrecedingNewline(for: doxygenReturns)
12181245
// FIXME: store the actual command name used in the original markup
12191246
printDoxygenStart("returns", for: doxygenReturns)
12201247
descendInto(doxygenReturns)

Tests/MarkdownTests/Visitors/MarkupFormatterTests.swift

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,7 +1627,32 @@ class MarkupFormatterMixedContentTests: XCTestCase {
16271627
zip(expected, printed).forEach { XCTAssertEqual($0, $1) }
16281628
}
16291629

1630-
func testDoxygenCommandsWithPrecedingNewlines() {
1630+
func testDoxygenCommandsPrecedingNewlinesWithSingleNewline() {
1631+
let expected = #"""
1632+
Does something.
1633+
1634+
\abstract abstract
1635+
\param x first param
1636+
\returns result
1637+
\note note
1638+
\discussion discussion
1639+
"""#
1640+
1641+
let formattingOptions = MarkupFormatter.Options(
1642+
adjacentDoxygenCommandsSpacing: .singleNewline)
1643+
let printed = Document(
1644+
Paragraph(Text("Does something.")),
1645+
DoxygenAbstract(children: Paragraph(Text("abstract"))),
1646+
DoxygenParameter(name: "x", children: Paragraph(Text("first param"))),
1647+
DoxygenReturns(children: Paragraph(Text("result"))),
1648+
DoxygenNote(children: Paragraph(Text("note"))),
1649+
DoxygenDiscussion(children: Paragraph(Text("discussion")))
1650+
).format(options: formattingOptions)
1651+
1652+
XCTAssertEqual(expected, printed)
1653+
}
1654+
1655+
func testDoxygenCommandsPrecedingNewlinesAsSeparateParagraphs() {
16311656
let expected = #"""
16321657
Does something.
16331658
@@ -1642,14 +1667,16 @@ class MarkupFormatterMixedContentTests: XCTestCase {
16421667
\discussion discussion
16431668
"""#
16441669

1670+
let formattingOptions = MarkupFormatter.Options(
1671+
adjacentDoxygenCommandsSpacing: .separateParagraphs)
16451672
let printed = Document(
16461673
Paragraph(Text("Does something.")),
16471674
DoxygenAbstract(children: Paragraph(Text("abstract"))),
16481675
DoxygenParameter(name: "x", children: Paragraph(Text("first param"))),
16491676
DoxygenReturns(children: Paragraph(Text("result"))),
16501677
DoxygenNote(children: Paragraph(Text("note"))),
16511678
DoxygenDiscussion(children: Paragraph(Text("discussion")))
1652-
).format()
1679+
).format(options: formattingOptions)
16531680

16541681
XCTAssertEqual(expected, printed)
16551682
}

0 commit comments

Comments
 (0)