Skip to content

Commit

Permalink
Implement Parse and TryParse static methods on Version and Range. (#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
perfectsquircle authored Sep 21, 2020
1 parent 00c1ecb commit fd0934d
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 11 deletions.
56 changes: 48 additions & 8 deletions src/SemVer/Range.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ public class Range : IEquatable<Range>
/// <param name="rangeSpec">The range specification string.</param>
/// <param name="loose">When true, be more forgiving of some invalid version specifications.</param>
/// <exception cref="System.ArgumentException">Thrown when the range specification is invalid.</exception>
public Range(string rangeSpec, bool loose=false)
public Range(string rangeSpec, bool loose = false)
{
_rangeSpec = rangeSpec;
var comparatorSetSpecs = rangeSpec.Split(new [] {"||"}, StringSplitOptions.None);
var comparatorSetSpecs = rangeSpec.Split(new[] { "||" }, StringSplitOptions.None);
_comparatorSets = comparatorSetSpecs.Select(s => new ComparatorSet(s)).ToArray();
}

Expand All @@ -49,7 +49,7 @@ public bool IsSatisfied(Version version)
/// <param name="versionString">The version to check.</param>
/// <param name="loose">When true, be more forgiving of some invalid version specifications.</param>
/// <returns>true if the range is satisfied by the version.</returns>
public bool IsSatisfied(string versionString, bool loose=false)
public bool IsSatisfied(string versionString, bool loose = false)
{
try
{
Expand Down Expand Up @@ -79,7 +79,7 @@ public IEnumerable<Version> Satisfying(IEnumerable<Version> versions)
/// <param name="versions">The version strings to check.</param>
/// <param name="loose">When true, be more forgiving of some invalid version specifications.</param>
/// <returns>An IEnumerable of satisfying version strings.</returns>
public IEnumerable<string> Satisfying(IEnumerable<string> versions, bool loose=false)
public IEnumerable<string> Satisfying(IEnumerable<string> versions, bool loose = false)
{
return versions.Where(v => IsSatisfied(v, loose));
}
Expand All @@ -100,7 +100,7 @@ public Version MaxSatisfying(IEnumerable<Version> versions)
/// <param name="versionStrings">The version strings to select from.</param>
/// <param name="loose">When true, be more forgiving of some invalid version specifications.</param>
/// <returns>The maximum satisfying version string, or null if no versions satisfied this range.</returns>
public string MaxSatisfying(IEnumerable<string> versionStrings, bool loose=false)
public string MaxSatisfying(IEnumerable<string> versionStrings, bool loose = false)
{
var versions = ValidVersions(versionStrings, loose);
var maxVersion = MaxSatisfying(versions);
Expand Down Expand Up @@ -180,7 +180,7 @@ public override int GetHashCode()
/// <param name="versionString">The version to check.</param>
/// <param name="loose">When true, be more forgiving of some invalid version specifications.</param>
/// <returns>true if the range is satisfied by the version.</returns>
public static bool IsSatisfied(string rangeSpec, string versionString, bool loose=false)
public static bool IsSatisfied(string rangeSpec, string versionString, bool loose = false)
{
var range = new Range(rangeSpec);
return range.IsSatisfied(versionString);
Expand All @@ -194,7 +194,7 @@ public static bool IsSatisfied(string rangeSpec, string versionString, bool loos
/// <param name="versions">The version strings to check.</param>
/// <param name="loose">When true, be more forgiving of some invalid version specifications.</param>
/// <returns>An IEnumerable of satisfying version strings.</returns>
public static IEnumerable<string> Satisfying(string rangeSpec, IEnumerable<string> versions, bool loose=false)
public static IEnumerable<string> Satisfying(string rangeSpec, IEnumerable<string> versions, bool loose = false)
{
var range = new Range(rangeSpec);
return range.Satisfying(versions);
Expand All @@ -207,12 +207,52 @@ public static IEnumerable<string> Satisfying(string rangeSpec, IEnumerable<strin
/// <param name="versionStrings">The version strings to select from.</param>
/// <param name="loose">When true, be more forgiving of some invalid version specifications.</param>
/// <returns>The maximum satisfying version string, or null if no versions satisfied this range.</returns>
public static string MaxSatisfying(string rangeSpec, IEnumerable<string> versionStrings, bool loose=false)
public static string MaxSatisfying(string rangeSpec, IEnumerable<string> versionStrings, bool loose = false)
{
var range = new Range(rangeSpec);
return range.MaxSatisfying(versionStrings);
}

/// <summary>
/// Construct a new range from a range specification.
/// </summary>
/// <param name="rangeSpec">The range specification string.</param>
/// <param name="loose">When true, be more forgiving of some invalid version specifications.</param>
/// <exception cref="System.ArgumentException">Thrown when the range specification is invalid.</exception>
/// <returns>The Range</returns>
public static Range Parse(string rangeSpec, bool loose = false)
=> new Range(rangeSpec, loose);

/// <summary>
/// Try to construct a new range from a range specification.
/// </summary>
/// <param name="rangeSpec">The range specification string.</param>
/// <param name="result">The Range, or null when parse fails.</param>
/// <returns>A boolean indicating success of the parse operation.</returns>
public static bool TryParse(string rangeSpec, out Range result)
=> TryParse(rangeSpec, loose: false, out result);

/// <summary>
/// Try to construct a new range from a range specification.
/// </summary>
/// <param name="rangeSpec">The range specification string.</param>
/// <param name="loose">When true, be more forgiving of some invalid version specifications.</param>
/// <param name="result">The Range, or null when parse fails.</param>
/// <returns>A boolean indicating success of the parse operation.</returns>
public static bool TryParse(string rangeSpec, bool loose, out Range result)
{
try
{
result = Parse(rangeSpec, loose);
return true;
}
catch
{
result = null;
return false;
}
}

private IEnumerable<Version> ValidVersions(IEnumerable<string> versionStrings, bool loose)
{
foreach (var v in versionStrings)
Expand Down
48 changes: 45 additions & 3 deletions src/SemVer/Version.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class Version : IComparable<Version>, IComparable, IEquatable<Version>
/// <summary>
/// The build string, or null for no build version.
/// </summary>
public string Build { get {return _build; } }
public string Build { get { return _build; } }

private static Regex strictRegex = new Regex(@"^
\s*v?
Expand Down Expand Up @@ -74,7 +74,7 @@ public class Version : IComparable<Version>, IComparable, IEquatable<Version>
/// <param name="input">The version string.</param>
/// <param name="loose">When true, be more forgiving of some invalid version specifications.</param>
/// <exception cref="System.ArgumentException">Thrown when the version string is invalid.</exception>
public Version(string input, bool loose=false)
public Version(string input, bool loose = false)
{
_inputString = input;

Expand Down Expand Up @@ -213,7 +213,7 @@ public int CompareTo(object obj)
throw new ArgumentException("Object is not a Version");
}
}

// Implement IComparable<Version>
public int CompareTo(Version other)
{
Expand Down Expand Up @@ -245,6 +245,48 @@ public override bool Equals(object other)
return Equals(other as Version);
}

// Static convenience methods

/// <summary>
/// Construct a new semantic version from a version string.
/// </summary>
/// <param name="input">The version string.</param>
/// <param name="loose">When true, be more forgiving of some invalid version specifications.</param>
/// <exception cref="System.ArgumentException">Thrown when the version string is invalid.</exception>
/// <returns>The Version</returns>
public static Version Parse(string input, bool loose = false)
=> new Version(input, loose);

/// <summary>
/// Try to construct a new semantic version from a version string.
/// </summary>
/// <param name="input">The version string.</param>
/// <param name="result">The Version, or null when parse fails.</param>
/// <returns>A boolean indicating success of the parse operation.</returns>
public static bool TryParse(string input, out Version result)
=> TryParse(input, loose: false, out result);

/// <summary>
/// Try to construct a new semantic version from a version string.
/// </summary>
/// <param name="input">The version string.</param>
/// <param name="loose">When true, be more forgiving of some invalid version specifications.</param>
/// <param name="result">The Version, or null when parse fails.</param>
/// <returns>A boolean indicating success of the parse operation.</returns>
public static bool TryParse(string input, bool loose, out Version result)
{
try
{
result = Parse(input, loose);
return true;
}
catch
{
result = null;
return false;
}
}

public static bool operator ==(Version a, Version b)
{
if (ReferenceEquals(a, null))
Expand Down
53 changes: 53 additions & 0 deletions test/SemVer.Tests/TryParse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using Xunit;

namespace SemVer.Tests
{
public class TryParse
{
[Theory]
[InlineData("1.0.0", false, true)]
[InlineData("v 1.2.3", true, true)]
[InlineData("Not SemVer", false, false)]
public void VersionTryParse(string input, bool loose, bool expectedResult)
{
//Given

//When
var success = Version.TryParse(input, loose, out var version);

//Then
Assert.Equal(expectedResult, success);
if (success)
{
Assert.NotNull(version);
}
else
{
Assert.Null(version);
}
}


[Theory]
[InlineData("~1.0.0", false, true)]
[InlineData("< 1", true, true)]
[InlineData("Not SemVer Range", false, false)]
public void RangeTryParse(string rangeSpec, bool loose, bool expectedResult)
{
//Given

//When
var success = Range.TryParse(rangeSpec, loose, out var range);

//Then
Assert.Equal(expectedResult, success);
if (success)
{
Assert.NotNull(range);
}
else {
Assert.Null(range);
}
}
}
}

0 comments on commit fd0934d

Please sign in to comment.