ProjectVersion.parse constructor

ProjectVersion.parse(
  1. String input
)

Parses a Flutter version string like 1.8.2+42 or 1.8.2 or 2.0.0-rc.1+100.

Throws ValidationException if the version string is malformed or invalid.

Implementation

factory ProjectVersion.parse(String input) {
  final trimmed = input.trim();
  if (trimmed.isEmpty) {
    throw const ValidationException('Version string cannot be empty.');
  }

  String versionPart = trimmed;
  int? buildNum;

  if (trimmed.contains('+')) {
    final parts = trimmed.split('+');
    if (parts.length > 2) {
      throw ValidationException(
        'Invalid version string format: "$input" (multiple "+" characters).',
      );
    }
    versionPart = parts[0];
    final buildStr = parts[1];
    if (buildStr.isEmpty) {
      throw ValidationException(
        'Invalid version string format: "$input" (missing build number after "+").',
      );
    }
    buildNum = int.tryParse(buildStr);
    if (buildNum == null || buildNum < 0) {
      throw ValidationException(
        'Invalid build number in version: "$buildStr". Must be a non-negative integer.',
      );
    }
  }

  String semverMain = versionPart;
  String? preReleasePart;

  if (versionPart.contains('-')) {
    final dashIndex = versionPart.indexOf('-');
    semverMain = versionPart.substring(0, dashIndex);
    preReleasePart = versionPart.substring(dashIndex + 1);
    if (preReleasePart.isEmpty) {
      throw ValidationException(
        'Invalid version string format: "$input" (missing pre-release identifier after "-").',
      );
    }
  }

  final semverComponents = semverMain.split('.');
  if (semverComponents.length != 3) {
    throw ValidationException(
      'Invalid version format: "$input". Expected "major.minor.patch[+buildNumber]" (e.g. 1.8.2+42).',
    );
  }

  final major = int.tryParse(semverComponents[0]);
  final minor = int.tryParse(semverComponents[1]);
  final patch = int.tryParse(semverComponents[2]);

  if (major == null ||
      major < 0 ||
      minor == null ||
      minor < 0 ||
      patch == null ||
      patch < 0) {
    throw ValidationException(
        'Version numbers must be non-negative integers: "$input".');
  }

  return ProjectVersion(
    major: major,
    minor: minor,
    patch: patch,
    preRelease: preReleasePart,
    buildNumber: buildNum,
  );
}