package com.intellij.plugins.haxe.ide.library;

import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.ui.RootDetector;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.plugins.haxe.HaxeBundle;
import com.intellij.plugins.haxe.HaxeFileType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author: Fedor.Korotkov
 */
public class HaxeLibRootDetector extends RootDetector {
  protected HaxeLibRootDetector() {
    super(OrderRootType.SOURCES, false, HaxeBundle.message("sources.root.detector.name"));
  }

  @NotNull
  @Override
  public Collection<VirtualFile> detectRoots(@NotNull VirtualFile rootCandidate, @NotNull ProgressIndicator progressIndicator) {
    List<VirtualFile> result = new ArrayList<VirtualFile>();
    collectRoots(rootCandidate, result, progressIndicator);
    return result;
  }

  public static void collectRoots(VirtualFile file, List<VirtualFile> result, @Nullable ProgressIndicator progressIndicator) {
    if (progressIndicator != null) {
      progressIndicator.checkCanceled();
    }
    if (!file.isDirectory() || file.getFileSystem() instanceof JarFileSystem) return;
    if (progressIndicator != null) {
      progressIndicator.setText2(file.getPresentableUrl());
    }

    if (file.findChild(".current") != null) {
      for (VirtualFile child : file.getChildren()) {
        if (child.isDirectory() && containsHaxeFiles(child)) {
          result.add(child);
        }
      }
      return;
    }

    for (VirtualFile child : file.getChildren()) {
      collectRoots(child, result, progressIndicator);
    }
  }

  private static boolean containsHaxeFiles(VirtualFile file) {
    boolean result = false;
    for (VirtualFile child : file.getChildren()) {
      if (child.isDirectory()) {
        result = result || containsHaxeFiles(child);
      }
      else {
        result = result || HaxeFileType.DEFAULT_EXTENSION.equalsIgnoreCase(child.getExtension());
      }
    }
    return result;
  }
}

@@ -287,26 +287,123 @@
 pi.vfs.V
-irtualFile
+fsUtilCore;%0Aimport com.intellij.openapi.vfs.VirtualFile;%0Aimport com.intellij.openapi.vfs.VirtualFileVisitor
 ;%0Aimport
@@ -1226,16 +1226,22 @@
 le file,
+ final
  List%3CVi
@@ -1269,16 +1269,22 @@
 ullable 
+final 
 Progress
@@ -1310,24 +1310,255 @@
 ndicator) %7B%0A
+    if (file.getFileSystem() instanceof JarFileSystem) %7B%0A      return;%0A    %7D%0A    VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() %7B%0A      @Override%0A      public boolean visitFile(@NotNull VirtualFile file) %7B%0A    
     if (prog
@@ -1574,32 +1574,36 @@
 ator != null) %7B%0A
+    
       progressIn
@@ -1627,22 +1627,30 @@
 eled();%0A
+    
     %7D%0A
+    
     if (
@@ -1672,71 +1672,32 @@
 ry()
- %7C%7C file.getFileSystem() instanceof JarFileSystem) return;%0A
+) return false;%0A   
     
+ 
 if (
@@ -1721,24 +1721,28 @@
  != null) %7B%0A
+    
       progre
@@ -1793,23 +1793,31 @@
 ));%0A    
-%7D%0A%0A
+    %7D%0A%0A   
     
+ 
 if (file
@@ -1846,24 +1846,28 @@
  != null) %7B%0A
+    
       for (V
@@ -1911,24 +1911,28 @@
 ) %7B%0A        
+    
 if (child.is
@@ -1980,24 +1980,28 @@
 %7B%0A          
+    
 result.add(c
@@ -2011,28 +2011,24 @@
 d);%0A        
-%7D%0A  
     %7D%0A      
@@ -2031,133 +2031,85 @@
     
+    %7D%0A          
 return
-;%0A    %7D%0A%0A    for (VirtualFile child : file.getChildren()) %7B%0A      collectRoots(child, result, progressIndicator);
+ false;%0A        %7D%0A%0A        return true;%0A      %7D
 %0A    %7D
+);
 %0A  %7D
@@ -2153,16 +2153,22 @@
 xeFiles(
+final 
 VirtualF
@@ -2171,28 +2171,27 @@
 ualFile 
-file
+dir
 ) %7B%0A    
 boolean 
@@ -2186,216 +2186,247 @@
     
-boolean result = false;%0A    for (VirtualFile child : file.getChildren()) %7B%0A      if (child.isDirectory()) %7B%0A        result = result %7C%7C containsHaxeFiles(child);%0A      %7D%0A      else %7B%0A        result = result %7C%7C
+final VirtualFileVisitor.Result result = VfsUtilCore.visitChildrenRecursively(dir, new VirtualFileVisitor() %7B%0A      @NotNull%0A      @Override%0A      public Result visitFileEx(@NotNull VirtualFile file) %7B%0A        return !file.isDirectory() &&
  Hax
@@ -2470,21 +2470,20 @@
 oreCase(
-child
+file
 .getExte
@@ -2490,16 +2490,41 @@
 nsion())
+ ? skipTo(dir) : CONTINUE
 ;%0A      
@@ -2526,24 +2526,26 @@
      %7D%0A    %7D
+);
 %0A    return 
@@ -2546,20 +2546,41 @@
 eturn result
+.skipToParent != null
 ;%0A  %7D%0A%7D%0A

Use VFS visitor in place of recursion (haxe)