protected void visitRoot(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();
  }
protected void visitRoot(File packageOutputRoot, String rootPackageVMName, @Nullable String requestedSimpleName)