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を生成している。