From a26ce0cccc51b111efcdae4528709f3ca181f09c Mon Sep 17 00:00:00 2001 From: MeltyPlayer Date: Thu, 25 Apr 2024 20:32:30 -0500 Subject: [PATCH] Fixed dumb bug where default enum values wouldn't be set right in generated readonly code. --- Schema Tests/readOnly/DefaultValueTests.cs | 42 +++++++++++++++++++- Schema Tests/readOnly/Enums.cs | 11 +++++ Schema/src/binary/parser/TypeInfo.cs | 2 +- Schema/src/readOnly/ReadOnlyTypeGenerator.cs | 42 ++++++++++++-------- Schema/src/util/symbols/SymbolTypeUtil.cs | 2 +- Schema/src/util/symbols/TypeSymbolUtil.cs | 25 ++++++++++-- 6 files changed, 101 insertions(+), 23 deletions(-) create mode 100644 Schema Tests/readOnly/Enums.cs diff --git a/Schema Tests/readOnly/DefaultValueTests.cs b/Schema Tests/readOnly/DefaultValueTests.cs index cac79e4..d7b4323 100644 --- a/Schema Tests/readOnly/DefaultValueTests.cs +++ b/Schema Tests/readOnly/DefaultValueTests.cs @@ -5,9 +5,9 @@ namespace schema.readOnly { internal class DefaultValueTests { [Test] + [TestCase("null")] [TestCase("false")] [TestCase("true")] - [TestCase("null")] public void TestSupportsDefaultBools(string boolValue) { ReadOnlyGeneratorTestUtil.AssertGenerated( $$""" @@ -36,10 +36,10 @@ public interface IReadOnlyWrapper { } [Test] + [TestCase("null")] [TestCase("0")] [TestCase("-123")] [TestCase("123")] - [TestCase("null")] public void TestSupportsDefaultInts(string intValue) { ReadOnlyGeneratorTestUtil.AssertGenerated( $$""" @@ -66,5 +66,43 @@ public interface IReadOnlyWrapper { """); } + + [Test] + [TestCase("null", "null")] + [TestCase("SomeType.FOO", "(other.SomeType) 123")] + public void + TestSupportsDefaultEnums(string enumValue, string readonlyValue) { + ReadOnlyGeneratorTestUtil.AssertGenerated( + $$""" + using schema.readOnly; + using foo.bar.other; + + namespace foo.bar.other { + public enum SomeType { + FOO = 123, + } + } + + namespace foo.bar { + [GenerateReadOnly] + public partial interface IWrapper { + [Const] + public void Foo(SomeType? value = {{enumValue}}); + } + } + """, + $$""" + namespace foo.bar { + public partial interface IWrapper : IReadOnlyWrapper { + void IReadOnlyWrapper.Foo(other.SomeType? value) => Foo(value); + } + + public interface IReadOnlyWrapper { + public void Foo(other.SomeType? value = {{readonlyValue}}); + } + } + + """); + } } } \ No newline at end of file diff --git a/Schema Tests/readOnly/Enums.cs b/Schema Tests/readOnly/Enums.cs new file mode 100644 index 0000000..d03b40e --- /dev/null +++ b/Schema Tests/readOnly/Enums.cs @@ -0,0 +1,11 @@ +namespace schema.readOnly { + internal enum SomeEnum { + FOO = 123, + } + + [GenerateReadOnly] + internal partial interface ISomeWrapper { + [Const] + void Foo(SomeEnum? bar = SomeEnum.FOO); + } +} \ No newline at end of file diff --git a/Schema/src/binary/parser/TypeInfo.cs b/Schema/src/binary/parser/TypeInfo.cs index 05658f2..e83ed1b 100644 --- a/Schema/src/binary/parser/TypeInfo.cs +++ b/Schema/src/binary/parser/TypeInfo.cs @@ -277,7 +277,7 @@ private void ParseNullable_(ref ITypeSymbol typeSymbol, Asserts.True(typeSymbol.IsGeneric(out _, out var genericArguments)); typeSymbol = genericArguments.ToArray()[0]; isNullable = true; - } else if (typeSymbol.IsNullable()) { + } else if (typeSymbol.IsNullable(out _)) { isNullable = true; } } diff --git a/Schema/src/readOnly/ReadOnlyTypeGenerator.cs b/Schema/src/readOnly/ReadOnlyTypeGenerator.cs index a2c1f46..bb39133 100644 --- a/Schema/src/readOnly/ReadOnlyTypeGenerator.cs +++ b/Schema/src/readOnly/ReadOnlyTypeGenerator.cs @@ -342,27 +342,37 @@ var isIndexer .Write(" ") .Write(parameterSymbol.Name.EscapeKeyword()); + + if (interfaceName == null && parameterSymbol.HasExplicitDefaultValue) { + var defaultValueType = parameterSymbol.Type.UnwrapNullable(); + cbsb.Write(" = "); var explicitDefaultValue = parameterSymbol.ExplicitDefaultValue; - switch (explicitDefaultValue) { - case null: - cbsb.Write("null"); - break; - case char: - cbsb.Write($"'{explicitDefaultValue}'"); - break; - case string: - cbsb.Write($"\"{explicitDefaultValue}\""); - break; - case bool boolValue: - cbsb.Write(boolValue ? "true" : "false"); - break; - default: - cbsb.Write(explicitDefaultValue.ToString()); - break; + if (defaultValueType.IsEnum(out _) && + explicitDefaultValue != null) { + cbsb.Write( + $"({typeSymbol.GetQualifiedNameFromCurrentSymbol(defaultValueType)}) {explicitDefaultValue}"); + } else { + switch (explicitDefaultValue) { + case null: + cbsb.Write("null"); + break; + case char: + cbsb.Write($"'{explicitDefaultValue}'"); + break; + case string: + cbsb.Write($"\"{explicitDefaultValue}\""); + break; + case bool boolValue: + cbsb.Write(boolValue ? "true" : "false"); + break; + default: + cbsb.Write(explicitDefaultValue.ToString()); + break; + } } } } diff --git a/Schema/src/util/symbols/SymbolTypeUtil.cs b/Schema/src/util/symbols/SymbolTypeUtil.cs index bc377d2..1dd3bd4 100644 --- a/Schema/src/util/symbols/SymbolTypeUtil.cs +++ b/Schema/src/util/symbols/SymbolTypeUtil.cs @@ -142,7 +142,7 @@ public static string GetQualifiedNameFromCurrentSymbol( $"{sourceSymbol.GetQualifiedNameFromCurrentSymbol(elementType, null, convertName, getNamespaceParts)}[]"; } - if (referencedSymbol.IsNullable()) { + if (referencedSymbol.IsNullable(out _)) { if (referencedSymbol.IsType(typeof(Nullable<>))) { var referencedNamedTypeSymbol = Asserts.AsA(referencedSymbol); diff --git a/Schema/src/util/symbols/TypeSymbolUtil.cs b/Schema/src/util/symbols/TypeSymbolUtil.cs index 6aba9d2..db0613e 100644 --- a/Schema/src/util/symbols/TypeSymbolUtil.cs +++ b/Schema/src/util/symbols/TypeSymbolUtil.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Microsoft.CodeAnalysis; @@ -15,8 +16,26 @@ public static bool IsArray(this ITypeSymbol typeSymbol, return false; } - public static bool IsNullable(this ITypeSymbol typeSymbol) - => typeSymbol.NullableAnnotation == NullableAnnotation.Annotated; + public static ITypeSymbol UnwrapNullable(this ITypeSymbol typeSymbol) + => typeSymbol.IsNullable(out var nullableType) + ? nullableType + : typeSymbol; + + public static bool IsNullable(this ITypeSymbol typeSymbol, + out ITypeSymbol nullableType) { + if (typeSymbol.IsType(typeof(Nullable<>))) { + nullableType = (typeSymbol as INamedTypeSymbol).TypeArguments[0]; + return true; + } + + if (typeSymbol.NullableAnnotation == NullableAnnotation.Annotated) { + nullableType = typeSymbol.OriginalDefinition; + return true; + } + + nullableType = default; + return false; + } public static IEnumerable GetBaseTypes( this ISymbol symbol) {