S-JIS[2013-08-31/2013-09-03] 変更履歴

「Open Model Element」ダイアログ

Xtextの「Open Model Element」ダイアログのメモ。

 

概要

Xtextで生成されたエディターを使っていると、Ctrl+Shift+F3キーで「Open Model Element」ダイアログを開くことが出来る。
「Open Model Element」ダイアログには全DSLファイル内の名称一覧が表示され、その中の1つを選択することで定義場所へジャンプすることが出来る。
名称やルールクラス名で対象を絞り込むことも出来て、非常に便利。

参考: Eclipse Community Forumsの[Xtext 2.2] Question about Xtext's index


XtextEObjectSearchDialog

「Open Model Element」ダイアログはXtextEObjectSearchDialogクラスで実現されている。

XtextEObjectSearchDialogクラスではIXtextEObjectSearchを使って検索および検索条件による絞り込みを行う。


ダイアログを開くメニュー

「Open Model Element」ダイアログを開くメニューを作ることが出来る。

uiプロジェクト/plugin.xml:

   <extension
         point="org.eclipse.ui.menus">
      <menuContribution
            locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
         <toolbar
               id="jp.hishidama.xtext.dmdl_editor.toolbar">
            <command
                  commandId="org.eclipse.xtext.ui.shared.OpenXtextElementCommand"
                  icon="〜.gif"
                  tooltip="Xtextの機能を使用してモデルを検索します。">
            </command>
         </toolbar>
      </menuContribution>
   </extension>

IXtextEObjectSearch

IXtextEObjectSearchは、ワークスペース全体からEObjectを探すクラス(インターフェース)。[2013-09-03]
デフォルト実装はIXtextEObjectSearch.Defaultというクラス。

これをカスタマイズして自分のDSLのファイルだけを探すようにすることが出来る。

DMDLEObjectSearch.java:

import java.util.Collections;

import org.eclipse.emf.common.util.URI;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.resource.IResourceDescription;
import org.eclipse.xtext.ui.search.IXtextEObjectSearch;

import com.google.common.base.Function;
import com.google.common.collect.Iterables;

import jp.hishidama.xtext.dmdl_editor.ui.internal.DMDLActivator;
public class DMDLEObjectSearch extends IXtextEObjectSearch.Default {

	private String projectName;
	public DMDLEObjectSearch(String projectName) {
		this.projectName = projectName;

		Injector injector = DMDLActivator.getInstance().getInjector(DMDLActivator.JP_HISHIDAMA_XTEXT_DMDL_EDITOR_DMDL);
		injector.injectMembers(this);
	}
	@Override
	protected Iterable<IEObjectDescription> getSearchScope() {
		return Iterables.concat(Iterables.transform(
			getResourceDescriptions().getAllResourceDescriptions(),
			new Function<IResourceDescription, Iterable<IEObjectDescription>>() {
				public Iterable<IEObjectDescription> apply(IResourceDescription from) {
					URI uri = from.getURI();
					if (isTarget(uri)) {
						return from.getExportedObjects();
					}
					return Collections.emptyList();
				}
			}));
	}
	private boolean isTarget(URI uri) {
		if (uri.fileExtension().equals("dmdl")) {
			String[] seg = uri.segments();
			if (seg.length >= 2 && projectName.equals(seg[1])) { // プロジェクト名
				return true;
			}
		}
		return false;
	}
}

呼び出す側:

import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.resource.IEObjectDescription;
	public static ModelDefinition findModel(IProject project, String name) {
		DMDLEObjectSearch search = new DMDLEObjectSearch(project.getName());

		Iterable<IEObjectDescription> list = search.findMatches(name, ModelDefinition.class.getSimpleName());
		for (IEObjectDescription i : list) {
			ModelDefinition model = (ModelDefinition) i.getEObjectOrProxy();
			if (model.eIsProxy()) {
				Injector injector = DMDLActivator.getInstance().getInjector(DMDLActivator.JP_HISHIDAMA_XTEXT_DMDL_EDITOR_DMDL);
				ResourceSet resourceSet = injector.getInstance(ResourceSet.class);
				model = (ModelDefinition) EcoreUtil.resolve(model, resourceSet);
			}

			String modelName = model.getName();
/*
			if (modelName == null) {
				URI uri = EcoreUtil.getURI(model);
				Injector injector = DMDLActivator.getInstance().getInjector(DMDLActivator.JP_HISHIDAMA_XTEXT_DMDL_EDITOR_DMDL);
				ResourceSet resourceSet = injector.getInstance(ResourceSet.class);
				Resource resource = resourceSet.getResource(uri, true);
				model = (ModelDefinition) resource.getEObject(uri.fragment());
				if (model != null) {
					modelName = model.getName();
				}
			}
*/
			if (name.equals(modelName)) {
				return model;
			}
		}
		return null;
	}

DMDLのModelDefinitionという定義を探す例。

IXtextEObjectSearchのfindMatches()を呼び出すと検索を実行する。
第1引数は検索したい名前のパターン、第2引数はルール定義クラス名。
(数が多いと時間がかかるだろう。XtextEObjectSearchDialogではIteratorJobというジョブを使い、非同期で検索している)

取得されたIterableから、getEObjectOrProxy()でEObjectが取れる。
ただし、URIだけセットされていて中身が全部nullという状態(プロキシー?)のようなので、URIからEObjectを生成している。


Xtext目次へ戻る / Eclipseへ戻る / 技術メモへ戻る
メールの送信先:ひしだま