void (File packageOutputRoot, String rootPackageVMName, @Nullable String requestedSimpleName) { final Stack<PackageData> stack = new Stack<>(new PackageData(rootPackageVMName, packageOutputRoot.listFiles())); while (!stack.isEmpty()) { ProgressIndicatorProvider.checkCanceled(); final PackageData packageData = stack.pop(); final String packageVMName = packageData.packageVMName; final File[] children = packageData.children; if (children == null) continue; final Map<String, List<File>> topLevelClasses = new HashMap<>(); for (File child : children) { if (AnalysisUtils.isClassFile(child)) { String simpleName = AnalysisUtils.getClassName(child); String classFqVMName = AnalysisUtils.buildVMName(packageVMName, simpleName); String toplevelClassSrcFQName = AnalysisUtils.getSourceToplevelFQName(classFqVMName); topLevelClasses.computeIfAbsent(toplevelClassSrcFQName, k -> new ArrayList<>()).add(child); } else if (requestedSimpleName == null && child.isDirectory()) { String childPackageVMName = AnalysisUtils.buildVMName(packageVMName, child.getName()); stack.push(new PackageData(childPackageVMName, child.listFiles())); } } String requestedTopLevelName = requestedSimpleName == null ? null : AnalysisUtils.internalNameToFqn(AnalysisUtils.buildVMName(packageVMName, requestedSimpleName)); for (Map.Entry<String, List<File>> entry : topLevelClasses.entrySet()) { String topLevelClassName = entry.getKey(); if (requestedTopLevelName != null && !requestedTopLevelName.equals(topLevelClassName)) continue; visitClassFiles(topLevelClassName, entry.getValue(), packageVMName); } } myCurrentRootsCount++; updateProgress(); }