From fa0c19d4f5e334d2d95b844245f2086ab19195f0 Mon Sep 17 00:00:00 2001 From: hadashiA Date: Sat, 3 Feb 2024 17:40:17 +0900 Subject: [PATCH] Fix compilation errors in .net8 with explicit static members --- sandbox/ConsoleApp/ConsoleApp.csproj | 2 +- sandbox/FileGenerate/FileGenerate.csproj | 2 +- sandbox/FileGenerate/SimplePrimitive.cs | 9 +- .../FileGenerate.A.g.cs | 6 + .../FileGenerate.Aa.g.cs | 19 +- .../FileGenerate.Bb.g.cs | 4 +- .../FileGenerate.C.g.cs | 72 +----- .../FileGenerate.Cc.g.cs | 23 +- .../FileGenerate.D.g.cs | 219 ++++++++++++++++++ .../UnitOfAttribute.cs | 4 +- src/UnitGenerator/SourceGenerator.cs | 60 +++-- 11 files changed, 322 insertions(+), 98 deletions(-) create mode 100644 sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.D.g.cs diff --git a/sandbox/ConsoleApp/ConsoleApp.csproj b/sandbox/ConsoleApp/ConsoleApp.csproj index cc776ea..44dace4 100644 --- a/sandbox/ConsoleApp/ConsoleApp.csproj +++ b/sandbox/ConsoleApp/ConsoleApp.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net8.0 enable false diff --git a/sandbox/FileGenerate/FileGenerate.csproj b/sandbox/FileGenerate/FileGenerate.csproj index 3373f19..427bfd1 100644 --- a/sandbox/FileGenerate/FileGenerate.csproj +++ b/sandbox/FileGenerate/FileGenerate.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 true $(ProjectDir)..\Generated diff --git a/sandbox/FileGenerate/SimplePrimitive.cs b/sandbox/FileGenerate/SimplePrimitive.cs index a17c135..9b7e04e 100644 --- a/sandbox/FileGenerate/SimplePrimitive.cs +++ b/sandbox/FileGenerate/SimplePrimitive.cs @@ -1,4 +1,5 @@ -using UnitGenerator; +using System; +using UnitGenerator; namespace FileGenerate { @@ -11,12 +12,16 @@ public readonly partial struct A public readonly partial struct B { } - + [UnitOf(typeof(int), UnitGenerateOptions.Comparable | UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator | UnitGenerateOptions.ParseMethod)] public readonly partial struct C { } + [UnitOf(typeof(Guid), UnitGenerateOptions.Comparable | UnitGenerateOptions.ParseMethod)] + public readonly partial struct D + { + } [UnitOf] public readonly partial struct Aa diff --git a/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.A.g.cs b/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.A.g.cs index 1097a85..3918798 100644 --- a/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.A.g.cs +++ b/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.A.g.cs @@ -18,6 +18,7 @@ readonly partial struct A #endif #if NET8_0_OR_GREATER , IEqualityOperators + , IUtf8SpanFormattable #endif { readonly int value; @@ -83,6 +84,11 @@ public override int GetHashCode() public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) => ((ISpanFormattable)value).TryFormat(destination, out charsWritten, format, provider); #endif +#if NET8_0_OR_GREATER + public bool TryFormat (Span utf8Destination, out int bytesWritten, ReadOnlySpan format, IFormatProvider? provider) => + ((IUtf8SpanFormattable)value).TryFormat(utf8Destination, out bytesWritten, format, provider); +#endif + // Default private class ATypeConverter : System.ComponentModel.TypeConverter diff --git a/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.Aa.g.cs b/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.Aa.g.cs index f92ae9d..342d296 100644 --- a/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.Aa.g.cs +++ b/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.Aa.g.cs @@ -12,10 +12,14 @@ namespace FileGenerate [System.ComponentModel.TypeConverter(typeof(AaTypeConverter))] readonly partial struct Aa : IEquatable -#if NET7_0_OR_GREATER - , IEqualityOperators -#endif , IFormattable +#if NET6_0_OR_GREATER + , ISpanFormattable +#endif +#if NET8_0_OR_GREATER + , IEqualityOperators + , IUtf8SpanFormattable +#endif { readonly int value; @@ -76,6 +80,15 @@ public override int GetHashCode() public string ToString(string? format, IFormatProvider? formatProvider) => value.ToString(format, formatProvider); +#if NET6_0_OR_GREATER + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) => + ((ISpanFormattable)value).TryFormat(destination, out charsWritten, format, provider); +#endif +#if NET8_0_OR_GREATER + public bool TryFormat (Span utf8Destination, out int bytesWritten, ReadOnlySpan format, IFormatProvider? provider) => + ((IUtf8SpanFormattable)value).TryFormat(utf8Destination, out bytesWritten, format, provider); +#endif + // Default private class AaTypeConverter : System.ComponentModel.TypeConverter diff --git a/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.Bb.g.cs b/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.Bb.g.cs index 9d8b2ed..4930b5b 100644 --- a/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.Bb.g.cs +++ b/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.Bb.g.cs @@ -12,9 +12,9 @@ namespace FileGenerate [System.ComponentModel.TypeConverter(typeof(BbTypeConverter))] readonly partial struct Bb : IEquatable -#if NET7_0_OR_GREATER +#if NET8_0_OR_GREATER , IEqualityOperators -#endif +#endif { readonly string value; diff --git a/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.C.g.cs b/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.C.g.cs index 82b70d9..4b9461e 100644 --- a/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.C.g.cs +++ b/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.C.g.cs @@ -19,8 +19,6 @@ readonly partial struct C #endif #if NET7_0_OR_GREATER , IComparisonOperators - , IParsable - , ISpanParsable , IAdditionOperators , ISubtractionOperators , IMultiplyOperators @@ -32,7 +30,7 @@ readonly partial struct C #endif #if NET8_0_OR_GREATER , IEqualityOperators - , IUtf8SpanParsable + , IUtf8SpanFormattable #endif { readonly int value; @@ -98,6 +96,11 @@ public override int GetHashCode() public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) => ((ISpanFormattable)value).TryFormat(destination, out charsWritten, format, provider); #endif +#if NET8_0_OR_GREATER + public bool TryFormat (Span utf8Destination, out int bytesWritten, ReadOnlySpan format, IFormatProvider? provider) => + ((IUtf8SpanFormattable)value).TryFormat(utf8Destination, out bytesWritten, format, provider); +#endif + // UnitGenerateOptions.ParseMethod public static C Parse(string s) @@ -119,69 +122,6 @@ public static bool TryParse(string s, out C result) } } -#if NET7_0_OR_GREATER - public static C Parse(string s, IFormatProvider? provider) - { - return new C(int.Parse(s, provider)); - } - - public static bool TryParse(string s, IFormatProvider? provider, out C result) - { - if (int.TryParse(s, provider, out var r)) - { - result = new C(r); - return true; - } - else - { - result = default(C); - return false; - } - } -#endif - -#if NET7_0_OR_GREATER - public static C Parse(ReadOnlySpan s, IFormatProvider? provider) - { - return new C(int.Parse(s, provider)); - } - - public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, out C result) - { - if (int.TryParse(s, provider, out var r)) - { - result = new C(r); - return true; - } - else - { - result = default(C); - return false; - } - } -#endif - -#if NET8_0_OR_GREATER - public static C Parse(ReadOnlySpan utf8Text, IFormatProvider? provider) - { - return new C(int.Parse(utf8Text, provider)); - } - - public static bool TryParse(ReadOnlySpan utf8Text, IFormatProvider? provider, out C result) - { - if (int.TryParse(utf8Text, provider, out var r)) - { - result = new C(r); - return true; - } - else - { - result = default(C); - return false; - } - } -#endif - // UnitGenerateOptions.ArithmeticOperator public static C operator +(C x, C y) diff --git a/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.Cc.g.cs b/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.Cc.g.cs index 4d4a367..1191acd 100644 --- a/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.Cc.g.cs +++ b/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.Cc.g.cs @@ -12,15 +12,13 @@ namespace FileGenerate [System.ComponentModel.TypeConverter(typeof(CcTypeConverter))] readonly partial struct Cc : IEquatable -#if NET7_0_OR_GREATER - , IEqualityOperators -#endif , IComparable -#if NET7_0_OR_GREATER - , IComparisonOperators -#endif , IFormattable +#if NET6_0_OR_GREATER + , ISpanFormattable +#endif #if NET7_0_OR_GREATER + , IComparisonOperators , IAdditionOperators , ISubtractionOperators , IMultiplyOperators @@ -29,6 +27,10 @@ readonly partial struct Cc , IUnaryNegationOperators , IIncrementOperators , IDecrementOperators +#endif +#if NET8_0_OR_GREATER + , IEqualityOperators + , IUtf8SpanFormattable #endif { readonly int value; @@ -90,6 +92,15 @@ public override int GetHashCode() public string ToString(string? format, IFormatProvider? formatProvider) => value.ToString(format, formatProvider); +#if NET6_0_OR_GREATER + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) => + ((ISpanFormattable)value).TryFormat(destination, out charsWritten, format, provider); +#endif +#if NET8_0_OR_GREATER + public bool TryFormat (Span utf8Destination, out int bytesWritten, ReadOnlySpan format, IFormatProvider? provider) => + ((IUtf8SpanFormattable)value).TryFormat(utf8Destination, out bytesWritten, format, provider); +#endif + // UnitGenerateOptions.ArithmeticOperator public static Cc operator +(Cc x, Cc y) diff --git a/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.D.g.cs b/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.D.g.cs new file mode 100644 index 0000000..7bce5b1 --- /dev/null +++ b/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.D.g.cs @@ -0,0 +1,219 @@ +// +// THIS (.cs) FILE IS GENERATED BY UnitGenerator. DO NOT CHANGE IT. +// +#pragma warning disable CS8669 +using System; +using System.Globalization; +#if NET7_0_OR_GREATER +using System.Numerics; +#endif +namespace FileGenerate +{ + [System.ComponentModel.TypeConverter(typeof(DTypeConverter))] + readonly partial struct D + : IEquatable + , IComparable + , IFormattable +#if NET6_0_OR_GREATER + , ISpanFormattable +#endif +#if NET7_0_OR_GREATER + , IComparisonOperators +#endif +#if NET8_0_OR_GREATER + , IEqualityOperators + , IUtf8SpanFormattable +#endif + { + readonly System.Guid value; + + public System.Guid AsPrimitive() => value; + + public D(System.Guid value) + { + this.value = value; + } + + public static explicit operator System.Guid(D value) + { + return value.value; + } + + public static explicit operator D(System.Guid value) + { + return new D(value); + } + + public bool Equals(D other) + { + return value.Equals(other.value); + } + + public override bool Equals(object obj) + { + if (obj == null) return false; + var t = obj.GetType(); + if (t == typeof(D)) + { + return Equals((D)obj); + } + if (t == typeof(System.Guid)) + { + return value.Equals((System.Guid)obj); + } + + return value.Equals(obj); + } + + public static bool operator ==(D x, D y) + { + return x.value.Equals(y.value); + } + + public static bool operator !=(D x, D y) + { + return !x.value.Equals(y.value); + } + + public override int GetHashCode() + { + return value.GetHashCode(); + } + + public override string ToString() => value.ToString(); + + public string ToString(string? format, IFormatProvider? formatProvider) => value.ToString(format, formatProvider); + +#if NET6_0_OR_GREATER + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) => + ((ISpanFormattable)value).TryFormat(destination, out charsWritten, format, provider); +#endif +#if NET8_0_OR_GREATER + public bool TryFormat (Span utf8Destination, out int bytesWritten, ReadOnlySpan format, IFormatProvider? provider) => + ((IUtf8SpanFormattable)value).TryFormat(utf8Destination, out bytesWritten, format, provider); +#endif + + public static readonly D Empty = default(D); + + public static D New() + { + return new D(Guid.NewGuid()); + } + + public static D NewD() + { + return new D(Guid.NewGuid()); + } + + // UnitGenerateOptions.ParseMethod + + public static D Parse(string s) + { + return new D(System.Guid.Parse(s)); + } + + public static bool TryParse(string s, out D result) + { + if (System.Guid.TryParse(s, out var r)) + { + result = new D(r); + return true; + } + else + { + result = default(D); + return false; + } + } + + // UnitGenerateOptions.Comparable + + public int CompareTo(D other) + { + return value.CompareTo(other.value); + } + public static bool operator >(D x, D y) + { + return x.value > y.value; + } + + public static bool operator <(D x, D y) + { + return x.value < y.value; + } + + public static bool operator >=(D x, D y) + { + return x.value >= y.value; + } + + public static bool operator <=(D x, D y) + { + return x.value <= y.value; + } + + // Default + + private class DTypeConverter : System.ComponentModel.TypeConverter + { + private static readonly Type WrapperType = typeof(D); + private static readonly Type ValueType = typeof(System.Guid); + + public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == WrapperType || sourceType == ValueType) + { + return true; + } + + return base.CanConvertFrom(context, sourceType); + } + + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, Type destinationType) + { + if (destinationType == WrapperType || destinationType == ValueType) + { + return true; + } + + return base.CanConvertTo(context, destinationType); + } + + public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + { + if (value != null) + { + var t = value.GetType(); + if (t == typeof(D)) + { + return (D)value; + } + if (t == typeof(System.Guid)) + { + return new D((System.Guid)value); + } + } + + return base.ConvertFrom(context, culture, value); + } + + public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) + { + if (value is D wrappedValue) + { + if (destinationType == WrapperType) + { + return wrappedValue; + } + + if (destinationType == ValueType) + { + return wrappedValue.AsPrimitive(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + } +} diff --git a/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/UnitOfAttribute.cs b/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/UnitOfAttribute.cs index 1daf128..c26ebf5 100644 --- a/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/UnitOfAttribute.cs +++ b/sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/UnitOfAttribute.cs @@ -37,8 +37,8 @@ public UnitOfAttribute(UnitGenerateOptions options = UnitGenerateOptions.None) { this.Type = typeof(T); this.Options = options; -   } -    } + } + } #endif [Flags] diff --git a/src/UnitGenerator/SourceGenerator.cs b/src/UnitGenerator/SourceGenerator.cs index ffa0a13..468e8b1 100644 --- a/src/UnitGenerator/SourceGenerator.cs +++ b/src/UnitGenerator/SourceGenerator.cs @@ -49,7 +49,7 @@ public void Execute(GeneratorExecutionContext context) { var arg = attr.ArgumentList!.Arguments[i]; var expr = arg.Expression; - + var argName = arg.NameEquals?.Name.ToString(); switch (argName) { @@ -104,7 +104,7 @@ public void Execute(GeneratorExecutionContext context) if (typeSymbol == null) throw new Exception("can not get typeSymbol."); var source = GenerateType(typeSymbol, prop); - + var ns = typeSymbol.ContainingNamespace.IsGlobalNamespace ? null : typeSymbol.ContainingNamespace.ToDisplayString(); @@ -112,7 +112,7 @@ public void Execute(GeneratorExecutionContext context) var filename = ns == null ? $"{typeSymbol.Name}.g.cs" : $"{ns}.{typeSymbol.Name}.g.cs"; - + context.AddSource(filename, source); } } @@ -164,8 +164,8 @@ public UnitOfAttribute(UnitGenerateOptions options = UnitGenerateOptions.None) { this.Type = typeof(T); this.Options = options; -   } -    } + } + } #endif [Flags] @@ -276,7 +276,7 @@ namespace {{ns}} readonly partial struct {{unitTypeName}} : IEquatable<{{unitTypeName}}> """); - if (prop.HasFlag(UnitGenerateOptions.Comparable) && + if (prop.HasFlag(UnitGenerateOptions.Comparable) && !prop.HasFlag(UnitGenerateOptions.WithoutComparisonOperator)) { anyPlatformInterfaces.Add($"IComparable<{unitTypeName}>"); @@ -309,7 +309,7 @@ readonly partial struct {{unitTypeName}} net8Interfaces.Add($"IUtf8SpanParsable<{unitTypeName}>"); } } - + if (prop.HasFlag(UnitGenerateOptions.ArithmeticOperator)) { if (prop.HasArithmeticOperator(UnitArithmeticOperators.Addition)) @@ -360,7 +360,7 @@ readonly partial struct {{unitTypeName}} { sb.AppendLine("#endif"); } - + if (net7Interfaces.Count > 0) { sb.AppendLine("#if NET7_0_OR_GREATER"); @@ -373,7 +373,7 @@ readonly partial struct {{unitTypeName}} { sb.AppendLine("#endif"); } - + if (net8Interfaces.Count > 0) { sb.AppendLine("#if NET8_0_OR_GREATER"); @@ -417,11 +417,11 @@ readonly partial struct {{unitTypeName}} { sb.AppendLine($$""" private partial void Normalize(ref {{innerTypeName}} value); - + """); - + } - + if (prop.HasFlag(UnitGenerateOptions.Validate)) { sb.AppendLine(""" @@ -712,7 +712,7 @@ public static bool TryParse(ReadOnlySpan utf8Text, IFormatProvider? provid """); } } - + if (prop.HasFlag(UnitGenerateOptions.MinMaxMethod)) { sb.AppendLine($$""" @@ -1297,13 +1297,28 @@ public bool IsSupportUtf8Formatter() _ => false }; } - + bool IsImplemented(INamedTypeSymbol interfaceSymbol) { foreach (var x in Type.AllInterfaces) { if (SymbolEqualityComparer.Default.Equals(x, interfaceSymbol)) { + foreach (var interfaceMember in x.GetMembers()) + { + if (interfaceMember.IsStatic) + { + // Do not allow explicit implementation + var implementation = Type.FindImplementationForInterfaceMember(interfaceMember); + switch (implementation) + { + case IMethodSymbol { ExplicitInterfaceImplementations.Length: > 0 }: + return false; + case IPropertySymbol { ExplicitInterfaceImplementations.Length: > 0 }: + return false; + } + } + } return true; } } @@ -1318,6 +1333,21 @@ bool IsImplementedGenericSelfType(INamedTypeSymbol interfaceSymbol) SymbolEqualityComparer.Default.Equals(x.ConstructedFrom, interfaceSymbol) && SymbolEqualityComparer.Default.Equals(x.TypeArguments[0], Type)) { + foreach (var interfaceMember in x.GetMembers()) + { + if (interfaceMember.IsStatic) + { + // Do not allow explicit implementation + var implementation = Type.FindImplementationForInterfaceMember(interfaceMember); + switch (implementation) + { + case IMethodSymbol { ExplicitInterfaceImplementations.Length: > 0 }: + return false; + case IPropertySymbol { ExplicitInterfaceImplementations.Length: > 0 }: + return false; + } + } + } return true; } } @@ -1354,4 +1384,4 @@ where attributeName is "UnitOf" or "UnitOfAttribute" } } } -} +} \ No newline at end of file