void (@NotNull final GroovyFile file, @NotNull final Set<? super String> importedClasses, @NotNull final Set<? super String> staticallyImportedMembers, @NotNull final Set<? super GrImportStatement> usedImports, @NotNull final Set<? super GrImportStatement> unresolvedOnDemandImports, @NotNull final Set<? super String> implicitlyImported, @NotNull final Set<? super String> innerClasses, @NotNull final Map<String, String> aliased, @NotNull final Map<String, String> annotations) { final Set<String> unresolvedReferenceNames = new LinkedHashSet<>(); file.accept(new PsiRecursiveElementWalkingVisitor() { @Override public void visitElement(@NotNull PsiElement element) { if (!(element instanceof GrImportStatement) && !(element instanceof GrPackageDefinition)) { super.visitElement(element); } if (element instanceof GrReferenceElement) { visitRefElement((GrReferenceElement)element); } } private void visitRefElement(GrReferenceElement refElement) { if (refElement.isQualified()) return; final String refName = refElement.getReferenceName(); if ("super".equals(refName)) return; final GroovyResolveResult[] resolveResults = refElement.multiResolve(false); if (resolveResults.length == 0 && refName != null) { if (PsiTreeUtil.getParentOfType(refElement, GrImportStatement.class) == null) { unresolvedReferenceNames.add(refName); } } for (GroovyResolveResult resolveResult : resolveResults) { final PsiElement context = resolveResult.getCurrentFileResolveContext(); final PsiElement resolved = resolveResult.getElement(); if (resolved == null) return; if (context instanceof GrImportStatement importStatement) { usedImports.add(importStatement); if (GroovyImportHelper.isImplicitlyImported(resolved, refName, file)) { addImplicitClass(resolved); } if (!importStatement.isAliasedImport() && !isAnnotatedImport(importStatement)) { String importedName = null; if (importStatement.isOnDemand()) { if (importStatement.isStatic()) { if (resolved instanceof PsiMember member) { final PsiClass clazz = member.getContainingClass(); if (clazz != null) { final String classQName = clazz.getQualifiedName(); if (classQName != null) { final String name = member.getName(); if (name != null) { importedName = classQName + "." + name; } } } } } else { importedName = getTargetQualifiedName(resolved); } } else { importedName = importStatement.getImportFqn(); } if (importedName == null) return; final String importRef = importStatement.getImportFqn(); if (importStatement.isAliasedImport()) { aliased.put(importRef, importedName); return; } if (importStatement.isStatic()) { staticallyImportedMembers.add(importedName); } else { importedClasses.add(importedName); if (resolved instanceof PsiClass && ((PsiClass)resolved).getContainingClass() != null) { innerClasses.add(importedName); } } } } else if (context == null && !(refElement.getParent() instanceof GrImportStatement) && refElement.getQualifier() == null && (!(resolved instanceof PsiClass) || ((PsiClass)resolved).getContainingClass() == null)) { addImplicitClass(resolved); } } } private void addImplicitClass(PsiElement element) { final String qname = getTargetQualifiedName(element); if (qname != null) { implicitlyImported.add(qname); importedClasses.add(qname); } } }); final Set<GrImportStatement> importsToCheck = new LinkedHashSet<>(PsiUtil.getValidImportStatements(file)); for (GrImportStatement anImport : importsToCheck) { if (usedImports.contains(anImport)) continue; final GrCodeReferenceElement ref = anImport.getImportReference(); assert ref != null : "invalid import!"; if (ref.resolve() == null) { if (anImport.isOnDemand()) { usedImports.add(anImport); unresolvedOnDemandImports.add(anImport); } else { String importedName = anImport.getImportedName(); if (importedName != null && unresolvedReferenceNames.contains(importedName)) { usedImports.add(anImport); final String symbolName = anImport.getImportFqn(); if (anImport.isAliasedImport()) { aliased.put(symbolName, importedName); } else if (anImport.isStatic()) { staticallyImportedMembers.add(symbolName); } else if (!isAnnotatedImport(anImport)) { importedClasses.add(symbolName); } } } } } file.acceptChildren(new GroovyElementVisitor() { @Override public void visitImportStatement(@NotNull GrImportStatement importStatement) { final String annotationText = importStatement.getAnnotationList().getText(); if (!StringUtil.isEmptyOrSpaces(annotationText)) { final String importRef = importStatement.getImportFqn(); annotations.put(importRef, annotationText); } } }); usedImports.removeAll(unusedImports(file)); }