Skip to content

Commit 19dc275

Browse files
Convert to Swift 4 (#9)
* Update syntax and build settings for Swift 4 * Fix broken links in README * Update Swift version requirement Mustard is using compactMap(_:)
1 parent 9298ed3 commit 19dc275

File tree

6 files changed

+67
-36
lines changed

6 files changed

+67
-36
lines changed

Mustard.xcodeproj/project.pbxproj

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,18 +173,19 @@
173173
isa = PBXProject;
174174
attributes = {
175175
LastSwiftUpdateCheck = 0820;
176-
LastUpgradeCheck = 0820;
176+
LastUpgradeCheck = 0930;
177177
ORGANIZATIONNAME = "Mathew Sanders";
178178
TargetAttributes = {
179179
AFC3B91C1E16E379005B4A99 = {
180180
CreatedOnToolsVersion = 8.2.1;
181181
DevelopmentTeam = AA32363L2C;
182-
LastSwiftMigration = 0820;
182+
LastSwiftMigration = 0930;
183183
ProvisioningStyle = Automatic;
184184
};
185185
AFC3B9251E16E379005B4A99 = {
186186
CreatedOnToolsVersion = 8.2.1;
187187
DevelopmentTeam = AA32363L2C;
188+
LastSwiftMigration = 0930;
188189
ProvisioningStyle = Automatic;
189190
};
190191
};
@@ -270,15 +271,23 @@
270271
CLANG_CXX_LIBRARY = "libc++";
271272
CLANG_ENABLE_MODULES = YES;
272273
CLANG_ENABLE_OBJC_ARC = YES;
274+
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
273275
CLANG_WARN_BOOL_CONVERSION = YES;
276+
CLANG_WARN_COMMA = YES;
274277
CLANG_WARN_CONSTANT_CONVERSION = YES;
278+
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
275279
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
276280
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
277281
CLANG_WARN_EMPTY_BODY = YES;
278282
CLANG_WARN_ENUM_CONVERSION = YES;
279283
CLANG_WARN_INFINITE_RECURSION = YES;
280284
CLANG_WARN_INT_CONVERSION = YES;
285+
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
286+
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
287+
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
281288
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
289+
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
290+
CLANG_WARN_STRICT_PROTOTYPES = YES;
282291
CLANG_WARN_SUSPICIOUS_MOVE = YES;
283292
CLANG_WARN_UNREACHABLE_CODE = YES;
284293
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -323,15 +332,23 @@
323332
CLANG_CXX_LIBRARY = "libc++";
324333
CLANG_ENABLE_MODULES = YES;
325334
CLANG_ENABLE_OBJC_ARC = YES;
335+
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
326336
CLANG_WARN_BOOL_CONVERSION = YES;
337+
CLANG_WARN_COMMA = YES;
327338
CLANG_WARN_CONSTANT_CONVERSION = YES;
339+
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
328340
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
329341
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
330342
CLANG_WARN_EMPTY_BODY = YES;
331343
CLANG_WARN_ENUM_CONVERSION = YES;
332344
CLANG_WARN_INFINITE_RECURSION = YES;
333345
CLANG_WARN_INT_CONVERSION = YES;
346+
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
347+
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
348+
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
334349
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
350+
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
351+
CLANG_WARN_STRICT_PROTOTYPES = YES;
335352
CLANG_WARN_SUSPICIOUS_MOVE = YES;
336353
CLANG_WARN_UNREACHABLE_CODE = YES;
337354
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -377,7 +394,8 @@
377394
PRODUCT_NAME = "$(TARGET_NAME)";
378395
SKIP_INSTALL = YES;
379396
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
380-
SWIFT_VERSION = 3.0;
397+
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
398+
SWIFT_VERSION = 4.0;
381399
};
382400
name = Debug;
383401
};
@@ -397,7 +415,8 @@
397415
PRODUCT_BUNDLE_IDENTIFIER = com.mathewsanders.Mustard;
398416
PRODUCT_NAME = "$(TARGET_NAME)";
399417
SKIP_INSTALL = YES;
400-
SWIFT_VERSION = 3.0;
418+
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
419+
SWIFT_VERSION = 4.0;
401420
};
402421
name = Release;
403422
};
@@ -410,7 +429,8 @@
410429
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
411430
PRODUCT_BUNDLE_IDENTIFIER = com.mathewsanders.MustardTests;
412431
PRODUCT_NAME = "$(TARGET_NAME)";
413-
SWIFT_VERSION = 3.0;
432+
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
433+
SWIFT_VERSION = 4.0;
414434
};
415435
name = Debug;
416436
};
@@ -423,7 +443,8 @@
423443
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
424444
PRODUCT_BUNDLE_IDENTIFIER = com.mathewsanders.MustardTests;
425445
PRODUCT_NAME = "$(TARGET_NAME)";
426-
SWIFT_VERSION = 3.0;
446+
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
447+
SWIFT_VERSION = 4.0;
427448
};
428449
name = Release;
429450
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>

