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
「Open Model Element」ダイアログはXtextEObjectSearchDialogクラスで実現されている。
XtextEObjectSearchDialogクラスではIXtextEObjectSearchを使って検索および検索条件による絞り込みを行う。
「Open Model Element」ダイアログを開くメニューを作ることが出来る。
<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は、ワークスペース全体からEObjectを探すクラス(インターフェース)。[2013-09-03]
デフォルト実装はIXtextEObjectSearch.Default
というクラス。
これをカスタマイズして自分のDSLのファイルだけを探すようにすることが出来る。
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を生成している。