簡體   English   中英

如何從 IType 中發現所有依賴項(又名“導入”)?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM