目次

キーワード

概要

2010年代に入って、C# コンパイラー開発チームは、C# のコンパイラーを再設計・再実装していました。 (プロジェクトとしては C# 5.0 の実装と並行して動いていたようなので少なくとも2010年以前からある。)

以下のような作りで再実装されています。

  • 最初から Visual Studio などの IDE との連携を意識した作り

    • 最大の恩恵を受けるのは .NET チーム自身ですが、結果として、Visual Studio の高機能化が促進され、.NET 開発者全体への恩恵が期待できます。

    • API がオープンなので、第三者による Visual Studio プラグイン開発も容易になります。

  • C# 実装

    • これは単純に実装難易度を下げるためと思われます。

    • 副次的に、かかるコストの割には効果が薄いということでこれまで実装されてこなかったような、ちょっとした便利機能が実装されやすくなります。

この新しいコンパイラーは、開発コードネーム「Roslyn」(アメリカ ワシントン州の地名が由来)として開発され、 最終的なプロダクト名は「.NET Compiler Platform となりました。 IDE との連携や第三者による IDE 拡張まで見越したものなので、単なるコンパイラーではなく、「プラットフォーム」という呼称が付いています。 (ただ、今でも俗称としてはコードネームそのままな「Roslyn」の方がよく使われます。)

現在は、GitHub 上でオープンソース開発されています(dotnet/roslyn)。

ちなみに、Visual Basic も同様です(.NET Compiler Platform には VB で実装しなおされた新しい VB コンパイラーも含まれます)。

背景: 2つのコンパイラー

Roslyn 以前の C#、あるいは、他のプログラミング言語でもよくある話なんですが、 実は、コンパイラーは2つ(以上)あって、それぞれ別々に保守されていたりします。

1つはソースコードをILやバイトコードに変換するためのもので、 もう1つは統合開発環境(IDE: Integrated Development Environment)がソースコード解析などに使うものです。 (2つ「以上」というのは、下手するとIDEの数だけ別のソースコード解析があります。)

後者は最終成果物であるILやバイトコードを生成しないので、正確に言うとコンパイラー(compiler: 翻訳者)ではないんですが(パーサー(parser: 文法を説明するもの)というのが正しい)、 何にしても、2つ別系統のものを別保守していたりします。 正しく動作させるために、2重のコストがかかっています。 当然、「2つのコンパイラー」の間でバージョン不一致が起きたりもします。

例えばこれは Java の話なんですが、「JDK 8のプレビューがリリースされたけども、Eclipseのコンパイラーが8未対応だからまだ(最近まで)Java 8は使えない」なんていう不思議な話があったりしました。 要するに、(本来の、バイトコードを生成する)Javaコンパイラー的には問題ないコードを、Eclipseはエラーだと認識して警告を発していました。 もちろん、Java 8 が正式リリースになる頃までには Eclipse 側も完全対応しましたが、タイムラグがあったわけです。

これまでの Visual Studio でこの手の問題が少なかったのは、単純に「2重のコスト」をきっちり支払っていたというだけです。 C# 利用者の負担は低い反面、スピード感には欠けます(新仕様が固まり、IDE まで含めて対応できる頃まで新バージョンのコンパイラーが公開されていない)。

この問題の解消のためには、最初から IDE との連携を見越した作りのコンパイラーが必要になります。 これが、.NET Compiler Platform が作られるに至った動機です。 ちなみに、.NET 以外でも、例えば Clang なんかは最初から IDE との連携を考えた設計をしたそうです。

「もう1つのコンパイラー」の仕事

(書き掛け)

要件

  • ソースコードのどこからどこまで(何行何列目)が何かという情報がとれる

  • 文脈に応じてソースコードを生成したり、書き替えたりできる

  • リアルタイム処理を必要とするので、パフォーマンスも求められる

パフォーマンスに関して補足

使い方

ほとんどの C# 開発者は何も意識することなく コンパイラーはこれまでとの互換性重視で作られてるし、 コンパイラーのコマンドライン オプションとかすら旧コンパイラーと全く一緒。

意識するとするなら、Visual Studio 拡張作る人。 誰でもコード解析を作れる

API の概要

割と誰でもコード解析が書けるということは、以下のようなものを作ることもできます。

  • 組織内専用コード解析

  • ライブラリ専用コード解析

組織内専用コード解析

例えば、大手企業などでは「社内標準」と称してコーディングに関するルールを定めていたりします。ただ、ルールを定めるのは簡単ですが、組織内のみなに守ってもらうのは容易くありません。ルールに関するドキュメントを書いて、読んで、守れているかチェックして…という一連の流れは誰にとってもしんどい作業です。

これに対して、組織用にコード解析を自作することで、何が悪くて正しくはどう書いてほしいのか、警告とその修正を機械的に行えます。

組織用のコード解析は、

  • NuGetパッケージ化して、ソリューション単位、プロジェクト単位で参照

  • Visual Studio拡張(vsix)化して、個人の全プロジェクトで参照

などの参照方法がとれます。ルールの適用範囲に応じて選べます。

ライブラリ専用コード解析

特定のライブラリを使う時にだけ必要になるコード解析もあります。

例えば、JSON読み書き用のライブラリを使う際、文字列中にJSONを埋め込んで使いたかったとして、その文字列中のJSONがJSON規格的に正しいかどうかのチェックがしたかったりします。また、正規表現での文字列検索がしたいときには、その正規表現が正しいかどうかチェックしたいです。これも、コード解析で実現できます。

一方で、このようなライブラリを使わない時には、その「専用コード解析」は無用の長物というか、むしろあると邪魔でしかないはずです。

先ほど、コード解析はNuGetパッケージ化できると説明しましたが、これには、ライブラリとコード解析の同梱もできます。JSON読み書きライブラリにJSONコード解析を同梱したり、正規表現ライブラリに正規表現コード解析を同梱したりできます。

このような特定用途向けのコード解析を、必要な分だけ作成・参照できるようにすることが、.NET Compiler Platformのゴールの一つです。

オープンな開発

プログラミング言語の開発は相当保守的にやるべきものなので、新機能の提案なんかに対する応答は鈍いけども 一応オープン ディスカッション

将来

.NET Compiler Platform のゴールの一端には掲げられているものの、 Scripting API、 DSL

更新履歴

ブログ