[英]How to discover all dependencies (aka. "imports") from an IType?
我正在使用 Eclipse JDT API 並且我有一個 IType。 我想發現這個 IType 的所有“依賴項”。
我認為這將是:
我現在忽略運行時依賴項發現。 我的目標是為“從 class 文件間接引用”提供一個 QuickFix,用於具有嚴格類路徑(無傳遞依賴)的設置。
還有一個復雜情況:類型本身或超類型可能來自沒有源附件的 jar。
按照這個答案的建議,我可能需要為此生成 AST。 該方法的任何提示? 我需要走完整的類型嗎? 還有另一種方法來獲取所有綁定並使用它們嗎? 那行得通嗎?
我最終以以下方式實現它。 它確實需要一些遞歸才能遵循一個類型的所有方法簽名。
// the type to analyze
IType typeToAnalyze = ...
// create an ASTParser
ASTParser parser = ASTParser.newParser(AST.getJLSLatest());
// set the resolution to a specific project which has the full classpath
parser.setProject(aJavaProject);
// configure the parser to resolve bindings
parser.setResolveBindings(true);
// I'm ok with ignoring method bodies
parser.setIgnoreMethodBodies(true);
// get the IBinding from the parser
IBinding[] bindings = parser.createBindings(new IJavaElement[] { typeToAnalyze }, monitor);
// I'm interested in the jar files or IJavaProjects
Set<IPath> dependencies = new HashSet<>();
// collect processed type names in a set to avoid endless recursion
Set<String> processedTypes = new HashSet<>();
// because we passed in an IType the returned binding is an instance of ITypeBinding
for (final IBinding binding : bindings) {
collectDependenciesFromType((ITypeBinding) binding, dependencies, processedTypes, monitor);
}
有幾種支持方法:
private void collectDependenciesFromType(final ITypeBinding binding, final Set<IPath> dependencies,
final Set<String> processedTypes, final IProgressMonitor monitor) {
if (monitor.isCanceled())
throw new OperationCanceledException();
if (binding.isAnonymous() || binding.isPrimitive() || binding.isNullType() || binding.isGenericType()
|| binding.isTypeVariable() || binding.isCapture() || binding.isWildcardType() || binding.isRecovered())
return;
if (binding.isArray()) {
collectDependenciesFromType(binding.getElementType(), dependencies, processedTypes, monitor);
return;
}
if (binding.getPackage().getName().startsWith("java."))
return;
if (processedTypes.contains(binding.getQualifiedName()))
return;
processedTypes.add(binding.getQualifiedName());
monitor.subTask(binding.getQualifiedName());
final IPath path = getJarOrProjectPath((IType) binding.getJavaElement());
if (path == null)
return;
dependencies.add(path);
for (final ITypeBinding interfaceBinding : binding.getInterfaces()) {
collectDependenciesFromType(interfaceBinding, dependencies, processedTypes, monitor);
}
final ITypeBinding superclass = binding.getSuperclass();
if (superclass != null) {
collectDependenciesFromType(superclass, dependencies, processedTypes, monitor);
}
for (final ITypeBinding typeParameter : binding.getTypeParameters()) {
collectDependenciesFromType(typeParameter, dependencies, processedTypes, monitor);
}
for (final IMethodBinding methodBinding : binding.getDeclaredMethods()) {
collectDependenciesFromMethod(methodBinding, dependencies, processedTypes, monitor);
}
}
private void collectDependenciesFromMethod(final IMethodBinding binding, final Set<IPath> dependencies,
final Set<String> processedTypes, final IProgressMonitor monitor) {
if (monitor.isCanceled())
throw new OperationCanceledException();
if (Modifier.isPrivate(binding.getModifiers()) || Modifier.isDefault(binding.getModifiers()))
return;
for (final ITypeBinding parameterType : binding.getParameterTypes()) {
collectDependenciesFromType(parameterType, dependencies, processedTypes, monitor);
}
collectDependenciesFromType(binding.getReturnType(), dependencies, processedTypes, monitor);
}
private IPath getJarOrProjectPath(final IType type) {
if (type.isBinary()) {
final IPackageFragmentRoot root = (IPackageFragmentRoot) type
.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
if ((root != null) && root.isArchive() && "jar".equals(root.getPath().getFileExtension()))
return root.getPath();
} else {
final IJavaProject javaProject = type.getJavaProject();
if (javaProject != null)
return javaProject.getPath();
}
return null;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.