From c92acb10deb50d283614392a55c693f1e0f5c508 Mon Sep 17 00:00:00 2001 From: Alex McAuliffe Date: Wed, 17 Aug 2022 11:38:20 +0100 Subject: [PATCH] IsValueGetter is false for Nullables (#132) This is because nullable is technically a struct (which is a value type) but is able to have no value for its inner and so be 'null Co-authored-by: Alex McAuliffe --- .../Contexts/CompilerContext.cs | 4 ++-- src/Stubble.Compilation/Helpers/TypeHelper.cs | 24 +++++++++++-------- .../InterpolationTokenRenderer.cs | 6 ++--- .../Stubble.Test.Shared/Spec/Spec.Sections.cs | 8 +++++++ test/Stubble.Test.Shared/Spec/SpecTest.cs | 2 -- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/Stubble.Compilation/Contexts/CompilerContext.cs b/src/Stubble.Compilation/Contexts/CompilerContext.cs index df3198d..d0f0eb4 100644 --- a/src/Stubble.Compilation/Contexts/CompilerContext.cs +++ b/src/Stubble.Compilation/Contexts/CompilerContext.cs @@ -200,9 +200,9 @@ public Expression GetTruthyExpression(Expression value) var parameter = Expression.Parameter(value.Type, "checkThis"); var checks = new List>(); - if (!parameter.Type.GetIsValueType()) + if (parameter.Type.IsNullable()) { - checks.Add(Tuple.Create(Expression.Equal(parameter, Expression.Constant(null)), FalseConstant)); + checks.Add(Tuple.Create(Expression.Equal(parameter, Expression.Default(parameter.Type)), FalseConstant)); } if (CompilerSettings.TruthyChecks.TryGetValue(parameter.Type, out var typeTruthyChecks)) diff --git a/src/Stubble.Compilation/Helpers/TypeHelper.cs b/src/Stubble.Compilation/Helpers/TypeHelper.cs index b8a5422..dd51f9b 100644 --- a/src/Stubble.Compilation/Helpers/TypeHelper.cs +++ b/src/Stubble.Compilation/Helpers/TypeHelper.cs @@ -54,18 +54,22 @@ public static Type GetElementTypeOfIEnumerable(this Type type) } /// - /// Returns if the type is a value type or not + /// Returns if the provided type is nullable or not. /// - /// The type to evaluate - /// If the type is a value type or not - [MethodImpl(MethodImplOptionPortable.AggressiveInlining)] - public static bool GetIsValueType(this Type type) + /// The type to evaluate. + /// If the type is nullable or not. + public static bool IsNullable(this Type type) { -#if NETSTANDARD1_3 - return type.GetTypeInfo().IsValueType; -#else - return type.IsValueType; -#endif + if (type.IsValueType is false) + { + return true; + } + else if (Nullable.GetUnderlyingType(type) is not null) + { + return true; + } + + return false; } } } diff --git a/src/Stubble.Compilation/Renderers/TokenRenderers/InterpolationTokenRenderer.cs b/src/Stubble.Compilation/Renderers/TokenRenderers/InterpolationTokenRenderer.cs index e88814c..1fa369a 100644 --- a/src/Stubble.Compilation/Renderers/TokenRenderers/InterpolationTokenRenderer.cs +++ b/src/Stubble.Compilation/Renderers/TokenRenderers/InterpolationTokenRenderer.cs @@ -40,9 +40,9 @@ protected override void Write(CompilationRenderer renderer, InterpolationToken o var formattedToString = expression.Type .GetMethod(nameof(object.ToString), formatProviderTypeArgs); - var item = expression.Type.GetIsValueType() - ? expression - : Expression.Coalesce(expression, Expression.Constant(string.Empty)); + var item = expression.Type.IsNullable() + ? Expression.Coalesce(expression, Expression.Constant(string.Empty)) + : expression; stringExpression = formattedToString is object ? Expression.Call(item, formattedToString, Expression.Constant(context.CompilationSettings.CultureInfo)) diff --git a/test/Stubble.Test.Shared/Spec/Spec.Sections.cs b/test/Stubble.Test.Shared/Spec/Spec.Sections.cs index 8282e68..e7b1ee9 100644 --- a/test/Stubble.Test.Shared/Spec/Spec.Sections.cs +++ b/test/Stubble.Test.Shared/Spec/Spec.Sections.cs @@ -290,6 +290,14 @@ public static partial class Specs Template = @"|{{# boolean }}={{/ boolean }}|", Expected = @"|=|", Partials = null + }, + new SpecTest { + Name = @"Null ints are not truthy", + Desc = @"Nullable items should be truthy checked", + Data = new { Count = (int?)null }, + Template = @"""{{#Count}}Should not be visible{{/Count}}""", + Expected = @"""""", + Partials = null }, }.Select(s => new object[] { s }); } diff --git a/test/Stubble.Test.Shared/Spec/SpecTest.cs b/test/Stubble.Test.Shared/Spec/SpecTest.cs index 27d6939..94c4c5b 100644 --- a/test/Stubble.Test.Shared/Spec/SpecTest.cs +++ b/test/Stubble.Test.Shared/Spec/SpecTest.cs @@ -3,11 +3,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Globalization; -using Xunit.Abstractions; namespace Stubble.Test.Shared.Spec {