Future compile()

in frontend_server_client/lib/src/frontend_server_client.dart [106:206]


  Future<CompileResult?> compile([List<Uri>? invalidatedUris]) async {
    String action;
    switch (_state) {
      case _ClientState.waitingForFirstCompile:
        action = 'compile';
        break;
      case _ClientState.waitingForRecompile:
        action = 'recompile';
        break;
      case _ClientState.waitingForAcceptOrReject:
        throw StateError(
            'Previous `CompileResult` must be accepted or rejected by '
            'calling `accept` or `reject`.');
      case _ClientState.compiling:
        throw StateError(
            'App is already being compiled, you must wait for that to '
            'complete and `accept` or `reject` the result before compiling '
            'again.');
      case _ClientState.rejecting:
        throw StateError('Still waiting for previous `reject` call to finish. '
            'You must await that before compiling again.');
    }
    _state = _ClientState.compiling;

    try {
      var command = StringBuffer('$action $_entrypoint');
      if (action == 'recompile') {
        if (invalidatedUris == null || invalidatedUris.isEmpty) {
          throw StateError(
              'Subsequent compile invocations must provide a non-empty list '
              'of invalidated uris.');
        }
        var boundaryKey = generateUuidV4();
        command.writeln(' $boundaryKey');
        for (var uri in invalidatedUris) {
          command.writeln('$uri');
        }
        command.write(boundaryKey);
      }

      _sendCommand(command.toString());
      var state = _CompileState.started;
      late String feBoundaryKey;
      var newSources = <Uri>{};
      var removedSources = <Uri>{};
      var compilerOutputLines = <String>[];
      var errorCount = 0;
      String? outputDillPath;
      while (
          state != _CompileState.done && await _feServerStdoutLines.hasNext) {
        var line = await _nextInputLine();
        switch (state) {
          case _CompileState.started:
            assert(line.startsWith('result'));
            feBoundaryKey = line.substring(line.indexOf(' ') + 1);
            state = _CompileState.waitingForKey;
            continue;
          case _CompileState.waitingForKey:
            if (line == feBoundaryKey) {
              state = _CompileState.gettingSourceDiffs;
            } else {
              compilerOutputLines.add(line);
            }
            continue;
          case _CompileState.gettingSourceDiffs:
            if (line.startsWith(feBoundaryKey)) {
              state = _CompileState.done;
              var parts = line.split(' ');
              outputDillPath = parts.getRange(1, parts.length - 1).join(' ');
              errorCount = int.parse(parts.last);
              continue;
            }
            var diffUri = Uri.parse(line.substring(1));
            if (line.startsWith('+')) {
              newSources.add(diffUri);
            } else if (line.startsWith('-')) {
              removedSources.add(diffUri);
            } else {
              throw StateError(
                  'unrecognized diff line, should start with a + or - but got: $line');
            }
            continue;
          case _CompileState.done:
            throw StateError('Unreachable');
        }
      }

      if (outputDillPath == null) {
        return null;
      }

      return CompileResult._(
          dillOutput: outputDillPath,
          errorCount: errorCount,
          newSources: newSources,
          removedSources: removedSources,
          compilerOutputLines: compilerOutputLines);
    } finally {
      _state = _ClientState.waitingForAcceptOrReject;
    }
  }