Interpolation constructor

Interpolation(
  1. Iterable<Object> contents,
  2. Iterable<FileSpan?> spans,
  3. FileSpan span
)

Creates a new Interpolation with the given contents.

The spans must include a FileSpan for each Expression in contents. These spans should generally cover the entire #{} surrounding the expression.

The single span must cover the entire interpolation.

Implementation

Interpolation(
  Iterable<Object /* String | Expression */ > contents,
  Iterable<FileSpan?> spans,
  this.span,
)   : contents = List.unmodifiable(contents),
      spans = List.unmodifiable(spans) {
  if (spans.length != contents.length) {
    throw ArgumentError.value(
      this.spans,
      "spans",
      "Must be the same length as contents.",
    );
  }

  for (var i = 0; i < this.contents.length; i++) {
    var isString = this.contents[i] is String;
    if (!isString && this.contents[i] is! Expression) {
      throw ArgumentError.value(
        this.contents,
        "contents",
        "May only contain Strings or Expressions.",
      );
    } else if (isString) {
      if (i != 0 && this.contents[i - 1] is String) {
        throw ArgumentError.value(
          this.contents,
          "contents",
          "May not contain adjacent Strings.",
        );
      } else if (i < spans.length && this.spans[i] != null) {
        throw ArgumentError.value(
          this.spans,
          "spans",
          "May not have a value for string elements (at index $i).",
        );
      }
    } else if (i >= spans.length || this.spans[i] == null) {
      throw ArgumentError.value(
        this.spans,
        "spans",
        "Must not have a value for expression elements (at index $i).",
      );
    }
  }
}