WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -374,11 +374,11 @@ extension PredicateExpressions.RangeExpressionContains : ConvertibleExpression {
} else if let rangeValue = (range as? _RangeValue)?._anyRange {
// Otherwise, if the range is a captured value then convert it to appropriate comparison expressions based on the range type
switch rangeValue {
case let .range(upper, lower):
case let .range(lower, upper):
let lowerBoundCondition = _comparison(elementExpr, try _expressionForBound(lower), type: .greaterThanOrEqualTo)
let upperBoundCondition = _comparison(elementExpr, try _expressionForBound(upper), type: .lessThan)
return .predicate(NSCompoundPredicate(andPredicateWithSubpredicates: [lowerBoundCondition, upperBoundCondition]))
case let .closed(upper, lower):
case let .closed(lower, upper):
let lowerValue = try _expressionCompatibleValue(for: lower)
let upperValue = try _expressionCompatibleValue(for: upper)
return .predicate(NSComparisonPredicate(
Expand Down
26 changes: 26 additions & 0 deletions Tests/FoundationEssentialsTests/PredicateConversionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,32 @@ private struct NSPredicateConversionTests {
#expect(!converted.evaluate(with: ObjCObject()))
}

@Test func rangesDistinctBounds() throws {
// Test that captured ranges have correct bounds order in NSPredicate conversion
// This tests the _RangeValue branch in RangeExpressionContains.convert
let lowerDate = Date(timeIntervalSinceReferenceDate: 100)
let upperDate = Date(timeIntervalSinceReferenceDate: 200)
let range = lowerDate ..< upperDate

let predicate = #Predicate<ObjCObject> {
range.contains($0.i)
}
let converted = try #require(convert(predicate))

// Verify the bounds are in the correct order (lower, upper)
#expect(converted == NSPredicate(format: "i >= %@ AND i < %@", lowerDate as NSDate, upperDate as NSDate))

// Create an object with a date in the range
let objInRange = ObjCObject()
objInRange.i = Date(timeIntervalSinceReferenceDate: 150)
#expect(converted.evaluate(with: objInRange), "Date in range should match")

// Create an object with a date outside the range
let objOutOfRange = ObjCObject()
objOutOfRange.i = Date(timeIntervalSinceReferenceDate: 250)
#expect(!converted.evaluate(with: objOutOfRange), "Date outside range should not match")
}

@Test func nonObjC() throws {
let predicate = #Predicate<ObjCObject> {
$0.nonObjCKeypath == 2
Expand Down