@Nullable
  private LookupFile getClosestParent(final String typed) {
    if (typed == null) return null;
    LookupFile lastFound = myFinder.find(typed);
    if (lastFound == null) return null;
    if (lastFound.exists()) {
      if (typed.charAt(typed.length() - 1) != File.separatorChar) return lastFound.getParent();
      return lastFound;
    }

    final String[] splits = myFinder.normalize(typed).split(myFileSpitRegExp);
    StringBuilder fullPath = new StringBuilder();
    for (int i = 0; i < splits.length; i++) {
      String each = splits[i];
      fullPath.append(each);
      if (i < splits.length - 1) {
        fullPath.append(myFinder.getSeparator());
      }
      final LookupFile file = myFinder.find(fullPath.toString());
      if (file == null || !file.exists()) return lastFound;
      lastFound = file;
    }

    return lastFound;
  }
  public void processCompletion(final CompletionResult result) {
    result.myToComplete = new ArrayList<LookupFile>();
    result.mySiblings = new ArrayList<LookupFile>();
    result.myKidsAfterSeparator = new ArrayList<LookupFile>();
    String typed = result.myCompletionBase;

    if (typed == null || typed.length() == 0) return;

    addMacroPaths(result, typed);

    final String typedText = myFinder.normalize(typed);

    result.current = getClosestParent(typed);
    result.myClosestParent = result.current;

    if (result.current != null) {
      result.currentParentMatch =
          SystemInfo.isFileSystemCaseSensitive
              ? typedText.equals(result.current.getAbsolutePath())
              : typedText.equalsIgnoreCase(result.current.getAbsolutePath());

      result.closedPath =
          typed.endsWith(myFinder.getSeparator())
              && typedText.length() > myFinder.getSeparator().length();
      final String currentParentText = result.current.getAbsolutePath();

      if (!typedText.toUpperCase().startsWith(currentParentText.toUpperCase())) return;

      String prefix = typedText.substring(currentParentText.length());
      if (prefix.startsWith(myFinder.getSeparator())) {
        prefix = prefix.substring(myFinder.getSeparator().length());
      } else if (typed.endsWith(myFinder.getSeparator())) {
        prefix = "";
      }

      result.effectivePrefix = prefix.toUpperCase();

      result.currentGrandparent = result.current.getParent();
      if (result.currentGrandparent != null && result.currentParentMatch && !result.closedPath) {
        final String currentGrandparentText = result.currentGrandparent.getAbsolutePath();
        if (StringUtil.startsWithConcatenationOf(
            typedText, currentGrandparentText, myFinder.getSeparator())) {
          result.grandparentPrefix =
              currentParentText
                  .substring(currentGrandparentText.length() + myFinder.getSeparator().length())
                  .toUpperCase();
        }
      }
    } else {
      result.effectivePrefix = typedText.toUpperCase();
    }

    ApplicationManager.getApplication()
        .runReadAction(
            new Runnable() {
              public void run() {
                if (result.current != null) {
                  result.myToComplete.addAll(
                      result.current.getChildren(
                          new LookupFilter() {
                            public boolean isAccepted(final LookupFile file) {
                              return myFilter.isAccepted(file)
                                  && file.getName()
                                      .toUpperCase()
                                      .startsWith(result.effectivePrefix);
                            }
                          }));

                  if (result.currentParentMatch && !result.closedPath) {
                    result.myKidsAfterSeparator.addAll(result.myToComplete);
                  }

                  if (result.grandparentPrefix != null) {
                    final List<LookupFile> siblings =
                        result.currentGrandparent.getChildren(
                            new LookupFilter() {
                              public boolean isAccepted(final LookupFile file) {
                                return !file.equals(result.current)
                                    && myFilter.isAccepted(file)
                                    && file.getName()
                                        .toUpperCase()
                                        .startsWith(result.grandparentPrefix);
                              }
                            });
                    result.myToComplete.addAll(0, siblings);
                    result.mySiblings.addAll(siblings);
                  }
                }

                int currentDiff = Integer.MIN_VALUE;
                LookupFile toPreselect = result.myPreselected;

                if (toPreselect == null || !result.myToComplete.contains(toPreselect)) {
                  boolean toPreselectFixed = false;
                  if (result.effectivePrefix.length() > 0) {
                    for (LookupFile each : result.myToComplete) {
                      String eachName = each.getName().toUpperCase();
                      if (!eachName.startsWith(result.effectivePrefix)) continue;
                      int diff = result.effectivePrefix.compareTo(eachName);
                      currentDiff = Math.max(diff, currentDiff);
                      if (currentDiff == diff) {
                        toPreselect = each;
                        toPreselectFixed = true;
                        break;
                      }
                    }

                    if (!toPreselectFixed) {
                      toPreselect = null;
                    }
                  } else {
                    toPreselect = null;
                  }

                  if (toPreselect == null) {
                    if (result.myToComplete.size() == 1) {
                      toPreselect = result.myToComplete.get(0);
                    } else if (result.effectivePrefix.length() == 0) {
                      if (result.mySiblings.size() > 0) {
                        toPreselect = result.mySiblings.get(0);
                      }
                    }

                    if (toPreselect == null
                        && !result.myToComplete.contains(toPreselect)
                        && result.myToComplete.size() > 0) {
                      toPreselect = result.myToComplete.get(0);
                    }
                  }
                }

                if (result.currentParentMatch && result.mySiblings.size() > 0) {
                  toPreselect = null;
                }

                result.myPreselected = toPreselect;
              }
            });
  }