Skip to content

track inner indentation for doxygen commands #118

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

Merged
merged 3 commits into from
Apr 6, 2023
Merged
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
13 changes: 10 additions & 3 deletions Sources/Markdown/Markdown.docc/Markdown/DoxygenCommands.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,16 @@ This is the thing that is modified.
}
```

Doxygen commands are not parsed within code blocks or block directive content. No indentation
adjustment is performed on paragraph arguments that span multiple lines, unlike with block directive
content.
Trailing lines in a command's description are allowed to be indented relative to the command. For
example, the description below is parsed as a paragraph, not a code block:

```markdown
\param thing
The thing.
This is the thing that is modified.
```

Doxygen commands are not parsed within code blocks or block directive content.

## Topics

Expand Down
19 changes: 17 additions & 2 deletions Sources/Markdown/Parser/BlockDirectiveParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -241,14 +241,26 @@ struct PendingDoxygenCommand {

var atLocation: SourceLocation

var atSignIndentation: Int

var nameLocation: SourceLocation

var innerIndentation: Int? = nil

var kind: CommandKind

var endLocation: SourceLocation

var indentationAdjustment: Int {
innerIndentation ?? atSignIndentation
}

mutating func addLine(_ line: TrimmedLine) {
endLocation = SourceLocation(line: line.lineNumber ?? 0, column: line.untrimmedText.count + 1, source: line.source)

if innerIndentation == nil, line.location?.line != atLocation.line, !line.isEmptyOrAllWhitespace {
innerIndentation = line.indentationColumnCount
}
}
}

Expand Down Expand Up @@ -655,8 +667,8 @@ private enum ParseContainer: CustomStringConvertible {
return parent?.indentationAdjustment(under: nil) ?? 0
case .blockDirective(let pendingBlockDirective, _):
return pendingBlockDirective.indentationColumnCount
case .doxygenCommand:
return parent?.indentationAdjustment(under: nil) ?? 0
case .doxygenCommand(let pendingCommand, _):
return pendingCommand.indentationAdjustment
}
}

Expand Down Expand Up @@ -842,6 +854,7 @@ struct ParseContainerStack {
guard !isCodeFenceOrIndentedCodeBlock(on: line) else { return nil }

var remainder = line
let indent = remainder.lexWhitespace()
guard let at = remainder.lex(until: { ch in
switch ch {
case "@", "\\":
Expand Down Expand Up @@ -871,6 +884,7 @@ struct ParseContainerStack {
remainder.lexWhitespace()
var pendingCommand = PendingDoxygenCommand(
atLocation: at.range!.lowerBound,
atSignIndentation: indent?.text.count ?? 0,
nameLocation: name.range!.lowerBound,
kind: .param(name: paramName.text),
endLocation: name.range!.upperBound)
Expand All @@ -879,6 +893,7 @@ struct ParseContainerStack {
case "return", "returns", "result":
var pendingCommand = PendingDoxygenCommand(
atLocation: at.range!.lowerBound,
atSignIndentation: indent?.text.count ?? 0,
nameLocation: name.range!.lowerBound,
kind: .returns,
endLocation: name.range!.upperBound)
Expand Down
102 changes: 101 additions & 1 deletion Tests/MarkdownTests/Parsing/DoxygenCommandParserTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,65 @@ class DoxygenCommandParserTests: XCTestCase {
XCTAssertEqual(document.debugDescription(), expectedDump)
}

func testParseIndentedDescription() {
let source = """
@param thing
The thing.
"""

let document = Document(parsing: source, options: parseOptions)

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

func testParseMultilineIndentedDescription() {
let source = """
@param thing The thing.
This is the thing that is messed with.
"""

let document = Document(parsing: source, options: parseOptions)

let expectedDump = """
Document
└─ DoxygenParameter parameter: thing
└─ Paragraph
├─ Text "The thing."
├─ SoftBreak
└─ Text "This is the thing that is messed with."
"""
XCTAssertEqual(document.debugDescription(), expectedDump)
}

func testParseWithIndentedAtSign() {
let source = """
Method description.

@param thing The thing.
This is the thing that is messed with.
"""

let document = Document(parsing: source, options: parseOptions)

let expectedDump = """
Document
├─ Paragraph
│ └─ Text "Method description."
└─ DoxygenParameter parameter: thing
└─ Paragraph
├─ Text "The thing."
├─ SoftBreak
└─ Text "This is the thing that is messed with."
"""
XCTAssertEqual(document.debugDescription(), expectedDump)
}

func testBreakDescriptionWithBlankLine() {
let source = """
@param thing The thing.
Expand Down Expand Up @@ -188,7 +247,6 @@ class DoxygenCommandParserTests: XCTestCase {

let document = Document(parsing: source, options: parseOptions)

// FIXME: The source location for the first description line is wrong
let expectedDump = """
Document @1:1-2:39
└─ DoxygenParameter @1:1-2:39 parameter: thing
Expand All @@ -200,6 +258,48 @@ class DoxygenCommandParserTests: XCTestCase {
XCTAssertEqual(document.debugDescription(options: .printSourceLocations), expectedDump)
}

func testSourceLocationsWithIndentation() {
let source = """
@param thing The thing.
This is the thing that is messed with.
"""

let document = Document(parsing: source, options: parseOptions)

let expectedDump = """
Document @1:1-2:43
└─ DoxygenParameter @1:1-2:43 parameter: thing
└─ Paragraph @1:14-2:43
├─ Text @1:14-1:24 "The thing."
├─ SoftBreak
└─ Text @2:5-2:43 "This is the thing that is messed with."
"""
XCTAssertEqual(document.debugDescription(options: .printSourceLocations), expectedDump)
}

func testSourceLocationsWithIndentedAtSign() {
let source = """
Method description.

@param thing The thing.
This is the thing that is messed with.
"""

let document = Document(parsing: source, options: parseOptions)

let expectedDump = """
Document @1:1-4:43
├─ Paragraph @1:1-1:20
│ └─ Text @1:1-1:20 "Method description."
└─ DoxygenParameter @3:2-4:43 parameter: thing
└─ Paragraph @3:15-4:43
├─ Text @3:15-3:25 "The thing."
├─ SoftBreak
└─ Text @4:5-4:43 "This is the thing that is messed with."
"""
XCTAssertEqual(document.debugDescription(options: .printSourceLocations), expectedDump)
}

func testDoesNotParseWithoutOption() {
do {
let source = """
Expand Down