PackageVersionNumberGeneralLibraryConstraint.parse constructor

PackageVersionNumberGeneralLibraryConstraint.parse(
  1. String text
)

Parses a version constraint.

This string is one of:

Whitespace is ignored.

Examples:

any
^0.7.2
^1.0.0-alpha
1.2.3-alpha
<=5.1.4
>2.0.4 <= 2.4.6

Implementation

factory PackageVersionNumberGeneralLibraryConstraint.parse(String text) {
  var originalText = text;

  void skipWhitespace() {
    text = text.trim();
  }

  skipWhitespace();

  // Handle the "any" constraint.
  if (text == 'any') return any;

  // Try to parse and consume a version number.
  PackageVersionNumberGeneralLibrary?
      matchPackageVersionNumberGeneralLibrary() {
    var version = startVersion.firstMatch(text);
    if (version == null) return null;

    text = text.substring(version.end);
    return PackageVersionNumberGeneralLibrary.parse(version[0]!);
  }

  // Try to parse and consume a comparison operator followed by a version.
  PackageVersionNumberGeneralLibraryRange? matchComparison() {
    var comparison = startComparison.firstMatch(text);
    if (comparison == null) return null;

    var op = comparison[0]!;
    text = text.substring(comparison.end);
    skipWhitespace();

    var version = matchPackageVersionNumberGeneralLibrary();
    if (version == null) {
      throw FormatException('Expected version number after "$op" in '
          '"$originalText", got "$text".');
    }

    return switch (op) {
      '<=' => PackageVersionNumberGeneralLibraryRange(
          max: version, includeMax: true),
      '<' => PackageVersionNumberGeneralLibraryRange(
          max: version, alwaysIncludeMaxPreRelease: true),
      '>=' => PackageVersionNumberGeneralLibraryRange(
          min: version, includeMin: true),
      '>' => PackageVersionNumberGeneralLibraryRange(min: version),
      _ => throw UnsupportedError(op),
    };
  }

  // Try to parse the "^" operator followed by a version.
  PackageVersionNumberGeneralLibraryConstraint? matchCompatibleWith() {
    if (!text.startsWith(compatibleWithChar)) return null;

    text = text.substring(compatibleWithChar.length);
    skipWhitespace();

    var version = matchPackageVersionNumberGeneralLibrary();
    if (version == null) {
      throw FormatException('Expected version number after '
          '"$compatibleWithChar" in "$originalText", got "$text".');
    }

    if (text.isNotEmpty) {
      throw FormatException('Cannot include other constraints with '
          '"$compatibleWithChar" constraint in "$originalText".');
    }

    return PackageVersionNumberGeneralLibraryConstraint.compatibleWith(
        version);
  }

  var compatibleWith = matchCompatibleWith();
  if (compatibleWith != null) return compatibleWith;

  PackageVersionNumberGeneralLibrary? min;
  var includeMin = false;
  PackageVersionNumberGeneralLibrary? max;
  var includeMax = false;

  for (;;) {
    skipWhitespace();

    if (text.isEmpty) break;

    var newRange =
        matchPackageVersionNumberGeneralLibrary() ?? matchComparison();
    if (newRange == null) {
      throw FormatException('Could not parse version "$originalText". '
          'Unknown text at "$text".');
    }

    if (newRange.min != null) {
      if (min == null || newRange.min! > min) {
        min = newRange.min;
        includeMin = newRange.includeMin;
      } else if (newRange.min == min && !newRange.includeMin) {
        includeMin = false;
      }
    }

    if (newRange.max != null) {
      if (max == null || newRange.max! < max) {
        max = newRange.max;
        includeMax = newRange.includeMax;
      } else if (newRange.max == max && !newRange.includeMax) {
        includeMax = false;
      }
    }
  }

  if (min == null && max == null) {
    throw const FormatException('Cannot parse an empty string.');
  }

  if (min != null && max != null) {
    if (min > max) return PackageVersionNumberGeneralLibraryConstraint.empty;
    if (min == max) {
      if (includeMin && includeMax) return min;
      return PackageVersionNumberGeneralLibraryConstraint.empty;
    }
  }

  return PackageVersionNumberGeneralLibraryRange(
      min: min, includeMin: includeMin, max: max, includeMax: includeMax);
}