@Override
    public void notifyTextAvailable(@NotNull String line, @NotNull Key outputType) {
      if (outputType == ProcessOutputTypes.STDERR) {
        myVm.logger.warn(line);
      }
      if (outputType != ProcessOutputTypes.STDOUT || myShuttingDown) {
        return;
      }

      if (myVm.logger.isTraceEnabled()) myVm.logger.trace(">> " + line);

      if (myLastOp == null) {
        WatcherOp watcherOp;
        try {
          watcherOp = WatcherOp.valueOf(line);
        }
        catch (IllegalArgumentException e) {
          // `wsl.exe` own error messages are coming in UTF16LE, accompanied by a couple of short tails (decoding artifacts)
          byte[] raw = line.getBytes(StandardCharsets.UTF_8);
          if (raw.length > 3 && raw[0] != 0 && raw[2] != 0 && raw[1] + raw[3] == 0) {
            myVm.logger.warn(new String(raw, StandardCharsets.UTF_16LE));
          }
          else if (!(raw.length == 1 && raw[0] == 0 || raw.length == 2 && raw[0] + raw[1] == 0)) {
            myVm.logger.error("Illegal watcher command: '" + line + "'", (Throwable)null);
          }
          return;
        }

        if (watcherOp == WatcherOp.GIVEUP) {
          notifyOnFailure(myVm.name, IdeCoreBundle.message("watcher.gave.up"), null);
        }
        else if (watcherOp == WatcherOp.RESET) {
          myNotificationSink.notifyReset(Strings.trimEnd(myVm.prefix, '\\'));
        }
        else {
          myLastOp = watcherOp;
        }
      }
      else if (myLastOp == WatcherOp.MESSAGE) {
        String localized = Objects.requireNonNullElse(IdeCoreBundle.INSTANCE.messageOrNull(line), line); //NON-NLS
        myVm.logger.warn(localized);
        notifyOnFailure(myVm.name, localized, NotificationListener.URL_OPENING_LISTENER);
        myLastOp = null;
      }
      else if (myLastOp == WatcherOp.UNWATCHEABLE) {
        if ("#".equals(line)) {
          mySettingRoots.decrementAndGet();
          processUnwatchable();
          myLines.clear();
          myLastOp = null;
        }
        else {
          myLines.add(line);
        }
      }
      else {
        String path = StringUtil.trimEnd(line.replace('\0', '\n'), File.separator);  // unescape
        processChange(path, myLastOp);
        myLastOp = null;
      }
    }
@Override
    public void notifyTextAvailable(@NotNull String line, @NotNull Key outputType)