Skip to content

don't automatically transfer the child elements' ranges to the parent #202

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 4 commits into from
Sep 24, 2024
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
10 changes: 8 additions & 2 deletions Sources/Markdown/Base/Document.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,14 @@ public extension Document {
}

/// Create a document from a sequence of block markup elements.
init<Children: Sequence>(_ children: Children) where Children.Element == BlockMarkup {
try! self.init(.document(parsedRange: nil, children.map { $0.raw.markup }))
init(_ children: some Sequence<BlockMarkup>) {
self.init(children, inheritSourceRange: false)
}

init(_ children: some Sequence<BlockMarkup>, inheritSourceRange: Bool) {
let rawChildren = children.map { $0.raw.markup }
let parsedRange = inheritSourceRange ? rawChildren.parsedRange : nil
try! self.init(.document(parsedRange: parsedRange, rawChildren))
}

// MARK: Visitation
Expand Down
14 changes: 12 additions & 2 deletions Sources/Markdown/Base/RawMarkup.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 Apple Inc. and the Swift project authors
Copyright (c) 2021-2024 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 @@ -196,7 +196,7 @@ final class RawMarkup: ManagedBuffer<RawMarkupHeader, RawMarkup> {

let parsedRange: SourceRange?
if preserveRange {
parsedRange = header.parsedRange ?? newChild.header.parsedRange
parsedRange = header.parsedRange
} else {
parsedRange = newChild.header.parsedRange
}
Expand Down Expand Up @@ -366,3 +366,13 @@ fileprivate extension Sequence where Element == RawMarkup {
return self.lazy.map { $0.subtreeCount }.reduce(0, +)
}
}

extension BidirectionalCollection where Element == RawMarkup {
var parsedRange: SourceRange? {
if let lowerBound = first?.parsedRange?.lowerBound, let upperBound = last?.parsedRange?.upperBound {
return lowerBound..<upperBound
} else {
return nil
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,14 @@ public struct BlockQuote: BlockMarkup, BasicBlockContainer {
public extension BlockQuote {
// MARK: BasicBlockContainer

init<Children: Sequence>(_ children: Children) where Children.Element == BlockMarkup {
try! self.init(.blockQuote(parsedRange: nil, children.map { $0.raw.markup }))
init(_ children: some Sequence<BlockMarkup>) {
self.init(children, inheritSourceRange: false)
}

init(_ children: some Sequence<BlockMarkup>, inheritSourceRange: Bool) {
let rawChildren = children.map { $0.raw.markup }
let parsedRange = inheritSourceRange ? rawChildren.parsedRange : nil
try! self.init(.blockQuote(parsedRange: parsedRange, rawChildren))
}

// MARK: Visitation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,14 @@ public struct CustomBlock: BlockMarkup, BasicBlockContainer {
// MARK: - Public API

public extension CustomBlock {
init<Children: Sequence>(_ children: Children) where Children.Element == BlockMarkup {
try! self.init(.customBlock(parsedRange: nil, children.map { $0.raw.markup }))
init(_ children: some Sequence<BlockMarkup>) {
self.init(children, inheritSourceRange: false)
}

init(_ children: some Sequence<BlockMarkup>, inheritSourceRange: Bool) {
let rawChildren = children.map { $0.raw.markup }
let parsedRange = inheritSourceRange ? rawChildren.parsedRange : nil
try! self.init(.customBlock(parsedRange: parsedRange, rawChildren))
}

// MARK: Visitation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,14 @@ public struct Paragraph: BlockMarkup, BasicInlineContainer {
public extension Paragraph {
// MARK: InlineContainer

init<Children: Sequence>(_ newChildren: Children) where Children.Element == InlineMarkup {
try! self.init(.paragraph(parsedRange: nil, newChildren.map { $0.raw.markup }))
init(_ newChildren: some Sequence<InlineMarkup>) {
self.init(newChildren, inheritSourceRange: false)
}

init(_ newChildren: some Sequence<InlineMarkup>, inheritSourceRange: Bool) {
let rawChildren = newChildren.map { $0.raw.markup }
let parsedRange = inheritSourceRange ? rawChildren.parsedRange : nil
try! self.init(.paragraph(parsedRange: parsedRange, rawChildren))
}

// MARK: Visitation
Expand Down
16 changes: 13 additions & 3 deletions Sources/Markdown/Block Nodes/Tables/TableCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,22 @@ public extension Table.Cell {

// MARK: BasicInlineContainer

init<Children>(_ children: Children) where Children : Sequence, Children.Element == InlineMarkup {
init(_ children: some Sequence<InlineMarkup>) {
self.init(colspan: 1, rowspan: 1, children)
}

init<Children>(colspan: UInt, rowspan: UInt, _ children: Children) where Children : Sequence, Children.Element == InlineMarkup {
try! self.init(RawMarkup.tableCell(parsedRange: nil, colspan: colspan, rowspan: rowspan, children.map { $0.raw.markup }))
init(_ children: some Sequence<InlineMarkup>, inheritSourceRange: Bool) {
self.init(colspan: 1, rowspan: 1, children, inheritSourceRange: inheritSourceRange)
}

init(colspan: UInt, rowspan: UInt, _ children: some Sequence<InlineMarkup>) {
self.init(colspan: colspan, rowspan: rowspan, children, inheritSourceRange: false)
}

init(colspan: UInt, rowspan: UInt, _ children: some Sequence<InlineMarkup>, inheritSourceRange: Bool) {
let rawChildren = children.map { $0.raw.markup }
let parsedRange = inheritSourceRange ? rawChildren.parsedRange : nil
try! self.init(.tableCell(parsedRange: parsedRange, colspan: colspan, rowspan: rowspan, rawChildren))
}

// MARK: Visitation
Expand Down
10 changes: 8 additions & 2 deletions Sources/Markdown/Inline Nodes/Inline Containers/Emphasis.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,14 @@ public struct Emphasis: RecurringInlineMarkup, BasicInlineContainer {
public extension Emphasis {
// MARK: BasicInlineContainer

init<Children>(_ newChildren: Children) where Children : Sequence, Children.Element == InlineMarkup {
try! self.init(RawMarkup.emphasis(parsedRange: nil, newChildren.map { $0.raw.markup }))
init(_ newChildren: some Sequence<InlineMarkup>) {
self.init(newChildren, inheritSourceRange: false)
}

init(_ newChildren: some Sequence<InlineMarkup>, inheritSourceRange: Bool) {
let rawChildren = newChildren.map { $0.raw.markup }
let parsedRange = inheritSourceRange ? rawChildren.parsedRange : nil
try! self.init(.emphasis(parsedRange: parsedRange, rawChildren))
}

// MARK: PlainTextConvertibleMarkup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,14 @@ public struct Strikethrough: RecurringInlineMarkup, BasicInlineContainer {
public extension Strikethrough {
// MARK: BasicInlineContainer

init<Children>(_ newChildren: Children) where Children : Sequence, Children.Element == InlineMarkup {
try! self.init(.strikethrough(parsedRange: nil, newChildren.map { $0.raw.markup }))
init(_ newChildren: some Sequence<InlineMarkup>) {
self.init(newChildren, inheritSourceRange: false)
}

init(_ newChildren: some Sequence<InlineMarkup>, inheritSourceRange: Bool) {
let rawChildren = newChildren.map { $0.raw.markup }
let parsedRange = inheritSourceRange ? rawChildren.parsedRange : nil
try! self.init(.strikethrough(parsedRange: parsedRange, rawChildren))
}

// MARK: PlainTextConvertibleMarkup
Expand Down
10 changes: 8 additions & 2 deletions Sources/Markdown/Inline Nodes/Inline Containers/Strong.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,14 @@ public struct Strong: RecurringInlineMarkup, BasicInlineContainer {
public extension Strong {
// MARK: BasicInlineContainer

init<Children>(_ newChildren: Children) where Children : Sequence, Children.Element == InlineMarkup {
try! self.init(.strong(parsedRange: nil, newChildren.map { $0.raw.markup }))
init(_ newChildren: some Sequence<InlineMarkup>) {
self.init(newChildren, inheritSourceRange: false)
}

init(_ newChildren: some Sequence<InlineMarkup>, inheritSourceRange: Bool) {
let rawChildren = newChildren.map { $0.raw.markup }
let parsedRange = inheritSourceRange ? rawChildren.parsedRange : nil
try! self.init(.strong(parsedRange: parsedRange, rawChildren))
}

// MARK: PlainTextConvertibleMarkup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
/// A block element that can contain only other block elements and doesn't require any other information.
public protocol BasicBlockContainer: BlockContainer {
/// Create this element from a sequence of block markup elements.
init<Children: Sequence>(_ children: Children) where Children.Element == BlockMarkup
init(_ children: some Sequence<BlockMarkup>)

/// Create this element from a sequence of block markup elements, and optionally inherit the source range from those elements.
init(_ children: some Sequence<BlockMarkup>, inheritSourceRange: Bool)
}

// MARK: - Public API
Expand All @@ -21,4 +24,14 @@ extension BasicBlockContainer {
public init(_ children: BlockMarkup...) {
self.init(children)
}

/// Create this element with a sequence of block markup elements, and optionally inherit the source range from those elements.
public init(_ children: BlockMarkup..., inheritSourceRange: Bool) {
self.init(children, inheritSourceRange: inheritSourceRange)
}

/// Default implementation of `init(_:inheritSourceRange:)` that discards the `inheritSourceRange` parameter.
public init(_ children: some Sequence<BlockMarkup>, inheritSourceRange: Bool) {
self.init(children)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,24 @@
/// A block or inline markup element that can contain only `InlineMarkup` elements and doesn't require any other information.
public protocol BasicInlineContainer: InlineContainer {
/// Create this element with a sequence of inline markup elements.
init<Children: Sequence>(_ children: Children) where Children.Element == InlineMarkup
init(_ children: some Sequence<InlineMarkup>)

/// Create this element with a sequence of inline markup elements, and optionally inherit the source range from those elements.
init(_ children: some Sequence<InlineMarkup>, inheritSourceRange: Bool)
}

extension BasicInlineContainer {
/// Create this element with a sequence of inline markup elements.
public init(_ children: InlineMarkup...) {
self.init(children)
}

public init(_ children: InlineMarkup..., inheritSourceRange: Bool) {
self.init(children, inheritSourceRange: inheritSourceRange)
}

/// Default implementation for `init(_:inheritSourceRange:)` that discards the `inheritSourceRange` parameter.
public init(_ children: some Sequence<InlineMarkup>, inheritSourceRange: Bool) {
self.init(children)
}
}
21 changes: 21 additions & 0 deletions Tests/MarkdownTests/Interpretive Nodes/AsideTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,27 @@ class AsideTests: XCTestCase {
}
}

/// Ensure that creating block quotes by construction doesn't trip the "loss of source information" assertion
/// by mistakenly gaining source information.
func testConstructedBlockQuoteDoesntChangeRangeSource() throws {
let source = "Note: This is just a paragraph."
let fakeFileLocation = URL(fileURLWithPath: "/path/to/some-file.md")
let document = Document(parsing: source, source: fakeFileLocation)
let paragraph = try XCTUnwrap(document.child(at: 0) as? Paragraph)

// this block quote has no source information, but its children do
let blockQuote = BlockQuote(paragraph)
let aside = try XCTUnwrap(Aside(blockQuote))

let expectedRootDump = """
BlockQuote
└─ Paragraph @/path/to/some-file.md:1:1-/path/to/some-file.md:1:32
└─ Text @/path/to/some-file.md:1:7-/path/to/some-file.md:1:32 "This is just a paragraph."
"""

XCTAssertEqual(expectedRootDump, aside.content[0].root.debugDescription(options: .printSourceLocations))
}

func assertAside(source: String, conversionStrategy: Aside.TagRequirement, expectedKind: Aside.Kind, expectedRootDump: String, file: StaticString = #file, line: UInt = #line) throws {
let fakeFileLocation = URL(fileURLWithPath: "/path/to/some-file.md")
let document = Document(parsing: source, source: fakeFileLocation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,22 @@ final class BasicBlockContainerTests: XCTestCase {
"""
XCTAssertEqual(expectedDump, newDocument.debugDescription())
}

func testInheritSourceRange() throws {
let source = "Note: This is just a paragraph."
let fakeFileLocation = URL(fileURLWithPath: "/path/to/some-file.md")
let document = Document(parsing: source, source: fakeFileLocation)
let paragraph = try XCTUnwrap(document.child(at: 0) as? Paragraph)

// this block quote has no source information, but its children do
let blockQuote = BlockQuote(paragraph, inheritSourceRange: true)

let expectedRootDump = """
BlockQuote @/path/to/some-file.md:1:1-/path/to/some-file.md:1:32
└─ Paragraph @/path/to/some-file.md:1:1-/path/to/some-file.md:1:32
└─ Text @/path/to/some-file.md:1:1-/path/to/some-file.md:1:32 "Note: This is just a paragraph."
"""

XCTAssertEqual(expectedRootDump, blockQuote.debugDescription(options: .printSourceLocations))
}
}