minimize

事業拡大のため、新しい仲間を募集しています。
→詳しくはこちら

Markerについて

Markerとは、Javaファイル内で警告があるときなどにエディタの左側に出るマークの事です。
ここでは既存のマーカーを流用する形のやり方を紹介します。非常に簡単です。

まずは plugin.xml に記述を追加します。

<extension
      id="SampleMarker"
      point="org.eclipse.core.resources.markers">
   <super
         type="org.eclipse.core.resources.problemmarker">
   </super>
   <persistent
         value="true">
   </persistent>
</extension>

こんな感じです。
problemmarker の記述をしておくと、マーカーの内容が Problems ビューに表示されます。
それと、org.eclipse.ui.editors を依存Plug-inに追加しておきます。

マーカー用のクラスを新規で作る必要は無いのですが
作っておいた方がわかりやすいのでここでは作ることにします。

public class SampleMarker {
    public static final String MARKER_ID = MyPlugin.PLUGIN_ID + ".SampleMarker";
}

他と同様、リテラル文字列は extension#id に合わせておきましょう。

マーカーはリソース(IResource)単位で付けることが出来ます。

void createMarker(IResource resource) {
    Map attributes = new HashMap();
    attributes.put(IMarker.PRIORITY, Integer.valueOf(IMarker.PRIORITY_NORMAL));
    attributes.put(IMarker.SEVERITY, Integer.valueOf(IMarker.SEVERITY_WARNING));
    attributes.put(IMarker.LINE_NUMBER, Integer.valueOf(2));
    attributes.put(IMarker.MESSAGE, "sample marker");
    MarkerUtilities.createMarker(resource, attributes, SampleMarker.MARKER_ID);
}

これで完了です。わかるように、マーカー作成(削除)に必要なのはIDだけなので
マーカークラスの作成は必須ではありません。

resource が示すファイルの2行目にマーカーが追加されます。
マーカーは勝手には消えないので、通常はまず対象リソースのマーカーを削除してから
必要なマーカーを追加するようにします。

マーカーを削除するには、

resource.deleteMarkers(SampleMarker.MARKER_ID, false, IResource.DEPTH_ZERO);

このようにします。
プロジェクト単位でまとめて消したい場合などは、

project.deleteMarkers(SampleMarker.MARKER_ID, false, IResource.DEPTH_INFINITE);

とやればOKです。

マーカーに任意のイメージを割り当てる

先程紹介した例は簡単ですが、もう少し高度な例も紹介します。
マーカーに任意のイメージを割り当てる方法です。

<extension
      id="SampleMarkerBase"
      point="org.eclipse.core.resources.markers">
   <super type="org.eclipse.core.resources.textmarker" />
   <persistent value="true" />
</extension>
<extension
      point="org.eclipse.ui.editors.markerAnnotationSpecification">
   <specification
         icon="icons/sample.gif"
         annotationType="sample.baseMarkerAnnotation">
   </specification>
</extension>
<extension
      point="org.eclipse.ui.editors.annotationTypes">
   <type
         markerType="myplugin.SampleMarkerBase"
         super="org.eclipse.ui.workbench.texteditor.warning"
         name="sample.baseMarkerAnnotation">
   </type>
</extension>

やや記述量が多いですが、それほど複雑ではありません。
まずは先程と同じように org.eclipse.core.resources.markers を定義します。
今回は、problemmarker ではなく textmarker を使いました。
こうすると、マーカーの内容は Problem ビューには表示されずエディタ内のみに表示されます。

続いて、2つのextensionを定義します。
sample.baseMarkerAnnotation というのは、任意で構いませんが
2つの要素内で値を合わせる必要があります。

やや注意しなければならないのが markerType です。
この値は、extension#id に合わせる必要があるのですが
myplugin. という prefix が付いています。
先程のマーカー定数定義を思い出して下さい。

public static final String MARKER_ID = MyPlugin.PLUGIN_ID + ".SampleMarker";

このように、マーカーIDは プラグインID + マーカーID という形で表されます。
プラグインID は MyPlugin.PLUGIN_ID として定数定義されています。
この値はプラグインを新規作成したときに作られますが
その後変更したい場合は注意が必要です。
具体的には、2箇所を変更します。

一箇所目は、プラグインクラスの定数定義です。

public class MyPlugin extends AbstractUIPlugin {
    public static final String PLUGIN_ID = "myplugin";
}

そしてもう一箇所は、META-INF/MANIFEST.MF ファイルです。

Bundle-SymbolicName: myplugin;singleton:=true

ファイルを直接編集しても良いですし
plugin.xml ファイルの Overview タブの ID を変更してもどちらでも構いません。

やや話が横道にそれましたが、以上でマーカーに任意のイメージを割り当てることが可能になりました。

複数のマーカーをグループ化する

マーカーには親子関係を作ることが出来ます。
実は先程の例でも、既にそれを使っています。
org.eclipse.core.resources.markers の定義を見てみましょう。

<extension
      id="SampleMarkerBase"
      point="org.eclipse.core.resources.markers">
   <super type="org.eclipse.core.resources.textmarker" />
   <persistent value="true" />
</extension>

このように、SampleMarkerBase は textmarker を親として定義されています。
ここでもう一つマーカーを作り、これを SampleMarkerBase の子としてみます。

<extension
      id="SampleMarkerExt"
      point="org.eclipse.core.resources.markers">
   <super type="myplugin.SampleMarkerBase" />
   <persistent value="true" />
</extension>

super の部分を変えただけです。
これで、SampleMarkerExt は SampleMarkerBase の子となりました。
super 要素は複数定義することも可能で、その場合複数の親子関係を作ることができます。

親子関係はどのように使うかというと、主にマーカーの取得・削除時です。
リソースからマーカーを削除する場合を考えます。

resource.deleteMarkers(SampleMarker.MARKER_ID, false, IResource.DEPTH_ZERO);

ここの第2パラメータに注目して下さい。
これは includeSubtypes として定義されていて、true にすると
「指定したマーカーIDおよびその子を全て削除する」という意味になります。
ですので…

resource.deleteMarkers(SampleMarker.BASE_ID, true, IResource.DEPTH_ZERO);

このようにすれば、リソースに含まれる BASE_ID のマーカーおよび
その子マーカーが全て削除されます。

ちなみに、第3パラメータは「リソースの再帰回数」を指定します。
resource がフォルダ(やプロジェクト)の場合、
IResource.DEPTH_ZERO を指定すると「そのフォルダのみ」が対象となります。
IResource.DEPTH_ONE を指定すると「フォルダおよびフォルダ直属の子リソース」が対象となり、
IResource.DEPTH_INFINITE を指定すると「フォルダおよびその全ての子リソース」が対象となります。