@Override
  public void setWatchRoots(@NotNull List<String> recursive, @NotNull List<String> flat, boolean shuttingDown) {
    if (shuttingDown) {
      myShuttingDown = true;
      for (Map.Entry<String, VmData> entry : myVMs.entrySet()) {
        shutdownProcess(entry.getValue(), false);
      }
    }
    if (myShuttingDown) return;

    Map<String, VmData> newVMs = new HashMap<>();
    List<String> ignored = new ArrayList<>();
    sortRoots(recursive, newVMs, ignored, true);
    sortRoots(flat, newVMs, ignored, false);
    myNotificationSink.notifyManualWatchRoots(this, ignored);

    for (Map.Entry<String, VmData> entry : newVMs.entrySet()) {
      VmData upcoming = entry.getValue(), vm = myVMs.computeIfAbsent(entry.getKey(), k -> upcoming);
      assert vm != null : entry;
      if (vm == upcoming) {
        setupProcess(vm);
      }
      else if (!vm.recursive.equals(upcoming.recursive) || !vm.flat.equals(upcoming.flat)) {
        vm.reload(upcoming);
        setupProcess(vm);
      }
      else {
        myNotificationSink.notifyManualWatchRoots(this, vm.ignored);
      }
    }

    for (Iterator<Map.Entry<String, VmData>> iterator = myVMs.entrySet().iterator(); iterator.hasNext(); ) {
      Map.Entry<String, VmData> entry = iterator.next();
      if (!newVMs.containsKey(entry.getKey())) {
        iterator.remove();
        shutdownProcess(entry.getValue(), true);
      }
    }
  }
@Override
  public void setWatchRoots(@NotNull List<String> recursive, @NotNull List<String> flat, boolean shuttingDown)