S-JIS[2014-05-03] 変更履歴

Eclipse JDT 入力補完

Eclipseプラグイン開発JDTの入力補完の実装方法について。


概要

Javaエディター上で独自の入力補完(content assist)を行うことが出来る。

extensionでorg.eclipse.jdt.ui.javaCompletionProposalComputerを定義する。


まず、入力補完を行うクラスを用意する。

MyCompletionProposalComputer.java:

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 = 〜; // ASTVisitorを使って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を取得し、それを使って補完文字列を構築する。

CompletionProposalクラスのコンストラクターの引数
引数 説明
1 replacementString 補完する文字列(補完後の文字列)
2 replacementOffset 補完された場合に置き換える開始位置
3 replacementLength 補完された場合に置き換える長さ(既存のソースからこの長さ分だけ削除される)
4 cursorPosition 補完後の位置(replacementOffsetからの相対位置)

マニフェストファイルのextensionで 入力補完クラスの指定を行う。

plugin.xml:

   <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)


JDTへ戻る / Eclipseプラグインへ戻る / Eclipseへ戻る / 技術メモへ戻る
メールの送信先:ひしだま