NodeToUpdate (@NotNull NewVirtualFileSystem fs, @NotNull NewVirtualFileSystem currentFS, @NotNull List<String> names, @Nullable NewVirtualFile fsRoot, @NotNull FilePartNode currentNode, @NotNull FilePartNode parentNode) { VirtualFile NEVER_TRIED_TO_FIND = NullVirtualFile.INSTANCE; // we try to never call file.findChild() until absolutely necessary, because it's expensive; // instead, rely on string name matching as long as possible VirtualFile currentFile = NEVER_TRIED_TO_FIND; for (int i = names.size() - 1; i >= 0; i--) { String name = names.get(i); currentFS = enterJar(fs, currentFS, name); int index = currentNode.binarySearchChildByName(name); if (index >= 0) { parentNode = currentNode; currentNode = currentNode.children[index]; //noinspection UseVirtualFileEquals currentFile = currentFile == NEVER_TRIED_TO_FIND || currentFile == null ? currentFile : currentFile.findChild(name); continue; } // create and insert new node // first, have to check if the file root/names(end)/.../names[i] exists // if yes, create nameId-based FilePartNode (for faster search and memory efficiency), // if not, create temp UrlPartNode which will be replaced with FPPN when the real file is created //noinspection UseVirtualFileEquals if (currentFile == NEVER_TRIED_TO_FIND) { fsRoot = findRoot(fs, names, fsRoot); currentFile = fsRoot == null ? null : findFileFromRoot(fsRoot, currentFS, names, i); } else { currentFile = currentFile == null ? null : findChildThroughJar(currentFile, name, currentFS); } // check that found child name is the same as the one we were looking for // otherwise it may be the 8.3 abbreviation, which we should expand and look again //noinspection UseVirtualFileEquals if (currentFile != null && currentFile != NEVER_TRIED_TO_FIND && !currentFile.getName().equals(name)) { name = currentFile.getName(); index = currentNode.binarySearchChildByName(name); if (index >= 0) { parentNode = currentNode; currentNode = currentNode.children[index]; continue; } } FilePartNode child = createNode(currentFS, currentNode, currentFile, name); currentNode.children = ArrayUtil.insert(currentNode.children, -index - 1, child); parentNode = currentNode; currentNode = child; } return new NodeToUpdate(parentNode, currentNode); }