インタフェースの検索
ContentAssist175のために、インタフェースを検索する方法を調べてみました。
全ての型を辿る
型が多いと、とても時間がかかります。ソースとバイナリ(Jarの中の型)で処理を分けるのが面倒くさいです。
IPackageFragmentRoot roots = javaProject.getAllPackageFragmentRoots(); for (int i = 0; i < roots.length; i++) { IJavaElement elements = roots[i].getChildren(); for (int p = 0; p < elements.length; p++) { if (elements[p] instanceof IPackageFragment) { IPackageFragment pkg = (IPackageFragment) elements[p]; String pkgName = pkg.getElementName(); if (pkg.getKind() == IPackageFragmentRoot.K_SOURCE) { ICompilationUnit units = pkg.getCompilationUnits(); for (int u = 0; u < units.length; u++) { IType types = units[u].getAllTypes(); for (int t = 0; t < types.length; t++) { IType type = (IType) types[t]; if (type.isInterface()) { String typeName = pkgName + "." + type.getElementName(); // ここでInterfaceを処理する } } } } else if (pkg.getKind() == IPackageFragmentRoot.K_BINARY) { IClassFile[] classes = pkg.getClassFiles(); for (int c = 0; c < classes.length; c++) { IType type = classes[c].getType(); if (type.isInterface()) { String typeName = pkgName + "." + type.getElementName(); // ここでInterfaceを処理する } } }
NameLookupで検索する
JDTのソースから発掘しました。prefixで始まるインタフェースだけを検索します。packageFragmentにnullを指定すると、全てのパッケージからの検索になります。初回実行時は非常に時間がかかるけど、2回目以降は速かったと思います。
IJavaElementRequestor requestor = new JavaElementRequestor() { public void acceptType(IType type) { String typeName = type.getFullyQualifiedName(); // ここでInterfaceを処理する } }; NameLookup nameLookup = javaProject.newNameLookup(compilationUnit.getOwner()); nameLookup.seekTypes(prefix, packageFragment, true, NameLookup.ACCEPT_INTERFACES, requestor);
SearchEngine.search()で検索する
Java検索ダイアログで使われているようです。prefixで始まる型の定義を検索します。インタフェースだけを検索することは出来ないみたいで、クラスもヒットしてしまう。それなりに時間がかかります。
SearchRequestor requestor = new SearchRequestor() { public void acceptSearchMatch(SearchMatch match) throws CoreException { Object javaElement = match.getElement(); if (javaElement instanceof IType && ( (IType) javaElement).isInterface() ) { IType type = (IType) javaElement; String typeName = type.getFullyQualifiedName(); // ここでInterfaceを処理する } } }; IJavaSearchScope scope = SearchEngine.createJavaSearchScope(javaProject.getAllPackageFragmentRoots()); SearchPattern pattern = SearchPattern.createPattern(prefix, IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_PREFIX_MATCH); new SearchEngine().search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, scope, requestor, null);
SearchEngine.searchAllTypeNames()で検索する
JDTのコンテンツアシストのソースから発掘しました。超速く検索できますが、Eclipse3.0と3.1でバイナリ非互換になってしまいます。
char prefixCharArray = prefix.toCharArray();
ArrayList res = new ArrayList();
IPackageFragmentRoot pkgs = javaProject.getAllPackageFragmentRoots();
JavaSearchScope scope = (JavaSearchScope) SearchEngine.createJavaSearchScope(pkgs);
new SearchEngine().searchAllTypeNames(null, prefixCharArray,
SearchPattern.R_PREFIX_MATCH, IJavaSearchConstants.INTERFACE,
scope, new TypeInfoRequestor(res),
IJavaSearchConstants.FORCE_IMMEDIATE_SEARCH, null);
for (int i = 0; i < res.size(); i++) {
TypeInfo typeInfo = (TypeInfo) res.get(i);
String typeName = typeInfo.getFullyQualifiedName();
// ここでInterfaceを処理する
}
検索メソッドのパラメータが変更されていました。
// Eclipse 3.0 public void searchAllTypeNames( final char packageName, final char typeName, final int matchRule, int searchFor, IJavaSearchScope scope, final ITypeNameRequestor nameRequestor, int waitingPolicy, IProgressMonitor progressMonitor) throws JavaModelException { // Eclipse 3.1 public void searchAllTypeNames( final char packageName, final char typeName, final int matchRule, int searchFor, IJavaSearchScope scope, final TypeNameRequestor nameRequestor, int waitingPolicy, IProgressMonitor progressMonitor) throws JavaModelException {
ContentAssist175のいきなりインタフェース検索で使ったのはコレ。パッケージとパッケージ内インタフェース検索には、NameLookupを使ってみました。
パッケージ内インタフェースの補完が、まだ手抜きなので、補完できない場合があります。それを修正したら、Kijimunaでもいきなり補完を実装したいところです。