Mustard.xcodeproj/xcshareddata/xcschemes/Mustard.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "0820"
3+
LastUpgradeVersion = "0930"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"

README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ Mustard is a Swift library for tokenizing strings when splitting by whitespace d
66

77
## Quick start using character sets
88

9-
Foundation includes the `String` method [`components(separatedBy:)`](https://developer.apple.com/reference/swift/string/1690777-components) that allows us to get substrings divided up by certain characters:
9+
Foundation includes the `String` method [`components(separatedBy:)`](https://developer.apple.com/documentation/foundation/nsstring/1413214-components) that allows us to get substrings divided up by certain characters:
1010

1111
````Swift
1212
let sentence = "hello 2017 year"
13-
let words = sentence.components(separatedBy: .whitespace)
13+
let words = sentence.components(separatedBy: .whitespaces)
1414
// words.count -> 3
1515
// words = ["hello", "2017", "year"]
1616
````
@@ -53,7 +53,7 @@ let tokens = "123Hello world&^45.67".tokens(matchedWith: .decimalDigits, .letter
5353
Mustard can do more than match from character sets. You can create your own tokenizers with more
5454
sophisticated matching behavior by implementing the `TokenizerType` and `TokenType` protocols.
5555

56-
Here's an example of using `DateTokenizer` ([see example for implementation](Documentation/Template tokenizer.md)) that finds substrings that match a `MM/dd/yy` format.
56+
Here's an example of using `DateTokenizer` ([see example for implementation](Documentation/Template%20tokenizer.md)) that finds substrings that match a `MM/dd/yy` format.
5757

5858
`DateTokenizer` returns tokens with the type `DateToken`. Along with the substring text and range, `DateToken` includes a `Date` object corresponding to the date in the substring:
5959

@@ -78,14 +78,14 @@ let tokens = text.tokens(matchedWith: DateTokenizer())
7878

7979
## Documentation & Examples
8080

81-
- [Greedy tokens and tokenizer order](Documentation/Greedy tokens and tokenizer order.md)
82-
- [Token types and AnyToken](Documentation/Token types and AnyToken.md)
83-
- [TokenizerType: implementing your own tokenizer](Documentation/TokenizerType protocol.md)
84-
- [EmojiTokenizer: matching emoji substrings](Documentation/Matching emoji.md)
85-
- [LiteralTokenizer: matching specific substrings](/Documentation/Literal tokenizer.md)
86-
- [DateTokenizer: tokenizer based on template match](Documentation/Template tokenizer.md)
87-
- [Alternatives to using Mustard](/Documentation/Alternatives to using Mustard.md)
88-
- [Performance comparisons](/Documentation/Performance Comparisons.md)
81+
- [Greedy tokens and tokenizer order](Documentation/Greedy%20tokens%20and%20tokenizer%20order.md)
82+
- [Token types and AnyToken](Documentation/Token%20types%20and%20AnyToken.md)
83+
- [TokenizerType: implementing your own tokenizer](Documentation/TokenizerType%20protocol.md)
84+
- [EmojiTokenizer: matching emoji substrings](Documentation/Matching%20emoji.md)
85+
- [LiteralTokenizer: matching specific substrings](Documentation/Literal%20tokenizer.md)
86+
- [DateTokenizer: tokenizer based on template match](Documentation/Template%20tokenizer.md)
87+
- [Alternatives to using Mustard](Documentation/Alternatives%20to%20using%20Mustard.md)
88+
- [Performance comparisons](Documentation/Performance%20Comparisons.md)
8989

9090
## Roadmap
9191
- [x] Include detailed examples and documentation
@@ -97,7 +97,7 @@ let tokens = text.tokens(matchedWith: DateTokenizer())
9797

9898
## Requirements
9999

100-
- Swift 3.0
100+
- Swift 4.1
101101

102102
## Author
103103

Sources/Mustard.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ public extension String {
257257
/// opportunity to match a substring.
258258
///
259259
/// Returns: An array of `Token` where each token is the type `Tokenizer.Token`.
260-
func tokens<Tokenizer, Token>(matchedWith tokenizers: Tokenizer...) -> [Token] where Tokenizer: TokenizerType, Token: TokenType, Tokenizer.Token == Token {
260+
func tokens<Tokenizer, Token>(matchedWith tokenizers: Tokenizer...) -> [Token] where Tokenizer: TokenizerType, Tokenizer.Token == Token {
261261

262262
return _tokens(from: tokenizers.map({ $0.anyTokenizer })) as! [Token]
263263
}
@@ -297,7 +297,7 @@ public extension String {
297297
advanceTokenStart: while tokenStartIndex < text.unicodeScalars.endIndex {
298298

299299
// prepare a backlog of tokens that can start with the current scalar
300-
let possibleTokenizers = tokenizers.flatMap({ tokenizer -> AnyTokenizer? in
300+
let possibleTokenizers = tokenizers.compactMap({ tokenizer -> AnyTokenizer? in
301301
tokenizer.prepareForReuse()
302302
return tokenizer.tokenizerStartingWith(text.unicodeScalars[tokenStartIndex])
303303
})
@@ -329,7 +329,7 @@ public extension String {
329329
// - advance tokenStartIndex to the currentIndex; and
330330
// - continue looking for tokens at new startIndex
331331

332-
tokens.append(tokenizer.makeToken(text: text[start..<next], range: start..<next))
332+
tokens.append(tokenizer.makeToken(text: String(text[start..<next]), range: start..<next))
333333

334334
tokenStartIndex = currentIndex
335335
continue advanceTokenStart
@@ -363,19 +363,19 @@ public extension String {
363363

364364
// MARK: - Optimizations for single tokenizer
365365

366-
func tokens<Tokenizer, Token>(matchedWith tokenizer: Tokenizer, advanceWhenCompleteTokenIsInvalid: Bool) -> [Token] where Tokenizer: TokenizerType, Token: TokenType, Tokenizer.Token == Token {
366+
func tokens<Tokenizer, Token>(matchedWith tokenizer: Tokenizer, advanceWhenCompleteTokenIsInvalid: Bool) -> [Token] where Tokenizer: TokenizerType, Tokenizer.Token == Token {
367367
return _tokens(from: tokenizer, advanceWhenCompleteTokenIsInvalid)
368368
}
369369

370-
func tokens<Tokenizer, Token>(matchedWith tokenizer: Tokenizer) -> [Token] where Tokenizer: TokenizerType, Token: TokenType, Tokenizer.Token == Token {
370+
func tokens<Tokenizer, Token>(matchedWith tokenizer: Tokenizer) -> [Token] where Tokenizer: TokenizerType, Tokenizer.Token == Token {
371371
return _tokens(from: tokenizer)
372372
}
373373

374374
public func components<Tokenizer>(matchedWith tokenizer: Tokenizer) -> [String] where Tokenizer: TokenizerType {
375375
return _tokens(from: tokenizer).map({ $0.text })
376376
}
377377

378-
internal func _tokens<Tokenizer, Token>(from singleTokenizer: Tokenizer, _ advanceWhenCompleteTokenIsInvalid: Bool = false) -> [Token] where Tokenizer: TokenizerType, Token: TokenType, Tokenizer.Token == Token {
378+
internal func _tokens<Tokenizer, Token>(from singleTokenizer: Tokenizer, _ advanceWhenCompleteTokenIsInvalid: Bool = false) -> [Token] where Tokenizer: TokenizerType, Tokenizer.Token == Token {
379379

380380
let text = self
381381
var tokens: [Token] = []
@@ -415,7 +415,7 @@ public extension String {
415415
// - advance tokenStartIndex to the currentIndex; and
416416
// - continue looking for tokens at new startIndex
417417

418-
tokens.append(tokenizer.makeToken(text: text[start..<next], range: start..<next) as! Token)
418+
tokens.append(tokenizer.makeToken(text: String(text[start..<next]), range: start..<next) as! Token)
419419

420420
tokenStartIndex = currentIndex
421421
continue advanceTokenStart

Tests/PerformanceTests.swift

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ class PerformanceTests: XCTestCase {
142142
let matches = formatter.matches(in: text, options: [], range: text.nsrange)
143143

144144
return matches.map { match in
145-
text.substring(with: match.rangeAt(0))!
145+
String(text[Range(match.range, in: text)!])
146146
}
147147
}
148148

@@ -213,7 +213,7 @@ class PerformanceTests: XCTestCase {
213213
let matches = formatter.matches(in: text, options: [], range: text.nsrange)
214214

215215
return matches.map { match in
216-
text.substring(with: match.rangeAt(0))!
216+
String(text[Range(match.range, in: text)!])
217217
}
218218
}
219219

@@ -240,7 +240,7 @@ class PerformanceTests: XCTestCase {
240240
let matches = formatter.matches(in: text, options: [], range: text.nsrange)
241241

242242
return matches.map { match in
243-
text.substring(with: match.rangeAt(0))!
243+
String(text[Range(match.range, in: text)!])
244244
}
245245
}
246246

@@ -367,18 +367,17 @@ final class DatePatternTokenizer: TokenizerType, DefaultTokenizerType {
367367
// Scanner extensions
368368
extension Scanner {
369369
func scanCharacters(from set: CharacterSet) -> String? {
370-
var value: NSString? = ""
371-
if scanCharacters(from:set, into: &value),
372-
let value = value as? String {
370+
var valueNS: NSString? = ""
371+
if scanCharacters(from:set, into: &valueNS),
372+
let value = valueNS as String? {
373373
return value
374374
}
375375
return nil
376376
}
377377

378378
func scanUpToCharacters(from set: CharacterSet) -> String? {
379-
var value: NSString? = ""
380-
if scanUpToCharacters(from: set, into: &value),
381-
let value = value as? String {
379+
var valueNS: NSString? = ""
380+
if scanUpToCharacters(from: set, into: &valueNS), let value = valueNS as String? {
382381
return value
383382
}
384383
return nil
@@ -407,7 +406,7 @@ extension String {
407406
var nsrange: NSRange {
408407
return NSRange(location: 0, length: utf16.count)
409408
}
410-
409+
/*
411410
/// Returns a substring with the given `NSRange`,
412411
/// or `nil` if the range can't be converted.
413412
func substring(with nsrange: NSRange) -> String? {
@@ -417,6 +416,8 @@ extension String {
417416
let end = UTF16Index(range.upperBound)
418417
return String(utf16[start..<end])
419418
}
419+
*/
420+
/*
420421

421422
/// Returns a range equivalent to the given `NSRange`,
422423
/// or `nil` if the range can't be converted.
@@ -431,4 +432,5 @@ extension String {
431432

432433
return start..<end
433434
}
435+
*/
434436
}

0 commit comments

Comments
 (0)