Skip to content

[5.7] Cherry pick a RegexBuilder and StringProcessing change #534

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
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
5 changes: 0 additions & 5 deletions Sources/RegexBuilder/Algorithms.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@

@_spi(RegexBuilder) import _StringProcessing

// FIXME(rdar://92459215): We should be using 'some RegexComponent' instead of
// <R: RegexComponent> for the methods below that don't impose any additional
// requirements on the type. Currently the generic parameter is needed to work
// around a compiler issue.

extension BidirectionalCollection where SubSequence == Substring {
/// Matches a regex in its entirety, where the regex is created by
/// the given closure.
Expand Down
6 changes: 4 additions & 2 deletions Sources/RegexBuilder/Builder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ public enum RegexComponentBuilder {
_RegexFactory().empty()
}

public static func buildPartialBlock<R: RegexComponent>(first: R ) -> R {
first
public static func buildPartialBlock<R: RegexComponent>(
first component: R
) -> Regex<R.RegexOutput> {
component.regex
}

public static func buildExpression<R: RegexComponent>(_ regex: R) -> R {
Expand Down
2 changes: 1 addition & 1 deletion Sources/_StringProcessing/Regex/Match.swift
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ extension BidirectionalCollection where SubSequence == Substring {
public func wholeMatch<R: RegexComponent>(
of r: R
) -> Regex<R.RegexOutput>.Match? {
try? r.regex.wholeMatch(in: self[...].base)
try? r.regex.wholeMatch(in: self[...])
}

/// Checks for a match against the string, starting at its beginning.
Expand Down
10 changes: 10 additions & 0 deletions Tests/RegexBuilderTests/AlgorithmsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,16 @@ class AlgorithmsResultBuilderTests: XCTestCase {
}

func testMatches() throws {
do {
let regex = Regex { OneOrMore(.any) }
XCTAssertEqual("abc".wholeMatch(of: regex)!.0, "abc")
XCTAssertEqual("abc".prefixMatch(of: regex)!.0, "abc")
XCTAssertEqual("abc".firstMatch(of: regex)!.0, "abc")
XCTAssertEqual("abc".suffix(1).wholeMatch(of: regex)!.0, "c")
XCTAssertEqual("abc".suffix(1).prefixMatch(of: regex)!.0, "c")
XCTAssertEqual("abc".suffix(1).firstMatch(of: regex)!.0, "c")
}

let int = Capture(OneOrMore(.digit)) { Int($0)! }

// Test syntax
Expand Down
22 changes: 21 additions & 1 deletion Tests/RegexBuilderTests/RegexDSLTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ class RegexDSLTests: XCTestCase {
XCTAssertEqual(str.wholeMatch(of: parser)?.1, version)
}
}

func testZeroWidthConsumer() throws {
struct Trace: CustomConsumingRegexComponent {
typealias RegexOutput = Void
Expand Down Expand Up @@ -1088,6 +1088,26 @@ class RegexDSLTests: XCTestCase {

""")
}

func testRegexComponentBuilderResultType() {
// Test that the user can declare a closure or computed property marked with
// `@RegexComponentBuilder` with `Regex` as the result type.
@RegexComponentBuilder
var unaryWithSingleNonRegex: Regex<Substring> {
OneOrMore("a")
}
@RegexComponentBuilder
var multiComponent: Regex<Substring> {
OneOrMore("a")
"b"
}
struct MyCustomRegex: RegexComponent {
@RegexComponentBuilder
var regex: Regex<Substring> {
OneOrMore("a")
}
}
}
}

extension Unicode.Scalar {
Expand Down