void (@NotNull Collection<String> rootsToAdd, @NotNull Set<WatchRequest> requestsToRemove, @NotNull Set<WatchRequest> result, @NotNull Map<String, List<WatchRequest>> roots, boolean recursiveWatchRoots) { List<WatchSymlinkRequest> watchSymlinkRequestsToAdd = new SmartList<>(); for (String root : rootsToAdd) { String watchRoot = prepareWatchRoot(root); if (watchRoot == null) continue; List<WatchRequest> requests = roots.computeIfAbsent(watchRoot, __ -> new SmartList<>()); boolean foundSameRequest = false; if (!requestsToRemove.isEmpty()) { for (WatchRequest currentRequest : requests) { if (requestsToRemove.remove(currentRequest)) { foundSameRequest = true; result.add(currentRequest); } } } if (!foundSameRequest) { WatchRequestImpl newRequest = new WatchRequestImpl(watchRoot, recursiveWatchRoots); requests.add(newRequest); result.add(newRequest); if (recursiveWatchRoots) { collectSymlinkRequests(newRequest, watchSymlinkRequestsToAdd); } if (requests.size() == 1 && !WatchRootsUtil.isCoveredRecursively(myOptimizedRecursiveWatchRoots, watchRoot)) { myWatcherRequiresUpdate = true; if (recursiveWatchRoots) { WatchRootsUtil.insertRecursivePath(myOptimizedRecursiveWatchRoots, watchRoot); } } } } List<WatchSymlinkRequest> watchSymlinkRequestsToRemove = new SmartList<>(); for (WatchRequest request : requestsToRemove) { removeWatchRequest(request); if (recursiveWatchRoots) { collectSymlinkRequests((WatchRequestImpl)request, watchSymlinkRequestsToRemove); } } if (recursiveWatchRoots) { addWatchSymlinkRequests(watchSymlinkRequestsToAdd); removeWatchSymlinkRequests(watchSymlinkRequestsToRemove); } }