LoginSignup
43
35

More than 3 years have passed since last update.

SourceKitについての話

Last updated at Posted at 2015-12-13

Swift その2の14日目を担当させていただく@ushisantoasobuと申します。よろしくお願いします

概要

今日のテーマはSourceKitになります。
先月SourceKitの機能を利用できるSourceKittenというライブラリについてLTをしてきました

このアドベントカレンダーでは、それを文章としてまとめあげたものにすればまあいいだろうと高を括っていましたが、Swiftのオープンソース化に伴いSourceKit自体のソースも読めるようになったので、そこらへんについてもほんのちょっと触れるようにはしたいと思います

SourceKitとは

あの憎っくき?

sourcekit_terminated.jpg

Swiftが世に出はじめたころからXcodeでSwiftを書いてきた人で、このクラッシュモーダルに遭遇したことはないという人はおそらくいないと思います。
意気揚々とSwiftを書いていると、突然このようなモーダルが表示されてXcodeが動かなくなるという・・・。クラッシュメッセージが、

SourceKitService Terminated

ということから、当時「SourceKitのせいでXcodeが動かなくなった、SourceKitさん頼むよー」といった内容のツイートが多く散見されましたが、自分もあの憎っくきSourceKitめみたいな認識が冗談半分にありました

Xcodeのサポートツール

SourceKitとは一言で言うと、Swiftのコードをパース・解析して、その結果をもとに開発者をサポートしてくれるツールになります。
Xcodeの6.x以降、実はSourceKitは別プロセスとしてXcodeとともに起動していて(正確にはSwiftのファイルをロードしたとき)、XPC経由で処理のやりとりをしています

  • シンタックスハイライト
  • オートコンプリート(補完)
  • 定義元ジャンプ
  • コードフォーマット

など、当たり前のように提供されているIDEの機能は、Xcode 6.x以降でSwiftを書くときにはSourceKitによるものということですね(Xcodeの6.x以前(あくまでLLVM/Clang以降)については、ここらへんがよくわかっていないのですが、コンパイラであるClang(LibClang?)がやっていくれていたという認識です)

プロセスが起動していることを確認する

Xcode(6.x以降)を起動して.swfitのファイルを開くと、以下のようなコマンドでSourceKitServiceが起動していることが確認できます。

$ ps aux | grep sourcekit
ushisantoasobu  70314   0.0  0.0  2423356    208 s014  R+    6:17PM   0:00.00 grep sourcekit
ushisantoasobu  70311   0.0  0.1  2514388   4764   ??  Ss    6:17PM   0:00.21 /Applications/Xcode 7.0.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/sourcekitd.framework/Versions/A/XPCServices/SourceKitService.xpc/Contents/MacOS/SourceKitService

ログを出力してみる

Xcode・SourceKit間の処理のやりとりをログ出力することができます。以下のようにXcodeを起動してみてください

export SOURCEKIT_LOGGING=3 && /Applications/Xcode\ 7.0.1.app/Contents/MacOS/Xcode

.swiftのファイルをいろいろいじると(ファイルを開く、カーソルをコードの上に合わせる、だけでも)ログが出力されると思います

sourcekit: [2:sourcekitd_send_request_sync-before:1299:666.2319] {
  key.request: source.request.editor.formattext,
  key.name: "/Users/ushisantoasobu/Documents/Twitilized/Twitilized/models/Setting.swift",
  key.line: 13,
  key.length: 1,
  key.sourcetext: "",
  key.editor.format.options: {
    key.editor.format.indentwidth: 4,
    key.editor.format.tabwidth: 4,
    key.editor.format.usetabs: 0
  }
}
...

key.requestをみていくと、各処理でどのようなことがやりとりされているのかがわかると思います(source.request.indexsourcesource.request.cursorinfosource.request.editor.replacetextなどなど)

ソースが読めるようになった

先述したように、Swiftがオープンソース化されてSourceKit自体のソースも読めるようになりました

SourceKittenとは

RealmJP Simardさんという方がつくったもので、SourceKitの機能を利用することができるライブラリになります。
SourceKitはこれまで(オープンソース化以前)は完全にドキュメントも存在しない非公開のAPIだったのですが、先述のログ出力の結果から解析してつくったもののようです。こちらに詳しく説明があります。

コマンドラインツールを使ってみる

SourceKittenはコマンドラインツールとしても提供されているので、少し試してみましょう

$ brew install sourcekitten

でインストールできます。helpを叩いてみましょう。提供されているコマンドがわかります

$ sourcekitten help
Available commands:

   complete    Generate code completion options.
   doc         Print Swift docs as JSON or Objective-C docs as XML
   help        Display general or command-specific help
   structure   Print Swift structure information as JSON
   syntax      Print Swift syntax information as JSON
   version     Display the current version of SourceKitten

次にsyntaxコマンドを打ってみましょう。以下のようにHoge.swiftファイルを指定します

$ sourcekitten syntax --file ./Hoge.swift

以下のような結果が表示されます(長いので後半は省略)

[
  {
    "offset" : 0,
    "length" : 3,
    "type" : "source.lang.swift.syntaxtype.comment"
  },
  {
    "offset" : 3,
    "length" : 26,
    "type" : "source.lang.swift.syntaxtype.comment"
  },
  {
    "offset" : 29,
    "length" : 15,
    "type" : "source.lang.swift.syntaxtype.comment"
  },
  {
    "offset" : 44,
    "length" : 3,
    "type" : "source.lang.swift.syntaxtype.comment"
  },
  {
    "offset" : 47,
    "length" : 43,
    "type" : "source.lang.swift.syntaxtype.comment"
  },
  {
    "offset" : 90,
    "length" : 61,
    "type" : "source.lang.swift.syntaxtype.comment"
  },
  {
    "offset" : 151,
    "length" : 3,
    "type" : "source.lang.swift.syntaxtype.comment"
  },
  {
    "offset" : 155,
    "length" : 6,
    "type" : "source.lang.swift.syntaxtype.keyword"
  },
  {
    "offset" : 162,
    "length" : 5,
    "type" : "source.lang.swift.syntaxtype.identifier"
  },
  {
    "offset" : 168,
    "length" : 6,
    "type" : "source.lang.swift.syntaxtype.keyword"
  },
  {
    "offset" : 175,
    "length" : 13,
    "type" : "source.lang.swift.syntaxtype.identifier"
  },
  {
    "offset" : 190,
    "length" : 16,
    "type" : "source.lang.swift.syntaxtype.comment"
  },
  {
    "offset" : 207,
    "length" : 4,
    "type" : "source.lang.swift.syntaxtype.keyword"
  },
  {
    "offset" : 212,
    "length" : 14,
    "type" : "source.lang.swift.syntaxtype.identifier"
  },
  {
    "offset" : 232,
    "length" : 7,
    "type" : "source.lang.swift.syntaxtype.typeidentifier"
  },

  (長いので省略...)

]

SourceKittenを利用してできること

さて、SourceKittenを利用してなにができるのでしょうか?
さきのsyntaxコマンドの出力結果をみて「それがどうしたの?」と思った方も多いはずです。
SourceKittenはあくまでSourceKitのラッパライブラリとしての責務を担うもので、それを利用したより実践的なライブラリを2つ紹介して終わりたいと思います(ともに、作者というか一番のコントリビュータは同じJP Simardさんです)

SwiftLint

SwiftのLinterです。使い方等は以前Qiitaも書きました(こちら)ので、良ければそちらをみてください

jazzy

SwiftDocのジェネレータです。Appleのリファレンスと同じようなドキュメントを生成してくれるようです

43
35
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
35