Kengo's blog

Technical articles about original projects, JVM, Static Analysis and TypeScript.

FileDocumentProvider継承時の注意

前回発生した「メニューバーからファイルを開くとエラーになる」の原因を調べていました。結論としては、FileDocumentProviderを継承しただけではワークスペース外のファイルを扱えないようです。

DocumentProvider#createDocumentの実装がポイント

今回の実装ではFileDocumentProviderを継承したHSPDocumentProviderクラスをドキュメント・プロバイダとして使用しています。このドキュメント・プロバイダは、渡されたオブジェクトとエディタで編集するためのドキュメントを関連付ける役割を担っています。

Text editors use document providers to bridge the gap between their input elements and the documents they work on. A single document provider may be shared between multiple editors; the methods take the editors' input elements as a parameter.

Eclipse SDK(IDocumentProvider)

FileDocumentProviderの場合、関連付けはcreateDocumentメソッドで行っています。このメソッドの内部で呼び出されているsetDocumentContentメソッドはFileEditorInputクラスだけを受けつけ、他のクラスはスーパークラスに任せています。スーパークラスでも処理されなかった場合はオブジェクトとドキュメントの関連付けに失敗するため、エディタにファイルの内容を表示することができません。

さてパッケージ・エクスプローラからファイルを開いた場合、HSPDocumentProvider#setDocumentContentメソッドの引数にはFileEditorInputクラスが渡されます。このためFileDocumentProviderは問題なく処理を行うことができます。
しかしメニューバーからファイルを開いた場合は、IEditorInputインタフェースの実装クラスとしてFileStoreEditorInputクラスが渡されます。このクラスはFileEditorInputのサブクラスではないため、FileDocumentProviderクラスによって受け付けることができません。このためドキュメントの関連付けに失敗し、表示処理を続行できないようです。


以下のJavadocによればワークスペースにないファイルを別々に扱うこと自体は仕様らしいので、エディタまたはドキュメント・プロバイダによって対応する必要があるでしょう。

Implements an IEditorInput instance appropriate for IFileStore elements that represent files that are not part of the current workspace.

Eclipse SDK(FileStoreEditorInput)

解決のヒント

現時点でクリアな解決方法は見つかっていませんが、FileDocumentProviderがFileEditorInput用の実装である事を考えるとそのサブクラスにFileStoreEditorInput対応を実装するべきではないでしょう。
ドキュメント・プロバイダを独自に実装をする場合はクラスファイルのエディタClassFileEditorがひとつの参考になりそうです。入力をIClassFileEditorInputというインタフェースにまとめ、ワークスペース内のクラスファイルをInternalClassFileEditorInputクラス、それ以外をExternalClassFileEditorInputクラスとして表現しています。