Skip to content

Commit cde3ef1

Browse files
authored
Merge pull request #9654 from phausler/swift-4.0-branch-NSRange_improvements
[Foundation] add additional conformances and functionality to NSRange
2 parents 3d49842 + 2c01358 commit cde3ef1

File tree

5 files changed

+119
-23
lines changed

5 files changed

+119
-23
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6086,13 +6086,15 @@ void TypeChecker::checkConformancesInContext(DeclContext *dc,
60866086
auto extendedNominal =
60876087
diag.ExistingDC->getAsNominalTypeOrNominalTypeExtensionContext();
60886088
if (existingModule != dc->getParentModule() &&
6089-
(existingModule == extendedNominal->getParentModule() ||
6089+
(existingModule->getName() ==
6090+
extendedNominal->getParentModule()->getName() ||
60906091
existingModule == diag.Protocol->getParentModule())) {
60916092
// Warn about the conformance.
60926093
diagnose(diag.Loc, diag::redundant_conformance_adhoc,
60936094
dc->getDeclaredInterfaceType(),
60946095
diag.Protocol->getName(),
6095-
existingModule == extendedNominal->getParentModule(),
6096+
existingModule->getName() ==
6097+
extendedNominal->getParentModule()->getName(),
60966098
existingModule->getName());
60976099

60986100
// Complain about any declarations in this extension whose names match

stdlib/public/SDK/Foundation/NSRange.swift

Lines changed: 106 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,121 @@
1212

1313
@_exported import Foundation // Clang module
1414

15+
extension NSRange : Hashable {
16+
public var hashValue: Int {
17+
#if arch(i386) || arch(arm)
18+
return Int(bitPattern: (UInt(bitPattern: location) | (UInt(bitPattern: length) << 16)))
19+
#elseif arch(x86_64) || arch(arm64)
20+
return Int(bitPattern: (UInt(bitPattern: location) | (UInt(bitPattern: length) << 32)))
21+
#endif
22+
}
23+
24+
public static func==(_ lhs: NSRange, _ rhs: NSRange) -> Bool {
25+
return lhs.location == rhs.location && rhs.length == rhs.length
26+
}
27+
}
28+
29+
extension NSRange : CustomStringConvertible, CustomDebugStringConvertible {
30+
public var description: String { return "{\(location), \(length)}" }
31+
public var debugDescription: String { return "{\(location), \(length)}" }
32+
}
33+
34+
extension NSRange {
35+
public init?(_ string: String) {
36+
if string.isEmpty {
37+
// fail early if the string is empty
38+
return nil
39+
}
40+
let scanner = Scanner(string: string)
41+
let digitSet = CharacterSet.decimalDigits
42+
let _ = scanner.scanUpToCharacters(from: digitSet, into: nil)
43+
if scanner.isAtEnd {
44+
// fail early if there are no decimal digits
45+
return nil
46+
}
47+
var location = 0
48+
guard scanner.scanInt(&location) else {
49+
return nil
50+
}
51+
if scanner.isAtEnd {
52+
// return early if there are no more characters after the first int in the string
53+
return nil
54+
}
55+
let _ = scanner.scanUpToCharacters(from: digitSet, into: nil)
56+
if scanner.isAtEnd {
57+
// return early if there are no integer characters after the first int in the string
58+
return nil
59+
}
60+
var length = 0
61+
guard scanner.scanInt(&length) else {
62+
return nil
63+
}
64+
65+
self.location = location
66+
self.length = length
67+
}
68+
}
69+
70+
extension NSRange {
71+
public var lowerBound: Int { return location }
72+
73+
public var upperBound: Int { return location + length }
74+
75+
public func contains(_ index: Int) -> Bool { return (!(index < location) && (index - location) < length) }
76+
77+
public mutating func formUnion(_ other: NSRange) {
78+
self = union(other)
79+
}
80+
81+
public func union(_ other: NSRange) -> NSRange {
82+
let max1 = location + length
83+
let max2 = other.location + other.length
84+
let maxend = (max1 < max2) ? max2 : max1
85+
let minloc = location < other.location ? location : other.location
86+
return NSRange(location: minloc, length: maxend - minloc)
87+
}
88+
89+
public func intersection(_ other: NSRange) -> NSRange? {
90+
let max1 = location + length
91+
let max2 = other.location + other.length
92+
let minend = (max1 < max2) ? max1 : max2
93+
if other.location <= location && location < max2 {
94+
return NSRange(location: location, length: minend - location)
95+
} else if location <= other.location && other.location < max1 {
96+
return NSRange(location: other.location, length: minend - other.location);
97+
}
98+
return nil
99+
}
100+
}
101+
102+
15103
//===----------------------------------------------------------------------===//
16104
// Ranges
17105
//===----------------------------------------------------------------------===//
18106

19107
extension NSRange {
20-
public init(_ x: Range<Int>) {
21-
location = x.lowerBound
22-
length = x.count
23-
}
24-
25-
// FIXME(ABI)#75 (Conditional Conformance): this API should be an extension on Range.
26-
// Can't express it now because the compiler does not support conditional
27-
// extensions with type equality constraints.
28-
public func toRange() -> Range<Int>? {
29-
if location == NSNotFound { return nil }
30-
return location..<(location+length)
31-
}
108+
public init(_ x: Range<Int>) {
109+
location = x.lowerBound
110+
length = x.count
111+
}
112+
113+
// FIXME(ABI)#75 (Conditional Conformance): this API should be an extension on Range.
114+
// Can't express it now because the compiler does not support conditional
115+
// extensions with type equality constraints.
116+
public func toRange() -> Range<Int>? {
117+
if location == NSNotFound { return nil }
118+
return location..<(location+length)
119+
}
32120
}
33121

34122
extension NSRange : CustomReflectable {
35-
public var customMirror: Mirror {
36-
return Mirror(self, children: ["location": location, "length": length])
37-
}
123+
public var customMirror: Mirror {
124+
return Mirror(self, children: ["location": location, "length": length])
125+
}
38126
}
39127

40128
extension NSRange : CustomPlaygroundQuickLookable {
41-
public var customPlaygroundQuickLook: PlaygroundQuickLook {
42-
return .range(Int64(location), Int64(length))
43-
}
129+
public var customPlaygroundQuickLook: PlaygroundQuickLook {
130+
return .range(Int64(location), Int64(length))
131+
}
44132
}

test/Compatibility/bridging-nsnumber-and-nsvalue.swift.gyb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ extension Equatable {
4545
}
4646
}
4747
extension Hashable { public var hashValue: Int { fatalError("trill hiphy") } }
48-
extension NSRange: Hashable {}
4948
extension CGSize: Hashable {}
5049
extension CGPoint: Hashable {}
5150
extension CGRect: Hashable {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-typecheck-verify-swift -swift-version 3
2+
3+
// REQUIRES: objc_interop
4+
5+
import Foundation
6+
7+
extension NSRange : Hashable { // expected-warning{{conformance of '_NSRange' to protocol 'Hashable' was already stated in the type's module 'Foundation'}}
8+
var hashValue: Int { return 0 } // expected-note{{var 'hashValue' will not be used to satisfy the conformance to 'Hashable'}}
9+
}

test/Constraints/bridging-nsnumber-and-nsvalue.swift.gyb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ coercionTypes = {
2929
'CGRect',
3030
'CGPoint',
3131
'CGSize',
32-
'NSRange',
3332
],
3433
}
3534
}%
@@ -41,7 +40,6 @@ extension Equatable {
4140
}
4241
}
4342
extension Hashable { public var hashValue: Int { fatalError("trill hiphy") } }
44-
extension NSRange: Hashable {}
4543
extension CGSize: Hashable {}
4644
extension CGPoint: Hashable {}
4745
extension CGRect: Hashable {}

0 commit comments

Comments
 (0)