Eclipseのプラグイン開発のJDTの入力補完の実装方法について。
|
Javaエディター上で独自の入力補完(content assist)を行うことが出来る。
extensionでorg.eclipse.jdt.ui.javaCompletionProposalComputerを定義する。
まず、入力補完を行うクラスを用意する。
import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext; import org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer; import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext; import org.eclipse.jface.text.contentassist.CompletionProposal; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.IContextInformation;
public class MyCompletionProposalComputer implements IJavaCompletionProposalComputer {
@Override public void sessionStarted() { }
@Override public List<ICompletionProposal> computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor) { if (!(context instanceof JavaContentAssistInvocationContext)) { return Collections.emptyList(); } JavaContentAssistInvocationContext javaContext = (JavaContentAssistInvocationContext) context; ICompilationUnit cu = javaContext.getCompilationUnit(); int offset = context.getInvocationOffset(); ASTNode node = 〜; // ASTのVisitorを使ってoffsetの位置のノードを取得 int start = node.getStartPosition(); int length = node.getLength(); List<ICompletionProposal> list = new ArrayList<ICompletionProposal>(); { String s = "assist1"; // 補完する文字列 CompletionProposal proposal = new CompletionProposal(s, start, length, s.length()); list.add(proposal); } { String s = "assist2"; // 補完する文字列 CompletionProposal proposal = new CompletionProposal(s, start, length, s.length()); list.add(proposal); } return list; }
@Override public List<IContextInformation> computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor) { return null; }
@Override public String getErrorMessage() { return null; }
@Override public void sessionEnded() { } }
入力補完を行うには、computeCompletionProposals()を実装する。
JDTの場合、引数のcontextにJavaContentAssistInvocationContextオブジェクトが渡される。
JavaContentAssistInvocationContextからICompilationUnitを取得できるので、ASTのVisidorを使ってASTNodeを取得し、それを使って補完文字列を構築する。
引数 | 説明 | |
---|---|---|
1 | replacementString | 補完する文字列(補完後の文字列) |
2 | replacementOffset | 補完された場合に置き換える開始位置 |
3 | replacementLength | 補完された場合に置き換える長さ(既存のソースからこの長さ分だけ削除される) |
4 | cursorPosition | 補完後の位置(replacementOffsetからの相対位置) |
マニフェストファイルのextensionで 入力補完クラスの指定を行う。
<extension id="jdt.assist.category" name="My JDT Proposals" point="org.eclipse.jdt.ui.javaCompletionProposalComputer"> <proposalCategory icon="icons/example.gif"> </proposalCategory> </extension> <extension id="jdt.assist.example" name="my assist" point="org.eclipse.jdt.ui.javaCompletionProposalComputer"> <javaCompletionProposalComputer activate="true" categoryId="com.example.jdt.assist.category" class="com.example.jdt.assist.MyCompletionProposalComputer" needsSortingAfterFiltering="false"> <partition type="__java_string"> </partition> </javaCompletionProposalComputer> </extension>
javaCompletionProposalComputerのextensionでは、まずカテゴリーを定義する。
カテゴリーに付けた名前は、設定ページ(Preferences)で入力補完の実施可否を設定する際に表示される。
(メニューバーの「Windows」→「Preferences」で設定ダイアログを開き、左側のツリーで「Java」⇒「Editor」⇒「Content
Assist」⇒「Advanced」で入力補完の実施可否を設定できる)
そして、入力補完を行うクラスを定義する。
ここでactivateをtrueにしておかないと、入力補完が実施されない。
categoryIdにはカテゴリーIDを指定する。接頭辞としてプラグインIDが付くので、plugin.xmlに直接記述するのではなく、マニフェストエディターの機能を使ってカテゴリーIDを選択する方がいいだろう。
partitionのtypeは、Javaソース上のどの位置で入力補完を発生させるかを指定する。 (partitionを複数書けば、複数の箇所で発生させることが出来る)
type | 説明 |
---|---|
__dftl_partition_content_type |
通常のソース |
__java_singleline_comment |
単一行コメントの中 |
__java_multiline_comment |
複数行コメントの中 |
__java_javadoc |
Javadocの中 |
__java_string |
文字列の中 |
__java_character |
入力補完の実験をしていると、以下のようなエラーダイアログが出ることがある。
ログにも以下のようなメッセージが出力される。
!ENTRY org.eclipse.jdt.ui 2 0 2014-05-03 11:53:11.904 !MESSAGE The 'Key string assist' proposal computer from the 'jp.hishidama.xtext.dmdl_editor.ui' plug-in did not complete normally. The extension took too long to return from the 'computeCompletionProposals()' operation.
computeCompletionProposals()の戻り値としてnullを返すとエラーが発生するので、補完候補が無い場合は空のListを返すようにする。
ついでに言うと、computeCompletionProposals()の呼び出しが返ってくる時間が決められており(デフォルトでは50ms)、その時間を過ぎてもエラーとなる。
つまり、ブレークポイントで止めてデバッグしていると、実行を再開した後でエラーになるということだ(苦笑)
(この時間は設定ページで多少変えられる。メニューバーの「Windows」→「Preferences」で設定ダイアログを開き、左側のツリーで「Java」⇒「Editor」⇒「Content
Assist」⇒「Advanced」で「Timeout for fetching parameter name from attached
Javadoc」にミリ秒単位で入力する。ただし最大は5000ms)