Blog

bevkjbvkbdkdxoeoziejdoiehz fiugebfuyegwik

Detecting Swift versions

Screenshot of Xcode Swift conversion

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.