From 8b01d68824154aa3155e8311ed20ab8b1d804858 Mon Sep 17 00:00:00 2001 From: Tristan Milnthorp Date: Tue, 8 Sep 2020 13:21:34 -0400 Subject: [PATCH 1/4] Add failing tests --- UnitsNet.Tests/UnitAbbreviationsCacheTests.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs b/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs index 5103231a36..67b2854192 100644 --- a/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs +++ b/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs @@ -296,6 +296,25 @@ public void MapUnitToDefaultAbbreviation_GivenCustomAbbreviation_SetsAbbreviatio Assert.Equal("1 m^2", Area.FromSquareMeters(1).ToString(newZealandCulture)); } + [Fact] + public void MapUnitOverrideTest() + { + UnitAbbreviationsCache.Default.MapUnitToDefaultAbbreviation(MassFlowUnit.GramPerSecond, NorwegianCulture, "grams/second"); + Assert.Equal(MassFlow.FromPoundsPerSecond(10), Quantity.Parse( NorwegianCulture, typeof( MassFlow ), "10 lb/s" )); + } + + [Fact] + public void MapUnitToDefaultAbbreviation_AddsNewUnitAsAdditionalOverride() + { + var cache = new UnitAbbreviationsCache(); + var abbreviationsBefore = cache.GetUnitAbbreviations(MassFlowUnit.GramPerSecond, NorwegianCulture); + + cache.MapUnitToDefaultAbbreviation(MassFlowUnit.GramPerSecond, NorwegianCulture, "grams/second"); + + var abbreviationsAfter = cache.GetUnitAbbreviations(MassFlowUnit.GramPerSecond, NorwegianCulture); + Assert.Equal(abbreviationsBefore.Length + 1, abbreviationsAfter.Length); + } + /// /// Convenience method to the proper culture parameter type. /// From a625c7fa4256d7c2c3659e634c233230904a356e Mon Sep 17 00:00:00 2001 From: Tristan Milnthorp Date: Tue, 8 Sep 2020 15:28:46 -0400 Subject: [PATCH 2/4] Wrap GetUnitsForAbbreviation in UnitAbbreviationsCache to allow for fallback/override behavior --- UnitsNet/CustomCode/UnitAbbreviationsCache.cs | 34 ++++++++++++++++--- UnitsNet/CustomCode/UnitParser.cs | 18 ++++------ .../CustomCode/UnitValueAbbreviationLookup.cs | 1 - 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/UnitsNet/CustomCode/UnitAbbreviationsCache.cs b/UnitsNet/CustomCode/UnitAbbreviationsCache.cs index a0b52ff101..dbb84304de 100644 --- a/UnitsNet/CustomCode/UnitAbbreviationsCache.cs +++ b/UnitsNet/CustomCode/UnitAbbreviationsCache.cs @@ -276,9 +276,11 @@ public string[] GetUnitAbbreviations(Type unitType, int unitValue, IFormatProvid if(!TryGetUnitValueAbbreviationLookup(unitType, formatProvider, out var lookup)) return formatProvider != FallbackCulture ? GetUnitAbbreviations(unitType, unitValue, FallbackCulture) : new string[] { }; - var abbreviations = lookup!.GetAbbreviationsForUnit(unitValue); - if(abbreviations.Count == 0) - return formatProvider != FallbackCulture ? GetUnitAbbreviations(unitType, unitValue, FallbackCulture) : new string[] { }; + var abbreviations = new HashSet(); + abbreviations.UnionWith(lookup!.GetAbbreviationsForUnit(unitValue)); + + if(formatProvider != FallbackCulture) + abbreviations.UnionWith(GetUnitAbbreviations(unitType, unitValue, FallbackCulture)); return abbreviations.ToArray(); } @@ -297,10 +299,32 @@ public string[] GetAllUnitAbbreviationsForQuantity(Type unitEnumType, IFormatPro if(!TryGetUnitValueAbbreviationLookup(unitEnumType, formatProvider, out var lookup)) return formatProvider != FallbackCulture ? GetAllUnitAbbreviationsForQuantity(unitEnumType, FallbackCulture) : new string[] { }; - return lookup!.GetAllUnitAbbreviationsForQuantity(); + var allAbbreviations = new HashSet(); + allAbbreviations.UnionWith(lookup!.GetAllUnitAbbreviationsForQuantity()); + + if(formatProvider != FallbackCulture) + allAbbreviations.UnionWith(GetAllUnitAbbreviationsForQuantity(unitEnumType, FallbackCulture)); + + return allAbbreviations.ToArray(); + } + + internal List GetUnitsForAbbreviation(Type unitType, IFormatProvider? formatProvider, string abbreviation, bool ignoreCase) + { + formatProvider = formatProvider ?? CultureInfo.CurrentUICulture; + + if(!TryGetUnitValueAbbreviationLookup(unitType, formatProvider, out var lookup)) + return formatProvider != FallbackCulture ? GetUnitsForAbbreviation(unitType, FallbackCulture, abbreviation, ignoreCase) : new List(); + + var units = new HashSet(); + units.UnionWith(lookup!.GetUnitsForAbbreviation(abbreviation, ignoreCase)); + + if(formatProvider != FallbackCulture) + units.UnionWith(GetUnitsForAbbreviation(unitType, FallbackCulture, abbreviation, ignoreCase)); + + return units.ToList(); } - internal bool TryGetUnitValueAbbreviationLookup(Type unitType, IFormatProvider? formatProvider, out UnitValueAbbreviationLookup? unitToAbbreviations) + private bool TryGetUnitValueAbbreviationLookup(Type unitType, IFormatProvider? formatProvider, out UnitValueAbbreviationLookup? unitToAbbreviations) { unitToAbbreviations = null; diff --git a/UnitsNet/CustomCode/UnitParser.cs b/UnitsNet/CustomCode/UnitParser.cs index 2becb1fd4d..6f5e71403f 100644 --- a/UnitsNet/CustomCode/UnitParser.cs +++ b/UnitsNet/CustomCode/UnitParser.cs @@ -72,20 +72,17 @@ public Enum Parse([NotNull] string unitAbbreviation, Type unitType, IFormatProvi if (unitAbbreviation == null) throw new ArgumentNullException(nameof(unitAbbreviation)); unitAbbreviation = unitAbbreviation.Trim(); - if(!_unitAbbreviationsCache.TryGetUnitValueAbbreviationLookup(unitType, formatProvider, out var abbreviations)) - throw new UnitNotFoundException($"No abbreviations defined for unit type [{unitType}] for culture [{formatProvider}]."); - - var unitIntValues = abbreviations!.GetUnitsForAbbreviation(unitAbbreviation, ignoreCase: true); + var unitIntValues = _unitAbbreviationsCache.GetUnitsForAbbreviation(unitType, formatProvider, unitAbbreviation, ignoreCase: true); if (unitIntValues.Count == 0) { unitAbbreviation = NormalizeUnitString(unitAbbreviation); - unitIntValues = abbreviations.GetUnitsForAbbreviation(unitAbbreviation, ignoreCase: true); + unitIntValues = _unitAbbreviationsCache.GetUnitsForAbbreviation(unitType, formatProvider, unitAbbreviation, ignoreCase: true); } // Narrow the search if too many hits, for example Megabar "Mbar" and Millibar "mbar" need to be distinguished if (unitIntValues.Count > 1) - unitIntValues = abbreviations.GetUnitsForAbbreviation(unitAbbreviation, ignoreCase: false); + unitIntValues = _unitAbbreviationsCache.GetUnitsForAbbreviation(unitType, formatProvider, unitAbbreviation, ignoreCase: false); switch (unitIntValues.Count) { @@ -197,20 +194,17 @@ public bool TryParse(string? unitAbbreviation, Type unitType, IFormatProvider? f unitAbbreviation = unitAbbreviation.Trim(); unit = default; - if(!_unitAbbreviationsCache.TryGetUnitValueAbbreviationLookup(unitType, formatProvider, out var abbreviations)) - return false; - - var unitIntValues = abbreviations!.GetUnitsForAbbreviation(unitAbbreviation, ignoreCase: true); + var unitIntValues = _unitAbbreviationsCache.GetUnitsForAbbreviation(unitType, formatProvider, unitAbbreviation, ignoreCase: true); if (unitIntValues.Count == 0) { unitAbbreviation = NormalizeUnitString(unitAbbreviation); - unitIntValues = abbreviations.GetUnitsForAbbreviation(unitAbbreviation, ignoreCase: true); + unitIntValues = _unitAbbreviationsCache.GetUnitsForAbbreviation(unitType, formatProvider, unitAbbreviation, ignoreCase: true); } // Narrow the search if too many hits, for example Megabar "Mbar" and Millibar "mbar" need to be distinguished if (unitIntValues.Count > 1) - unitIntValues = abbreviations.GetUnitsForAbbreviation(unitAbbreviation, ignoreCase: false); + unitIntValues = _unitAbbreviationsCache.GetUnitsForAbbreviation( unitType, formatProvider, unitAbbreviation, ignoreCase: false); if(unitIntValues.Count != 1) return false; diff --git a/UnitsNet/CustomCode/UnitValueAbbreviationLookup.cs b/UnitsNet/CustomCode/UnitValueAbbreviationLookup.cs index a82d3f7faf..089770606a 100644 --- a/UnitsNet/CustomCode/UnitValueAbbreviationLookup.cs +++ b/UnitsNet/CustomCode/UnitValueAbbreviationLookup.cs @@ -73,7 +73,6 @@ internal void Add(int unit, string abbreviation, bool setAsDefault = false) abbreviationsForUnit.Insert(0, abbreviation); else abbreviationsForUnit.Add(abbreviation); - } } } From bc5f8c40d3e8a1cff846aeba39ad48a09ca8e0de Mon Sep 17 00:00:00 2001 From: Tristan Milnthorp Date: Tue, 8 Sep 2020 15:31:13 -0400 Subject: [PATCH 3/4] Fix whitespace for code consistency --- UnitsNet.Tests/UnitAbbreviationsCacheTests.cs | 2 +- UnitsNet/CustomCode/UnitParser.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs b/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs index 67b2854192..4b5e5ca0b6 100644 --- a/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs +++ b/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs @@ -300,7 +300,7 @@ public void MapUnitToDefaultAbbreviation_GivenCustomAbbreviation_SetsAbbreviatio public void MapUnitOverrideTest() { UnitAbbreviationsCache.Default.MapUnitToDefaultAbbreviation(MassFlowUnit.GramPerSecond, NorwegianCulture, "grams/second"); - Assert.Equal(MassFlow.FromPoundsPerSecond(10), Quantity.Parse( NorwegianCulture, typeof( MassFlow ), "10 lb/s" )); + Assert.Equal(MassFlow.FromPoundsPerSecond(10), Quantity.Parse(NorwegianCulture, typeof(MassFlow), "10 lb/s")); } [Fact] diff --git a/UnitsNet/CustomCode/UnitParser.cs b/UnitsNet/CustomCode/UnitParser.cs index 6f5e71403f..9e8f95bcae 100644 --- a/UnitsNet/CustomCode/UnitParser.cs +++ b/UnitsNet/CustomCode/UnitParser.cs @@ -204,7 +204,7 @@ public bool TryParse(string? unitAbbreviation, Type unitType, IFormatProvider? f // Narrow the search if too many hits, for example Megabar "Mbar" and Millibar "mbar" need to be distinguished if (unitIntValues.Count > 1) - unitIntValues = _unitAbbreviationsCache.GetUnitsForAbbreviation( unitType, formatProvider, unitAbbreviation, ignoreCase: false); + unitIntValues = _unitAbbreviationsCache.GetUnitsForAbbreviation(unitType, formatProvider, unitAbbreviation, ignoreCase: false); if(unitIntValues.Count != 1) return false; From 5be4cf7052da175622f2e99e9d9fe12a67d31fd4 Mon Sep 17 00:00:00 2001 From: Tristan Milnthorp Date: Wed, 9 Sep 2020 11:20:54 -0400 Subject: [PATCH 4/4] Don't modify default UnitAbbreviationsCache in test --- UnitsNet.Tests/UnitAbbreviationsCacheTests.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs b/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs index 4b5e5ca0b6..5e83ae4d67 100644 --- a/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs +++ b/UnitsNet.Tests/UnitAbbreviationsCacheTests.cs @@ -297,10 +297,13 @@ public void MapUnitToDefaultAbbreviation_GivenCustomAbbreviation_SetsAbbreviatio } [Fact] - public void MapUnitOverrideTest() + public void MapUnitToDefaultAbbreviation_ParsesUsingDefaultString() { - UnitAbbreviationsCache.Default.MapUnitToDefaultAbbreviation(MassFlowUnit.GramPerSecond, NorwegianCulture, "grams/second"); - Assert.Equal(MassFlow.FromPoundsPerSecond(10), Quantity.Parse(NorwegianCulture, typeof(MassFlow), "10 lb/s")); + var cache = new UnitAbbreviationsCache(); + cache.MapUnitToDefaultAbbreviation(MassFlowUnit.GramPerSecond, NorwegianCulture, "grams/second"); + + var parser = new QuantityParser(cache); + Assert.Equal(MassFlow.FromPoundsPerSecond(10), parser.Parse("10 lb/s", NorwegianCulture, MassFlow.From)); } [Fact]