Skip to content

Add primary associated type to RegexComponent #454

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
May 29, 2022
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
82 changes: 41 additions & 41 deletions Sources/RegexBuilder/Algorithms.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ extension BidirectionalCollection where SubSequence == Substring {
/// - Parameter content: A closure that returns a regex to match against.
/// - Returns: The match if there is one, or `nil` if none.
@available(SwiftStdlib 5.7, *)
public func wholeMatch<R: RegexComponent>(
@RegexComponentBuilder of content: () -> R
) -> Regex<R.RegexOutput>.Match? {
public func wholeMatch<Output>(
@RegexComponentBuilder of content: () -> some RegexComponent<Output>
) -> Regex<Output>.Match? {
wholeMatch(of: content())
}

Expand All @@ -35,9 +35,9 @@ extension BidirectionalCollection where SubSequence == Substring {
/// - Parameter content: A closure that returns a regex to match against.
/// - Returns: The match if there is one, or `nil` if none.
@available(SwiftStdlib 5.7, *)
public func prefixMatch<R: RegexComponent>(
@RegexComponentBuilder of content: () -> R
) -> Regex<R.RegexOutput>.Match? {
public func prefixMatch<Output>(
@RegexComponentBuilder of content: () -> some RegexComponent<Output>
) -> Regex<Output>.Match? {
prefixMatch(of: content())
}

Expand All @@ -49,8 +49,8 @@ extension BidirectionalCollection where SubSequence == Substring {
/// - Returns: `true` if the regex returned by `content` matched anywhere in
/// this collection, otherwise `false`.
@available(SwiftStdlib 5.7, *)
public func contains<R: RegexComponent>(
@RegexComponentBuilder _ content: () -> R
public func contains(
@RegexComponentBuilder _ content: () -> some RegexComponent
) -> Bool {
contains(content())
}
Comment on lines 51 to 56
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately I believe these will fail to integrate with the current Swift compiler due to rdar://92459215, see the comment at the top of the file (I don't know if some RegexComponent<Output> works tho)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh huh, I see swiftlang/swift#42532 passed, maybe that's just an issue on main?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened #458 to verify

Copy link
Contributor

@hamishknight hamishknight May 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, seems to be fixed now (other test failure unrelated)

Edit: Looks like it was fixed by swiftlang/swift#58991

Expand All @@ -63,8 +63,8 @@ extension BidirectionalCollection where SubSequence == Substring {
/// match of if the regex returned by `content`. Returns `nil` if no match
/// for the regex is found.
@available(SwiftStdlib 5.7, *)
public func firstRange<R: RegexComponent>(
@RegexComponentBuilder of content: () -> R
public func firstRange(
@RegexComponentBuilder of content: () -> some RegexComponent
) -> Range<Index>? {
firstRange(of: content())
}
Expand All @@ -78,8 +78,8 @@ extension BidirectionalCollection where SubSequence == Substring {
/// `content`. Returns an empty collection if no match for the regex
/// is found.
@available(SwiftStdlib 5.7, *)
public func ranges<R: RegexComponent>(
@RegexComponentBuilder of content: () -> R
public func ranges(
@RegexComponentBuilder of content: () -> some RegexComponent
) -> [Range<Index>] {
ranges(of: content())
}
Expand All @@ -99,10 +99,10 @@ extension BidirectionalCollection where SubSequence == Substring {
/// - Returns: A collection of substrings, split from this collection's
/// elements.
@available(SwiftStdlib 5.7, *)
public func split<R: RegexComponent>(
public func split(
maxSplits: Int = Int.max,
omittingEmptySubsequences: Bool = true,
@RegexComponentBuilder separator: () -> R
@RegexComponentBuilder separator: () -> some RegexComponent
) -> [SubSequence] {
split(separator: separator(), maxSplits: maxSplits, omittingEmptySubsequences: omittingEmptySubsequences)
}
Expand All @@ -115,8 +115,8 @@ extension BidirectionalCollection where SubSequence == Substring {
/// - Returns: `true` if the initial elements of this collection match
/// regex returned by `content`; otherwise, `false`.
@available(SwiftStdlib 5.7, *)
public func starts<R: RegexComponent>(
@RegexComponentBuilder with content: () -> R
public func starts(
@RegexComponentBuilder with content: () -> some RegexComponent
) -> Bool {
starts(with: content())
}
Expand All @@ -132,8 +132,8 @@ extension BidirectionalCollection where SubSequence == Substring {
/// the start of the collection, the entire contents of this collection
/// are returned.
@available(SwiftStdlib 5.7, *)
public func trimmingPrefix<R: RegexComponent>(
@RegexComponentBuilder _ content: () -> R
public func trimmingPrefix(
@RegexComponentBuilder _ content: () -> some RegexComponent
) -> SubSequence {
trimmingPrefix(content())
}
Expand All @@ -145,9 +145,9 @@ extension BidirectionalCollection where SubSequence == Substring {
/// - Returns: The first match for the regex created by `content` in this
/// collection, or `nil` if no match is found.
@available(SwiftStdlib 5.7, *)
public func firstMatch<R: RegexComponent>(
@RegexComponentBuilder of content: () -> R
) -> Regex<R.RegexOutput>.Match? {
public func firstMatch<Output>(
@RegexComponentBuilder of content: () -> some RegexComponent<Output>
) -> Regex<Output>.Match? {
firstMatch(of: content())
}

Expand All @@ -159,9 +159,9 @@ extension BidirectionalCollection where SubSequence == Substring {
/// - Returns: A collection of matches for the regex returned by `content`.
/// If no matches are found, the returned collection is empty.
@available(SwiftStdlib 5.7, *)
public func matches<R: RegexComponent>(
@RegexComponentBuilder of content: () -> R
) -> [Regex<R.RegexOutput>.Match] {
public func matches<Output>(
@RegexComponentBuilder of content: () -> some RegexComponent<Output>
) -> [Regex<Output>.Match] {
matches(of: content())
}
}
Expand All @@ -175,8 +175,8 @@ where Self: BidirectionalCollection, SubSequence == Substring {
/// - Parameter content: A closure that returns the regex to search for
/// at the start of this collection.
@available(SwiftStdlib 5.7, *)
public mutating func trimPrefix<R: RegexComponent>(
@RegexComponentBuilder _ content: () -> R
public mutating func trimPrefix(
@RegexComponentBuilder _ content: () -> some RegexComponent
) {
trimPrefix(content())
}
Expand All @@ -196,11 +196,11 @@ where Self: BidirectionalCollection, SubSequence == Substring {
/// - Returns: A new collection in which all matches for regex in `subrange`
/// are replaced by `replacement`, using `content` to create the regex.
@available(SwiftStdlib 5.7, *)
public func replacing<R: RegexComponent, Replacement: Collection>(
public func replacing<Replacement: Collection>(
with replacement: Replacement,
subrange: Range<Index>,
maxReplacements: Int = .max,
@RegexComponentBuilder content: () -> R
@RegexComponentBuilder content: () -> some RegexComponent
) -> Self where Replacement.Element == Element {
replacing(content(), with: replacement, subrange: subrange, maxReplacements: maxReplacements)
}
Expand All @@ -218,10 +218,10 @@ where Self: BidirectionalCollection, SubSequence == Substring {
/// - Returns: A new collection in which all matches for regex in `subrange`
/// are replaced by `replacement`, using `content` to create the regex.
@available(SwiftStdlib 5.7, *)
public func replacing<R: RegexComponent, Replacement: Collection>(
public func replacing<Replacement: Collection>(
with replacement: Replacement,
maxReplacements: Int = .max,
@RegexComponentBuilder content: () -> R
@RegexComponentBuilder content: () -> some RegexComponent
) -> Self where Replacement.Element == Element {
replacing(content(), with: replacement, maxReplacements: maxReplacements)
}
Expand All @@ -237,10 +237,10 @@ where Self: BidirectionalCollection, SubSequence == Substring {
/// - content: A closure that returns the collection to search for
/// and replace.
@available(SwiftStdlib 5.7, *)
public mutating func replace<R: RegexComponent, Replacement: Collection>(
public mutating func replace<Replacement: Collection>(
with replacement: Replacement,
maxReplacements: Int = .max,
@RegexComponentBuilder content: () -> R
@RegexComponentBuilder content: () -> some RegexComponent
) where Replacement.Element == Element {
replace(content(), with: replacement, maxReplacements: maxReplacements)
}
Expand All @@ -262,11 +262,11 @@ where Self: BidirectionalCollection, SubSequence == Substring {
/// are replaced by the result of calling `replacement`, where regex
/// is the result of calling `content`.
@available(SwiftStdlib 5.7, *)
public func replacing<R: RegexComponent, Replacement: Collection>(
public func replacing<Output, Replacement: Collection>(
subrange: Range<Index>,
maxReplacements: Int = .max,
@RegexComponentBuilder content: () -> R,
with replacement: (Regex<R.RegexOutput>.Match) throws -> Replacement
@RegexComponentBuilder content: () -> some RegexComponent<Output>,
with replacement: (Regex<Output>.Match) throws -> Replacement
) rethrows -> Self where Replacement.Element == Element {
try replacing(content(), subrange: subrange, maxReplacements: maxReplacements, with: replacement)
}
Expand All @@ -286,10 +286,10 @@ where Self: BidirectionalCollection, SubSequence == Substring {
/// are replaced by the result of calling `replacement`, where regex is
/// the result of calling `content`.
@available(SwiftStdlib 5.7, *)
public func replacing<R: RegexComponent, Replacement: Collection>(
public func replacing<Output, Replacement: Collection>(
maxReplacements: Int = .max,
@RegexComponentBuilder content: () -> R,
with replacement: (Regex<R.RegexOutput>.Match) throws -> Replacement
@RegexComponentBuilder content: () -> some RegexComponent<Output>,
with replacement: (Regex<Output>.Match) throws -> Replacement
) rethrows -> Self where Replacement.Element == Element {
try replacing(content(), maxReplacements: maxReplacements, with: replacement)
}
Expand All @@ -305,10 +305,10 @@ where Self: BidirectionalCollection, SubSequence == Substring {
/// - replacement: A closure that receives the full match information,
/// including captures, and returns a replacement collection.
@available(SwiftStdlib 5.7, *)
public mutating func replace<R: RegexComponent, Replacement: Collection>(
public mutating func replace<Output, Replacement: Collection>(
maxReplacements: Int = .max,
@RegexComponentBuilder content: () -> R,
with replacement: (Regex<R.RegexOutput>.Match) throws -> Replacement
@RegexComponentBuilder content: () -> some RegexComponent<Output>,
with replacement: (Regex<Output>.Match) throws -> Replacement
) rethrows where Replacement.Element == Element {
try replace(content(), maxReplacements: maxReplacements, with: replacement)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ extension BidirectionalCollection where SubSequence == Substring {
/// `false`.
@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public func contains<R: RegexComponent>(_ regex: R) -> Bool {
public func contains(_ regex: some RegexComponent) -> Bool {
_contains(RegexConsumer(regex))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ extension BidirectionalCollection where SubSequence == Substring {
/// Returns `nil` if `regex` is not found.
@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public func firstRange<R: RegexComponent>(of regex: R) -> Range<Index>? {
public func firstRange(of regex: some RegexComponent) -> Range<Index>? {
_firstRange(of: RegexConsumer(regex))
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,8 @@ extension BidirectionalCollection where SubSequence == Substring {
/// `regex`. Returns an empty collection if `regex` is not found.
@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public func ranges<R: RegexComponent>(
of regex: R
public func ranges(
of regex: some RegexComponent
) -> [Range<Index>] {
Array(_ranges(of: regex))
}
Expand Down
12 changes: 6 additions & 6 deletions Sources/_StringProcessing/Algorithms/Algorithms/Replace.swift
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ extension RangeReplaceableCollection where SubSequence == Substring {
/// - Returns: A new collection in which all occurrences of subsequence
/// matching `regex` in `subrange` are replaced by `replacement`.
@available(SwiftStdlib 5.7, *)
public func replacing<R: RegexComponent, Replacement: Collection>(
_ regex: R,
public func replacing<Replacement: Collection>(
_ regex: some RegexComponent,
with replacement: Replacement,
subrange: Range<Index>,
maxReplacements: Int = .max
Expand All @@ -212,8 +212,8 @@ extension RangeReplaceableCollection where SubSequence == Substring {
/// matching `regex` are replaced by `replacement`.
@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public func replacing<R: RegexComponent, Replacement: Collection>(
_ regex: R,
public func replacing<Replacement: Collection>(
_ regex: some RegexComponent,
with replacement: Replacement,
maxReplacements: Int = .max
) -> Self where Replacement.Element == Element {
Expand All @@ -232,8 +232,8 @@ extension RangeReplaceableCollection where SubSequence == Substring {
/// - maxReplacements: A number specifying how many occurrences of the
/// sequence matching `regex` to replace. Default is `Int.max`.
@available(SwiftStdlib 5.7, *)
public mutating func replace<R: RegexComponent, Replacement: Collection>(
_ regex: R,
public mutating func replace<Replacement: Collection>(
_ regex: some RegexComponent,
with replacement: Replacement,
maxReplacements: Int = .max
) where Replacement.Element == Element {
Expand Down
4 changes: 2 additions & 2 deletions Sources/_StringProcessing/Algorithms/Algorithms/Split.swift
Original file line number Diff line number Diff line change
Expand Up @@ -426,8 +426,8 @@ extension BidirectionalCollection where SubSequence == Substring {
/// - Returns: A collection of substrings, split from this collection's
/// elements.
@_disfavoredOverload
public func split<R: RegexComponent>(
separator: R,
public func split(
separator: some RegexComponent,
maxSplits: Int = .max,
omittingEmptySubsequences: Bool = true
) -> [SubSequence] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ extension BidirectionalCollection where SubSequence == Substring {
/// - Parameter regex: A regex to compare to this sequence.
/// - Returns: `true` if the initial elements of the sequence matches the
/// beginning of `regex`; otherwise, `false`.
public func starts<R: RegexComponent>(with regex: R) -> Bool {
public func starts(with regex: some RegexComponent) -> Bool {
_starts(with: RegexConsumer(regex))
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ extension BidirectionalCollection where SubSequence == Substring {
/// `prefix` from the start.
@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public func trimmingPrefix<R: RegexComponent>(_ regex: R) -> SubSequence {
public func trimmingPrefix(_ regex: some RegexComponent) -> SubSequence {
_trimmingPrefix(RegexConsumer(regex))
}

Expand All @@ -313,7 +313,7 @@ extension RangeReplaceableCollection
/// - Parameter regex: The regex to remove from this collection.
@_disfavoredOverload
@available(SwiftStdlib 5.7, *)
public mutating func trimPrefix<R: RegexComponent>(_ regex: R) {
public mutating func trimPrefix(_ regex: some RegexComponent) {
_trimPrefix(RegexConsumer(regex))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ extension BidirectionalCollection where SubSequence == Substring {
/// - Returns: The first match of `regex` in the collection, or `nil` if
/// there isn't a match.
@available(SwiftStdlib 5.7, *)
public func firstMatch<R: RegexComponent>(
of r: R
) -> Regex<R.RegexOutput>.Match? {
public func firstMatch<Output>(
of r: some RegexComponent<Output>
) -> Regex<Output>.Match? {
let slice = self[...]
return try? r.regex.firstMatch(in: slice)
}
Expand Down
18 changes: 9 additions & 9 deletions Sources/_StringProcessing/Algorithms/Matching/MatchReplace.swift
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,11 @@ extension RangeReplaceableCollection where SubSequence == Substring {
/// - Returns: A new collection in which all occurrences of subsequence
/// matching `regex` are replaced by `replacement`.
@available(SwiftStdlib 5.7, *)
public func replacing<R: RegexComponent, Replacement: Collection>(
_ regex: R,
public func replacing<Output, Replacement: Collection>(
_ regex: some RegexComponent<Output>,
subrange: Range<Index>,
maxReplacements: Int = .max,
with replacement: (Regex<R.RegexOutput>.Match) throws -> Replacement
with replacement: (Regex<Output>.Match) throws -> Replacement
) rethrows -> Self where Replacement.Element == Element {

precondition(maxReplacements >= 0)
Expand Down Expand Up @@ -162,10 +162,10 @@ extension RangeReplaceableCollection where SubSequence == Substring {
/// - Returns: A new collection in which all occurrences of subsequence
/// matching `regex` are replaced by `replacement`.
@available(SwiftStdlib 5.7, *)
public func replacing<R: RegexComponent, Replacement: Collection>(
_ regex: R,
public func replacing<Output, Replacement: Collection>(
_ regex: some RegexComponent<Output>,
maxReplacements: Int = .max,
with replacement: (Regex<R.RegexOutput>.Match) throws -> Replacement
with replacement: (Regex<Output>.Match) throws -> Replacement
) rethrows -> Self where Replacement.Element == Element {
try replacing(
regex,
Expand All @@ -183,10 +183,10 @@ extension RangeReplaceableCollection where SubSequence == Substring {
/// - replacement: A closure that receives the full match information,
/// including captures, and returns a replacement collection.
@available(SwiftStdlib 5.7, *)
public mutating func replace<R: RegexComponent, Replacement: Collection>(
_ regex: R,
public mutating func replace<Output, Replacement: Collection>(
_ regex: some RegexComponent<Output>,
maxReplacements: Int = .max,
with replacement: (Regex<R.RegexOutput>.Match) throws -> Replacement
with replacement: (Regex<Output>.Match) throws -> Replacement
) rethrows where Replacement.Element == Element {
self = try replacing(
regex,
Expand Down
8 changes: 4 additions & 4 deletions Sources/_StringProcessing/Algorithms/Matching/Matches.swift
Original file line number Diff line number Diff line change
Expand Up @@ -204,15 +204,15 @@ extension BidirectionalCollection where SubSequence == Substring {
/// - Parameter regex: The regex to search for.
/// - Returns: A collection of matches of `regex`.
@available(SwiftStdlib 5.7, *)
public func matches<R: RegexComponent>(
of r: R
) -> [Regex<R.RegexOutput>.Match] {
public func matches<Output>(
of r: some RegexComponent<Output>
) -> [Regex<Output>.Match] {
let slice = self[...]
var start = self.startIndex
let end = self.endIndex
let regex = r.regex

var result = [Regex<R.RegexOutput>.Match]()
var result = [Regex<Output>.Match]()
while start <= end {
guard let match = try? regex._firstMatch(
slice.base, in: start..<end
Expand Down
2 changes: 1 addition & 1 deletion Sources/_StringProcessing/Regex/Core.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

/// A type that represents a regular expression.
@available(SwiftStdlib 5.7, *)
public protocol RegexComponent {
public protocol RegexComponent<RegexOutput> {
associatedtype RegexOutput
var regex: Regex<RegexOutput> { get }
}
Expand Down