replaceCommand method

void replaceCommand(
  1. int index,
  2. dynamic replacement, [
  3. dynamic resultIndex
])

Replaces the command at index with replacement (a single command or a list of commands), remapping Result/NestedResult references in later commands so they keep pointing at the right command after the splice.

resultIndex is the argument that references to the replaced command's result should resolve to. Defaults to index; pass a Result/NestedResult map to redirect references to a specific command in replacement.

Implementation

void replaceCommand(int index, dynamic replacement, [dynamic resultIndex]) {
  resultIndex ??= index;

  if (replacement is! List) {
    commands[index] = replacement;
    return;
  }

  final sizeDiff = replacement.length - 1;
  commands.replaceRange(index, index + 1, [
    for (final command in replacement) _deepClone(command),
  ]);

  mapArguments((arg, _, commandIndex) {
    if (commandIndex < index + replacement.length) {
      return arg;
    }

    if (resultIndex is! int) {
      if ((arg["\$kind"] == 'Result' && arg["Result"] == index) ||
          (arg["\$kind"] == 'NestedResult' &&
              arg["NestedResult"][0] == index)) {
        if (arg["NestedResult"] == null || arg["NestedResult"][1] == 0) {
          return _deepClone(resultIndex);
        }
        throw ArgumentError(
          'Cannot replace command $index with a specific result type: '
          'NestedResult[$index, ${arg["NestedResult"][1]}] references a nested '
          'element that cannot be mapped to the replacement result',
        );
      }
    }

    switch (arg["\$kind"]) {
      case 'Result':
        if (arg["Result"] == index && resultIndex is int) {
          arg["Result"] = resultIndex;
        }
        if (arg["Result"] > index) {
          arg["Result"] += sizeDiff;
        }
        break;
      case 'NestedResult':
        if (arg["NestedResult"][0] == index && resultIndex is int) {
          return {
            "\$kind": 'NestedResult',
            "NestedResult": [resultIndex, arg["NestedResult"][1]],
          };
        }
        if (arg["NestedResult"][0] > index) {
          arg["NestedResult"][0] += sizeDiff;
        }
        break;
    }
    return arg;
  });
}