So we are all familiar with the "Convert to latest Swift syntax..." assistant Xcode provides. Yesterday, I wondered if that couldn't be leveraged to detect if a piece of Swift code is written for the version the current Xcode provides or if it is for an older version.
First, I ventured into the Xcode headers - the functionality in question is implemented by IDEKit:
$ find . -name 'IDESwift*'
./IDESwiftMigrationAssistantContext.h
./IDESwiftMigrationGeneratingPreviewAssistant.h
./IDESwiftMigrationOverviewAssistant.h
./IDESwiftMigrationReviewChangesAssistant.h
./IDESwiftMigrationReviewChangesFile.h
./IDESwiftMigrationTarget.h
./IDESwiftMigrationTargetChooserAssistant.h
./IDESwiftMigrationTargetChooserItem.h
./IDESwiftMigrationTargetChooserTargetItem.h
But it quickly turned out that this was only UI. After some more poking, I ended up discovering a new commandline tool in Xcode 6.3 called swift-update
.
$ xcrun swift-update
<unknown>:0: error: error opening '' for output: Error opening output file '': No such file or directory
Unfortunately, it was a bit unfriendly, like most of Apple's "private" CLI tools. In the end, its usage is quite similar to regular swift
, a successful invocation looks like this:
$ xcrun -sdk iphoneos swift-update -sdk /Applications/Xcode-6.3.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.3.sdk Stargate.swift -target arm64-apple-ios8.3 -o out.yaml
The output is some YAML that looks like this:
[
{
"file": "JaroWinkler.swift",
"offset": 80,
"remove": 13,
"text": "count",
},
]
So it is an array of locations in the given files that need to be changed to update to the latest Swift syntax. From there on, it was quite trivial to build a little Ruby library around this which set up the correct flags for swift-update
and provides its results in a convenient form.
The tool is called Grenouille and its basic usage looks like this:
$ grenouille Stargate.swift
1.2
More information can be found in the project's README.