Help us understand the problem. What is going on with this article?

Xcode の FileMerge.app で Swift のシンタクスハイライトを復活させる

はじめに

macOS の開発ツールである Xcode には開発に役立つツールが色々と入っていて、その中に diff やマージ作業を GUI で行う FileMerge.app というツールがある。「なんちゃら code を立ち上げるまでもないなぁ」というときに、opendiff file1 file2 でターミナルからサクッと立ち上げられるので、個人的には重宝している。左右のペインで2つのファイルを見比べることができるのはもちろん、行単位だけでなく文字単位で差分をハイライトしてくれるので、差分が把握しやすい。

ところが、いつの頃からか(Xcode 9 ぐらいではちゃんと動いていたと思う)、Swift ソースコードを指定して opendiff を起動すると、ターミナルに大量のエラーメッセージが吐き出されるようになり、シンタクスハイライトや関数や変数の宣言の選択ができなくなってしまった(とりあえず、標準エラー出力を /dev/null にリダイレクトする alias をして使っているが)。

Xcode のベータを含む新しいバージョンが出るたびに、Feedback Assistant で報告しているし、他の人も Apple Developer Forums で報告しているのだが、一向に直してくれる気配がない。原因はなんとなく分かっていたので、直してみることにした。

環境

  • macOS 10.14.6 (18G3020) + Xcode 11.3.1 (11C505)
  • macOS 10.15.4 (19E266) + Xcode 11.4 (11E146)

原因

opendiff で吐き出されるエラーメッセージは以下のような感じ。

$ opendiff file1.swift file2.swift
2020-02-11 18:24:52.980 FileMerge[59271:5815923] Couldn't load language spec for '<DVTSourceCodeLanguage:0x7fd1912b2340:'Xcode.SourceCodeLanguage.Swift'>'
...
(同じエラーメッセージが延々と吐き出される)
...

Swift の language spec が読み込めないと怒られている。Objective C などでは怒られることはない。試しに、Objective C の language spec とやらを探してみる。こういう場合、Rust 製の fd という高速版 find コマンドが便利。

$ cd /Applications/Xcode.app/Contents
$ fd lang | grep -i spec | grep -i objective | grep -vi c++
SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/ObjectiveC.xclangspec
SharedFrameworks/SourceModel.framework/Versions/A/Resources/LanguageSpecifications/ObjectiveC.xclangspec
Developer/Platforms/WatchSimulator.platform/Developer/Library/PrivateFrameworks/DVTFoundation.framework/ObjectiveC.xclangspec
Developer/Platforms/AppleTVSimulator.platform/Developer/Library/PrivateFrameworks/DVTFoundation.framework/ObjectiveC.xclangspec
Developer/Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/DVTFoundation.framework/ObjectiveC.xclangspec
Developer/Platforms/MacOSX.platform/Developer/iOSSupport/Library/PrivateFrameworks/DVTFoundation.framework/Versions/A/Resources/ObjectiveC.xclangspec

.xclangspec という拡張子を持つファイルが language spec らしいので、Swift のものがあるかどうかを探してみる。

$ fd -e xclangspec | grep -i swift
SharedFrameworks/SourceModel.framework/Versions/A/Resources/LanguageSpecifications/Swift.xclangspec
SharedFrameworks/SourceModel.framework/Versions/A/Resources/LanguageSpecifications/SwiftDocumentationMarkup.xclangspec

Swift の language spec は存在するようだが、Objective C の場合と比べてみると、DVTFoundation.framework に Swift の language spec が存在しないのが原因のようだ。

適当に直してみる

SharedFrameworks/SourceModel.framework/Versions/A/Resources/LanguageSpecifications/Swift.xclangspec を SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/ にコピーしてみる。そうすると...

$ opendiff file1.swift file2.swift
2020-02-11 19:08:56.115 FileMerge[59516:5884912] [MT] DVTSourceScanner: Couldn't load language spec for 'xcode.lang.comment.recursive' (from '')

エラーが1つに減った。DVTFoundation.framework の下にある他の言語の language spec ファイルをみても、xcode.lang.comment.recursive という記述はないので、コピーしてきた Swift.xclangspec 中の xcode.lang.comment.recursive という記述がある行を // でコメントアウトする。

$ diff -U0 Swift.xclangspec,bak Swift.xclangspec
--- Swift.xclangspec,bak    2020-02-11 18:53:48.000000000 +0900
+++ Swift.xclangspec    2020-02-11 19:09:56.000000000 +0900
@@ -196 +196 @@
-                //"xcode.lang.comment.recursive",
+                "xcode.lang.comment.recursive",
@@ -218 +218 @@
-                //"xcode.lang.comment.recursive",
+                "xcode.lang.comment.recursive",
$ opendiff file1.swift file2.swift
$

とりあえずエラーは出なくなったし、シンタクスハイライトもできているようだ。

おわりに

関数や変数の宣言などが正しく抽出できない場合があるようだし、そもそも、Xcode.app パッケージの中身を直接いじっているので、あくまでも、自己責任で。

それにしても、Apple さん、このぐらい、さっさと直してくれないかなぁ...

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした