IDE Eclipse 環境のプラグインを開発するときには、設計に関して考慮すべき事項がいくつかあり、それらを考慮することによって、以下のことが確実になります。
- ユーザー・インターフェース・スレッドがロックされないこと
- パフォーマンスに影響を与えることなく UI を修飾できること
- データがバックグラウンドで処理されること
このチュートリアルで取り上げるのは、Eclipse プラグインを設計する際の考慮事項を踏まえて、ワークスペースに保管されたリソース関連のデータを処理し、表示する方法です。具体的には、リソースに関する情報を保管および処理するために Eclipse が提供しているマーカー・インターフェースについて詳しく見て行きます。
リソースに対するデータ・マーカーを処理する際のベスト・プラクティスを説明するために、まず、データをマーキングする方法を示します。それに続き、ユーザー・インターフェース上でマーカーを表現する方法、そしてリソースの変更に応じてマーカーを更新する方法を説明します。このコンテキストで言うリソースとは、IResource インターフェースを実装するプロジェクト、ファイル、フォルダー、Java オブジェクト (パッケージ、クラス、ソースを含む) などの Eclipse オブジェクトです。
このチュートリアルの対象読者は、基本的なプラグインを作成することはできるものの、Eclipse リソースを扱う際のベスト・プラクティスは知らないため、それを学びたいという開発者です。
個々の拡張ポイントとインターフェースについては、Eclipse.org にドキュメントが揃っています。このチュートリアルは、これらの拡張ポイントとインターフェースを組み合わせて使用する際のベスト・プラクティスを選択する上で参考となります。このチュートリアルを読んで、既存の Eclipse 関数を利用して新しい機能を提供する方法を学んでください。
マーカーを使用する目的は、リソースを変更することなく、リソースに情報をリンクさせることです。マーカーが付けられた情報の一般的な例としては、ブレークポイント、ブックマーク、コンパイル・エラーが挙げられます。コンパイル・エラーを例にとると、コンパイル・ジョブが実行されるたびに、ソースがひと通り調べられ、エラーを強調表示するための新しいマーカーが作成されます。
このチュートリアルの最初のパートでは、独自のマーカーを作成します。その方法は、マーカー拡張ポイントを利用して、たった 1 行のコードを作成するだけのことです。
独自のマーカーは、IMarker 拡張ポイント org.eclipse.core.resources.markers
を継承することによって作成することができます。まずは、リスト 1 のコードを plugin.xml ファイルに追加してください。このコードは、これから com.ibm.mymarkers.mymarker という id を持つ My Marker という名前のマーカーを作成することを意味します。このマーカーのスーパータイプは、org.eclipse.core.resources.marker です。これは最も基本的なマーカー・タイプですが、これよりも多少具体的な関数を提供する他のスーパータイプを継承することもできます。他のスーパータイプとしては、以下のものを使用することができます。
- org.eclipse.core.resources.problemmarker
- org.eclipse.core.resources.textmarker
注: これらのスーパータイプは、必要に応じていくつでも使用することができます。
リスト 1. マーカーの拡張を定義するコード (plugin.xml より抜粋)
<extension point="org.eclipse.core.resources.markers" id="com.ibm.mymarkers.mymarker" name="My Marker"> <super type="org.eclipse.core.resources.marker"/> <persistent value="false"/> <attribute name="description"/> </extension> |
リスト 1 では persistent 要素と attribute
要素に注目してください。この 2 つが、mymarker
マーカーに対して指定するプロパティーです。persistent 要素は、マーカーをワークスペース内に保管するかどうかを指定します。もう一方の要素では、mymarker に
description という新しい属性を持たせています。
マーカーを新規に作成する場合には、対象とするリソースで createMarker メソッドを呼び出します。その際、新規マーカーの属性を設定することもできます。
マーカーを作成するには、リスト 2 に記載するメソッドを使用することもできます。このメソッドに唯一必要な入力は、マーカーにリンクする IResource だけです。マーカーを作成した後、マーカーの属性を設定することができます。
リスト 2. 新規マーカー・タイプを作成する Java コード
public static IMarker createMarker(IResource res)
throws CoreException {
IMarker marker = null;
//note: you use the id that is defined in your plugin.xml
marker = res.createMarker("com.ibm.mymarkers.mymarker");
marker.setAttribute("description," "this is one of my markers");
//note: you can also use attributes from your supertype
marker.setAttribute(IMarker.MESSAGE, "My Marker");
return marker;
}
|
IResource に関連付けられたマーカーを検索するには、リソースに対して問い合わせを行い、特定の id
を持つすべてのマーカーを取得することと、関連するリソースを検索するかどうかを指定することができます。マーカーを検索するためには、特定のリソースで findMarkers メソッドを呼び出します。メソッド呼び出しには、マーカー・タイプや検索の深さなどの引数を指定する必要があります。
リスト 3 のコードは、IResource.DEPTH_ZERO
引数を使って、該当するリソースと直接リンクするマーカーを検索します。
リスト 3. 新規マーカー・タイプを検索する Java コード
public static final String MARKER = "com.ibm.mymarkers.mymarker";
public static List<IMarker> findMarkers(IResource resource) {
try {
return Arrays.asList(resource.findMarkers(MARKER, true,
IResource.DEPTH_ZERO));
} catch (CoreException e) {
return new ArrayList<IMarker>();
}
}
|
リソースの深さを IResource.DEPTH_INFINITE に変更すると、そのリソースまたはその任意のサブリソースに関連するすべてのマーカーが返されます。例えば、パッケージを渡して、そのパッケージからリソースにリンクされたすべてのマーカーを取得することもできます。
パート 2: アノテーションを使用してマーカーを表示および更新する
アノテーションは、エディター内で特定のテキスト領域にマークを付けるために使用します。Eclipse では、エラー、警告、ビルド問題、タスク、ブレークポイントといった情報を表示するために、アノテーションが幅広く使用されます。アノテーションは、エディターのルーラー上とテキスト上に表示されます。図 1 に一例として、構文エラーを表示するアノテーションを示します。
図 1. アノテーションの例
アノテーションの一般的な実装は、ファイルを構文解析しながら、エラーや「ToDo」タグなどを見つけ出すとマークを生成します。この処理は、ビルド時に行われるのが通常です。他のアノテーション実装は、ブレークポイントなどの永続マーカーにリンクされます。ここでは、永続マーカーを使った例を取り上げます。
ユーザーはアノテーションの表示方法を、「General (一般)」 > 「Editors (エディター)」 > 「Text Editors (テキスト・エディター)」 > 「Annotations (アノテーション)」の順に選択すると表示される設定パネルでカスタマイズすることができます。つまり、ユーザーがアノテーションをカスタマイズできるようにするために追加で行わなければならない作業はありません。
図 2. アノテーション設定パネルのスクリーン・ショット
図 2 を拡大したものを見るには、ここをクリックしてください。
このチュートリアルのパート 1 で取り上げたマーカーは、単純にデフォルトのマーカー・タイプを継承しただけです。パート 2
では、テキスト・マーカー・タイプを継承して、テキストの位置をマーキングできるようにします。このタイプのマーカーは、charStart と charEnd という 2
つの重要な属性を定義します。また、このマーカーの場合には、セッションが終わっても次のセッションで維持されるように、persistent 要素の value 属性を
“true” に変更します。以上の内容を設定するには、マーカーをリスト 4 に定義されているように更新してください。
リスト 4. マーカーの拡張定義 (plugin.xml より抜粋)
<extension point="org.eclipse.core.resources.markers" id="com.ibm.mymarkers.mymarker" name="My Marker"> <super type="org.eclipse.core.resources.textmarker"/> <super type="org.eclipse.core.resources.marker"/> <persistent value="true"/> </extension> |
独自のアノテーションを作成するには、拡張ポイント org.eclipse.ui.editors.markerAnnotationSpecification を使用します (リスト 5 を参照)。以下のリストは、アノテーションのプロパティーとそのデフォルトの表示オプションを定義するコードです。
リスト 5. アノテーション拡張を定義するコード (plugin.xml より抜粋)
<extension point="org.eclipse.ui.editors.markerAnnotationSpecification" id="myannotationspecification" name="MyAnnotation"> <specification annotationType="com.ibm.example.myannotation" label="MyAnnotation" icon="icons/sample.gif" overviewRulerPreferenceKey="clruler" overviewRulerPreferenceValue="true" colorPreferenceKey="clcolor" colorPreferenceValue="255,255,0" textPreferenceKey="cltext" textPreferenceValue="true" verticalRulerPreferenceKey="clvertical" verticalRulerPreferenceValue="true" textStylePreferenceKey="clstyle" textStylePreferenceValue="BOX"> </specification> </extension> |
この XML のなかで、仕様にリンクするために使用するのは id 属性および annotationType 属性です。カスタマイズに使用できるその他の属性については、Eclipse.org
にドキュメントが用意されています (「参考文献」を参照)。
次のステップは、拡張ポイント org.eclipse.ui.editors.annotationTypes を使用して、既存のマーカーを新しいアノテーション仕様に関連付けることです。仕様に関連付けるには、仕様のアノテーション・タイプとマーカー定義の id を使用します。
リスト 6. アノテーション・タイプを定義するコード (plugin.xml より抜粋)
<extension point="org.eclipse.ui.editors.annotationTypes">
<type markerSeverity="0"
super="org.eclipse.ui.workbench.texteditor.info"
name="com.ibm.example.myannotation"
markerType="com.ibm.mymarkers.mymarker"/>
</extension>
|
この拡張ポイントについてのさらに詳しい情報を Eclipse.org から探すには「参考文献」を参照してください。
アノテーションを作成してエディターに追加するには、リスト 7 のコードを使用します。
リスト 7. エディターへの新規アノテーションの追加
public static void addAnnotation(IMarker marker, ITextSelection selection,
ITextEditor editor) {
//The DocumentProvider enables to get the document currently loaded in the editor
IDocumentProvider idp = editor.getDocumentProvider();
//This is the document we want to connect to. This is taken from
//the current editor input.
IDocument document = idp.getDocument(editor.getEditorInput());
//The IannotationModel enables to add/remove/change annotation to a Document
//loaded in an Editor
IAnnotationModel iamf = idp.getAnnotationModel(editor.getEditorInput());
//Note: The annotation type id specify that you want to create one of your
//annotations
SimpleMarkerAnnotation ma = new SimpleMarkerAnnotation(
“com.ibm.example.myannotation”,marker);
//Finally add the new annotation to the model
iamf.connect(document);
iamf.addAnnotation(ma,newPosition(selection.getOffset(),selection.getLength()));
iamf.disconnect(document);
}
|
アノテーション・モデルは、文書の編集時にアノテーションを移動させますが、アノテーションの移動に伴ってマーカーの属性を更新することはしません。アノテーションが移動した場合には、マーカーの
charStart 属性と charEnd 属性を更新しなければなりません。最後に紹介する拡張ポイントは、マーカー・アップデーターです。マーカー・アップデーターは、アノテーションの移動に伴ってマーカーを更新するために使用するクラスを定義します。
リスト 8. マーカー・アップデーターを定義するコード (plugin.xml より抜粋)
<extension point="org.eclipse.ui.editors.markerUpdaters">
<updater
id="com.ibm.example.MarkerUpdater"
class="com.ibm.example.mymarker.MarkerUpdater"
markerType="com.ibm.mymarkers.mymarker">
</updater>
</extension>:
|
アノテーションが移動されたときに実行するコードを提供するには、IMarkerUpdater インターフェースを使用します。リスト
9 に記載するクラスが、マーカー・アップデーターです。マーカー・アップデーターのコードで興味深いのは updateMarker メソッドで、上記では、このメソッドを使ってマーカーの charStart および charEnd 属性を更新しています。
リスト 9. マーカー・アップデーターのコード
public class MarkerUpdater implements IMarkerUpdater {
/*
*Returns the attributes for which this updater is responsible.
*If the result is null, the updater assumes responsibility for any attributes.
*/
@Override
public String[] getAttribute() {
return null;
}
@Override
public String getMarkerType() {
//returns the marker type that we are interested in updating
return "com.ibm.mymarkers.mymarker";
}
@Override
public boolean updateMarker(IMarker marker, IDocument doc, Position position) {
try {
int start = position.getOffset();
int end = position.getOffset() + position.getLength();
marker.setAttribute(IMarker.CHAR_START, start);
marker.setAttribute(IMarker.CHAR_END, end);
return true;
} catch (CoreException e) {
return false;
}
}
}
|
パート 3: マーキングした IResources をデコレーターによって識別する
Eclipse 内でワークベンチのオブジェクトに可視の情報を追加するには、デコレーターを使用します。一般にデコレーターが表示するのは、オブジェクト・タイプと、そのオブジェクトに現在関連付けられている重要なあらゆるプロパティーです。図 3 に、パッケージ・エクスプローラーでデコレーターがユーザーに対してどのように表示されるのかを示します。デコレーターは、それぞれの項目が Java ソース・ファイルなのかパッケージなのかを示すとともに、警告またはエラーが含まれるソースおよびパッケージを表すマーカー・アイコンを表示します。パッケージ・エクスプローラーでは、例えばファイルがリポジトリーと同期しているかどうかなどの、チームの詳細を追加するためにも、デコレーターが使用されます。
図 3. 記号のアイコンで修飾されたパッケージおよびソース
独自のデコレーターを追加する場合の最初のステップは、org.eclipse.ui.decorators 拡張ポイントを継承することです。これによって、新しいデコレーターを定義できるようにして、修飾するオブジェクトの種類を選択します。
デコレーターを定義する際には、以下のフィールドが重要です。
- class —
ILightweightLabelDecorator(lightweight が “true” に設定されているため) を実装するクラスの完全修飾名を指定する必要があります。 - enablement — デコレーターを適用する Eclipse オブジェクトのリストを含めます。
リスト 10. デコレーターを定義するコード (plugin.xml より抜粋)
<extension point="org.eclipse.ui.decorators"> <decorator id="com.ibm.example.filedecorator" label="MyMarker Decorator" state="true" class= "com.ibm.example.mymarker.FileDecorator" adaptable="true" lightweight="true"> <enablement> <objectClass name="org.eclipse.core.resources.IResource"/> </enablement> </decorator> </extension> |
Eclipse.org の、拡張ポイントに関する詳細なドキュメントについては、「参考文献」を参照してください。
注: lightweight と非 lightweight の違いに注意してください。API によると、非 lightweight デコレーターは今後の Eclipse では使用が廃止されることになっています。
独自のデコレーターの振る舞いを決定するには、FileDecorator
クラスを実装する必要があります。そしてこのクラスが、ILightweightLabelDecorator
を実装しなければなりません。このクラスに LabelProvider
を継承させるのは賢明な方法です。そうすれば、対象とするメソッド、すなわち decorate() だけをオーバーライドすることができます。
リスト 11 に、decorate() の基本的な実装を記載します。
リスト 11.
decorate() の基本実装
public void decorate(Object resource, IDecoration decoration) {
decoration.addOverlay(ImageDescriptor.createFromFile(FileDecorator.class,
"/icons/sample.gif"), IDecoration.TOP_RIGHT);
decoration.addPrefix("My Prefix ");
decoration.addSuffix(" My Suffix");
}
|
IDecoration オブジェクトを使用して、フォントや、テキストの色、背景色をカスタマイズすることもできます。
図 4. リスト 11 のIResources を修飾するコードによる結果を示すスクリーン・ショット
decorate() の最初の引数は、修飾対象とするリソースをフィルタリングするために使用することができます。リスト 12 に一例として、特定のマーカーが含まれるリソースだけを修飾する場合に使用するコードを記載します。
リスト 12. 特定のマーカーを持つリソースの修飾
public void decorate(Object resource, IDecoration decoration) {
if(resource instanceof IResource){
List<IMarker> markers = MyMarkerFactory.findMarkers((IResource) resource);
if (markers.size() > 0) {
decoration.addSuffix(" Marker !!");
}
}
}
|
これで、チュートリアルは完了です。この後に考えられる改善には、どのようなものがあるでしょうか。
例えば、以下のような高度な改善を加えることができます。
- マーカーに編集可能なプロパティーを追加する: これによって、ユーザーがマーカーの状態を変更できるようになります。
- マーカーの作成および削除を自動化する: バックグラウンド処理のジョブを使用して、マーカーを自動的に作成、更新、削除します。
- マーカー・ホバーをカスタマイズする: 高度なマーカー・ホバーを使用して、HTML やマルチメディア・コンテンツをサポートします。
このチュートリアルでは、Eclipse を使用して容易にマーカーを作成およびカスタマイズして、高度なリソース・マーキングを行いました。ぜひ、この単純ながらも強力なツールを使用して、皆さんが開発したプラグインを Eclipse IDE に完全に組み込んでください。ただし注意する点として、この機能を広範に実装しすぎると、ユーザーにとって目障りになる恐れがあります。また、「Eclipse User Interface Guidelines」(「参考文献」を参照) を考慮に入れて Eclipse のルック・アンド・フィールを維持するのは、開発者の責任です。
学ぶために
- Eclipse.org
によるマーカー拡張ポイントに関する資料
- Eclipse.org
によるリソース・マーカーに関する資料
- Eclipse.org
によるデコレーター拡張ポイントに関する資料
- Eclipse.org
によるマーカー・アノテーション仕様拡張ポイントに関する資料
- Eclipse.org
によるアノテーション・タイプ拡張ポイントに関する資料
- Eclipse User
Interface Guidelines
- developerWorks on Twitter: developerWorks
をフォローして最新ニュースを入手してください。
- developerWorks Open source ゾーン: 開発や IBM 製品でオープンソース技術を使用する際に役立つ広範なハウツー情報、ツール、およびプロジェクト更新を見つけてください。
- 興味深いイベント: 世界中で近日中に予定されている IBM オープンソース開発者を対象とした会議、見本市、ウェブ放送をチェックしてください。
- developerWorks podcasts: ソフトウェア開発者向けの興味深いインタビューとディスカッションを聞いてください。
- developerWorks オンデマンド・デモ: 無料のオンライン・デモで、IBM およびオープンソースの技術と製品機能を試してみてください。
製品や技術を入手するために
- Eclipse Marketplace
は、オープンソースと商用両方の Eclipse 関連のオファリングを見つけられる便利なポータルです。Indigo が含まれるパッケージをダウンロードして、Eclipse Marketplace クライアントにアクセスしてください。
議論するために
- developerWorks
コミュニティー: ここでは他の developerWorks
ユーザーとのつながりを持てる他、開発者が主導するブログ、フォーラム、グループ、ウィキを調べることができます。developerWorks コミュニティーで、現実世界のオープンソース・グループの構築を手伝ってください。

