XtextのNatureAddingEditorCallbackクラス(IXtextEditorCallbackインターフェース)のメモ。
|
Xtextで生成されたエディターを起動すると、初回に「Do you want to add the Xtext nature to the project 'プロジェクト名'?」というダイアログが表示される。
このダイアログはNatureAddingEditorCallbackクラスで表示しているので、 ダイアログを出さないようにする為にはNatureAddingEditorCallbackクラスを独自クラスに差し替えればよい。
ただし、NatureAddingEditorCallbackは(Eclipseプラグイン機構の仕組みにより)外部に公開されていないクラスなので、直接継承しようとすると警告が出る。
したがって、(他の処理も特に無いので)NatureAddingEditorCallbackの親クラスを継承して独自クラスを作ればよい。
Xtext2.4ではNatureAddingEditorCallbackはAbstractDirtyStateAwareEditorCallbackを継承しているので、独自クラスもAbstractDirtyStateAwareEditorCallbackを継承すれば(このクラスは公開されているクラスなので)警告も出ない。
と思っていた。
しかし、Xtext2.7でAbstractDirtyStateAwareEditorCallbackが非推奨となり、NatureAddingEditorCallbackもIXtextEditorCallback.NullImplを継承するよう修正された。
AbstractDirtyStateAwareEditorCallbackを継承した独自クラスを使っていると、Xtext2.7環境では、エディターで文字を入力する度に
『Resource was edited concurrently.』「The resource is concurrently edited in
another editor. Do you want to continue?」というダイアログが出て、非常に鬱陶しい。

「Yes」を押せば一時的に出なくなるが、ファイルを保存してから修正しようとするとまた出てくる(苦笑)
Xtext2.7では、NatureAddingEditorCallbackを差し替えるには(AbstractDirtyStateAwareEditorCallbackでなく)IXtextEditorCallback.NullImplを継承するようにするべき。
とは言え、過去のバージョンでも使えるようにするなら、警告が出るのはあきらめて、NatureAddingEditorCallbackを直接継承しておくのが良さそうだ。
→ネイチャーの自動登録
Xtext2.4で(NatureAddingEditorCallbackを差し替えて)自動的にネイチャーを登録する例。
import java.util.Arrays; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.xtext.ui.XtextProjectHelper; import org.eclipse.xtext.ui.editor.AbstractDirtyStateAwareEditorCallback; import org.eclipse.xtext.ui.editor.XtextEditor;
public class MyEditorCallback extends AbstractDirtyStateAwareEditorCallback {
@Override
public void afterCreatePartControl(XtextEditor editor) {
super.afterCreatePartControl(editor);
IResource resource = editor.getResource();
if (resource == null) {
return;
}
IProject project = resource.getProject();
if (!XtextProjectHelper.hasNature(project) && project.isAccessible() && !project.isHidden()) {
addNature(project);
}
}
private void addNature(IProject project) {
try {
IProjectDescription description = project.getDescription();
String[] natures = description.getNatureIds();
String[] newNatures = Arrays.copyOf(natures, natures.length + 1);
newNatures[natures.length] = XtextProjectHelper.NATURE_ID;
description.setNatureIds(newNatures);
project.setDescription(description, null);
} catch (CoreException e) {
MyActivator.getInstance().getLog().log(e.getStatus());
}
}
}
作成したCallbackクラスをUiModuleで指定する。
public class MyUiModule extends com.example.ui.AbstractMyUiModule {
〜
@Override
public Class<? extends org.eclipse.xtext.ui.editor.IXtextEditorCallback> bindIXtextEditorCallback() {
return MyEditorCallback.class;
}
}
Xtext2.7で(NatureAddingEditorCallbackを差し替えて)自動的にネイチャーを登録する例。
(Xtext2.4版との違いは、親クラスだけ)
import java.util.Arrays; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.xtext.ui.XtextProjectHelper; import org.eclipse.xtext.ui.editor.IXtextEditorCallback; import org.eclipse.xtext.ui.editor.XtextEditor;
public class MyEditorCallback extends IXtextEditorCallback.NullImpl {
@Override
public void afterCreatePartControl(XtextEditor editor) {
super.afterCreatePartControl(editor);
IResource resource = editor.getResource();
if (resource == null) {
return;
}
IProject project = resource.getProject();
if (!XtextProjectHelper.hasNature(project) && project.isAccessible() && !project.isHidden()) {
addNature(project);
}
}
private void addNature(IProject project) {
try {
IProjectDescription description = project.getDescription();
String[] natures = description.getNatureIds();
String[] newNatures = Arrays.copyOf(natures, natures.length + 1);
newNatures[natures.length] = XtextProjectHelper.NATURE_ID;
description.setNatureIds(newNatures);
project.setDescription(description, null);
} catch (CoreException e) {
MyActivator.getInstance().getLog().log(e.getStatus());
}
}
}
作成したCallbackクラスをUiModuleで指定する。
public class MyUiModule extends com.example.ui.AbstractMyUiModule {
〜
@Override
public Class<? extends org.eclipse.xtext.ui.editor.IXtextEditorCallback> bindIXtextEditorCallback() {
return MyEditorCallback.class;
}
}