Skip to content

Commit

Permalink
Merge pull request #44 from Cysharp/hadashiA/fix-net8
Browse files Browse the repository at this point in the history
Fix compilation errors in .net8 with explicit static members
neuecc authored Feb 3, 2024
2 parents a40a091 + fa0c19d commit 3ac1cc8
Showing 11 changed files with 322 additions and 98 deletions.
2 changes: 1 addition & 1 deletion sandbox/ConsoleApp/ConsoleApp.csproj
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
2 changes: 1 addition & 1 deletion sandbox/FileGenerate/FileGenerate.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>

<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(ProjectDir)..\Generated</CompilerGeneratedFilesOutputPath>
9 changes: 7 additions & 2 deletions sandbox/FileGenerate/SimplePrimitive.cs
Original file line number Diff line number Diff line change
@@ -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<int>]
public readonly partial struct Aa
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@ readonly partial struct A
#endif
#if NET8_0_OR_GREATER
, IEqualityOperators<A, A, bool>
, IUtf8SpanFormattable
#endif
{
readonly int value;
@@ -83,6 +84,11 @@ public override int GetHashCode()
public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider) =>
((ISpanFormattable)value).TryFormat(destination, out charsWritten, format, provider);
#endif
#if NET8_0_OR_GREATER
public bool TryFormat (Span<byte> utf8Destination, out int bytesWritten, ReadOnlySpan<char> format, IFormatProvider? provider) =>
((IUtf8SpanFormattable)value).TryFormat(utf8Destination, out bytesWritten, format, provider);
#endif

// Default

private class ATypeConverter : System.ComponentModel.TypeConverter
Original file line number Diff line number Diff line change
@@ -12,10 +12,14 @@ namespace FileGenerate
[System.ComponentModel.TypeConverter(typeof(AaTypeConverter))]
readonly partial struct Aa
: IEquatable<Aa>
#if NET7_0_OR_GREATER
, IEqualityOperators<Aa, Aa, bool>
#endif
, IFormattable
#if NET6_0_OR_GREATER
, ISpanFormattable
#endif
#if NET8_0_OR_GREATER
, IEqualityOperators<Aa, Aa, bool>
, 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<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider) =>
((ISpanFormattable)value).TryFormat(destination, out charsWritten, format, provider);
#endif
#if NET8_0_OR_GREATER
public bool TryFormat (Span<byte> utf8Destination, out int bytesWritten, ReadOnlySpan<char> format, IFormatProvider? provider) =>
((IUtf8SpanFormattable)value).TryFormat(utf8Destination, out bytesWritten, format, provider);
#endif

// Default

private class AaTypeConverter : System.ComponentModel.TypeConverter
Original file line number Diff line number Diff line change
@@ -12,9 +12,9 @@ namespace FileGenerate
[System.ComponentModel.TypeConverter(typeof(BbTypeConverter))]
readonly partial struct Bb
: IEquatable<Bb>
#if NET7_0_OR_GREATER
#if NET8_0_OR_GREATER
, IEqualityOperators<Bb, Bb, bool>
#endif
#endif
{
readonly string value;

Original file line number Diff line number Diff line change
@@ -19,8 +19,6 @@ readonly partial struct C
#endif
#if NET7_0_OR_GREATER
, IComparisonOperators<C, C, bool>
, IParsable<C>
, ISpanParsable<C>
, IAdditionOperators<C, C, C>
, ISubtractionOperators<C, C, C>
, IMultiplyOperators<C, C, C>
@@ -32,7 +30,7 @@ readonly partial struct C
#endif
#if NET8_0_OR_GREATER
, IEqualityOperators<C, C, bool>
, IUtf8SpanParsable<C>
, IUtf8SpanFormattable
#endif
{
readonly int value;
@@ -98,6 +96,11 @@ public override int GetHashCode()
public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider) =>
((ISpanFormattable)value).TryFormat(destination, out charsWritten, format, provider);
#endif
#if NET8_0_OR_GREATER
public bool TryFormat (Span<byte> utf8Destination, out int bytesWritten, ReadOnlySpan<char> 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<char> s, IFormatProvider? provider)
{
return new C(int.Parse(s, provider));
}

public static bool TryParse(ReadOnlySpan<char> 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<byte> utf8Text, IFormatProvider? provider)
{
return new C(int.Parse(utf8Text, provider));
}

public static bool TryParse(ReadOnlySpan<byte> 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)
Original file line number Diff line number Diff line change
@@ -12,15 +12,13 @@ namespace FileGenerate
[System.ComponentModel.TypeConverter(typeof(CcTypeConverter))]
readonly partial struct Cc
: IEquatable<Cc>
#if NET7_0_OR_GREATER
, IEqualityOperators<Cc, Cc, bool>
#endif
, IComparable<Cc>
#if NET7_0_OR_GREATER
, IComparisonOperators<Cc, Cc, bool>
#endif
, IFormattable
#if NET6_0_OR_GREATER
, ISpanFormattable
#endif
#if NET7_0_OR_GREATER
, IComparisonOperators<Cc, Cc, bool>
, IAdditionOperators<Cc, Cc, Cc>
, ISubtractionOperators<Cc, Cc, Cc>
, IMultiplyOperators<Cc, Cc, Cc>
@@ -29,6 +27,10 @@ readonly partial struct Cc
, IUnaryNegationOperators<Cc, Cc>
, IIncrementOperators<Cc>
, IDecrementOperators<Cc>
#endif
#if NET8_0_OR_GREATER
, IEqualityOperators<Cc, Cc, bool>
, 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<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider) =>
((ISpanFormattable)value).TryFormat(destination, out charsWritten, format, provider);
#endif
#if NET8_0_OR_GREATER
public bool TryFormat (Span<byte> utf8Destination, out int bytesWritten, ReadOnlySpan<char> format, IFormatProvider? provider) =>
((IUtf8SpanFormattable)value).TryFormat(utf8Destination, out bytesWritten, format, provider);
#endif

// UnitGenerateOptions.ArithmeticOperator

public static Cc operator +(Cc x, Cc y)
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
// <auto-generated>
// THIS (.cs) FILE IS GENERATED BY UnitGenerator. DO NOT CHANGE IT.
// </auto-generated>
#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<D>
, IComparable<D>
, IFormattable
#if NET6_0_OR_GREATER
, ISpanFormattable
#endif
#if NET7_0_OR_GREATER
, IComparisonOperators<D, D, bool>
#endif
#if NET8_0_OR_GREATER
, IEqualityOperators<D, D, bool>
, 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<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider) =>
((ISpanFormattable)value).TryFormat(destination, out charsWritten, format, provider);
#endif
#if NET8_0_OR_GREATER
public bool TryFormat (Span<byte> utf8Destination, out int bytesWritten, ReadOnlySpan<char> 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);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -37,8 +37,8 @@ public UnitOfAttribute(UnitGenerateOptions options = UnitGenerateOptions.None)
{
this.Type = typeof(T);
this.Options = options;
  }
    }
}
}
#endif

[Flags]
60 changes: 45 additions & 15 deletions src/UnitGenerator/SourceGenerator.cs
Original file line number Diff line number Diff line change
@@ -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,15 +104,15 @@ 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();

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<byte> 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"
}
}
}
}
}

0 comments on commit 3ac1cc8

Please sign in to comment.