Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Appegy.Union
{
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class, Inherited = false)]
public class ExposeAttribute : Attribute
{
public Type[] Interfaces { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Appegy.Union
{
[AttributeUsage(System.AttributeTargets.Struct | AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
[AttributeUsage(System.AttributeTargets.Struct | AttributeTargets.Class, Inherited = false)]
public class UnionAttribute : System.Attribute
{
public System.Type[] Types { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void WhenGettingCircle_AndTypeIsNotCircle_ThenThrowsException()
public void WhenSettingCircle_ThenTypeIsCircle()
{
// Arrange
var shape = new Shape();
var shape = new Shape(new Hexagon());
var circle = new Circle(5);

// Act
Expand Down Expand Up @@ -76,7 +76,7 @@ public void WhenGettingRectangle_AndTypeIsNotRectangle_ThenThrowsException()
public void WhenSettingRectangle_ThenTypeIsRectangle()
{
// Arrange
var shape = new Shape();
var shape = new Shape(new Hexagon());
var rectangle = new Rectangle(4, 6);

// Act
Expand Down Expand Up @@ -116,7 +116,7 @@ public void WhenGettingHexagon_AndTypeIsNotHexagon_ThenThrowsException()
public void WhenSettingHexagon_ThenTypeIsHexagon()
{
// Arrange
var shape = new Shape();
var shape = new Shape(new Circle());
var hexagon = new Hexagon(3);

// Act
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@ public static class DiagnosticDescriptors
{
private const string Category = "Union";

public static DiagnosticDescriptor NotStruct { get; } = new(
id: "UNION001",
title: "Type has to be struct",
messageFormat: "The type '{0}' must be a struct to use [Union].",
category: Category,
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true);

public static DiagnosticDescriptor NotPartial { get; } = new(
id: "UNION002",
title: "Struct is not partial",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
.SyntaxProvider
.ForAttributeWithMetadataName(
ExposeAttributeName,
predicate: static (syntax, _) => syntax is StructDeclarationSyntax,
predicate: static (syntax, _) => syntax is TypeDeclarationSyntax,
transform: static (ctx, _) =>
{
var syntax = (StructDeclarationSyntax)ctx.TargetNode;
var symbol = ctx.SemanticModel.GetDeclaredSymbol(syntax) as INamedTypeSymbol;
var syntax = (TypeDeclarationSyntax)ctx.TargetNode;
var symbol = ctx.SemanticModel.GetDeclaredSymbol(syntax);
var attribute = ctx.Attributes.First();
var interfaces = attribute
.GetTypesFromConstructor(TypeKind.Interface)
Expand All @@ -53,14 +53,14 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
.SyntaxProvider
.ForAttributeWithMetadataName(
UnionAttributeName,
predicate: static (syntax, _) => syntax is StructDeclarationSyntax,
predicate: static (syntax, _) => syntax is TypeDeclarationSyntax,
transform: static (ctx, _) =>
{
var syntax = (StructDeclarationSyntax)ctx.TargetNode;
var symbol = ctx.SemanticModel.GetDeclaredSymbol(syntax) as INamedTypeSymbol;
var syntax = (TypeDeclarationSyntax)ctx.TargetNode;
var symbol = ctx.SemanticModel.GetDeclaredSymbol(syntax);
var attribute = ctx.Attributes.First();
var types = attribute
.GetTypesFromConstructor(TypeKind.Struct)
.GetTypesFromConstructor()
.Select(c => new ExposeTypeInfo(c))
.ToImmutableList();
return (Symbol: symbol!, Types: types);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Appegy.Union.Generator;

public record struct ExposeAttributePartInput(StructDeclarationSyntax Syntax, IReadOnlyList<ExposeTypeInfo> Types, IReadOnlyList<ExposeInterfaceInfo> Interfaces);
public record struct ExposeAttributePartInput(TypeDeclarationSyntax Syntax, IReadOnlyList<ExposeTypeInfo> Types, IReadOnlyList<ExposeInterfaceInfo> Interfaces);

public readonly struct ExposeTypeInfo(INamedTypeSymbol symbol)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.CodeDom.Compiler;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Appegy.Union.Generator;

Expand All @@ -8,7 +9,18 @@ public override void Generate(IndentedTextWriter codeWriter, ExposeAttributePart
{
var (syntax, _, interfaces) = input;

codeWriter.Write("partial struct ");
codeWriter.Write("partial ");

switch (syntax)
{
case StructDeclarationSyntax:
codeWriter.Write("struct ");
break;
case ClassDeclarationSyntax:
codeWriter.Write("class ");
break;
}

codeWriter.Write(syntax.Identifier.Text);

codeWriter.WriteLine(" :");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.CodeDom.Compiler;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Appegy.Union.Generator;

Expand All @@ -10,7 +11,16 @@ public override void Generate(IndentedTextWriter codeWriter, UnionAttributePartI
var types = input.Types;

codeWriter.WriteLine(AttributesNames.GeneratedCodeAttribute);
codeWriter.Write("partial struct ");
codeWriter.Write("partial ");
switch (syntax)
{
case StructDeclarationSyntax:
codeWriter.Write("struct ");
break;
case ClassDeclarationSyntax:
codeWriter.Write("class ");
break;
}
codeWriter.WriteLine(syntax.Identifier.Text);

codeWriter.Write(" : global::System.IEquatable<");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ public class UnionAttributeAnalyzer : DiagnosticAnalyzer
NotPartial,
NestedNotPartial,
NoTypesProvided,
NotStruct,
DuplicateUnionType);

public override void Initialize(AnalysisContext context)
Expand All @@ -39,38 +38,37 @@ private void AnalyzeAttribute(SyntaxNodeAnalysisContext context)
VerifyPartialModifier(context, attributeSyntax);
VerifyParentsPartial(context, attributeSyntax);
VerifyArgumentsExistence(context, attributeSyntax);
VerifyAllTypesAreStruct(context, attributeSyntax);
VerifyNoDuplicate(context, attributeSyntax);
}

private static void VerifyPartialModifier(SyntaxNodeAnalysisContext context, AttributeSyntax attributeSyntax)
{
if (attributeSyntax.Parent?.Parent is not StructDeclarationSyntax structDeclaration)
if (attributeSyntax.Parent?.Parent is not TypeDeclarationSyntax typeDeclaration)
{
return;
}

if (structDeclaration.Modifiers.Any(SyntaxKind.PartialKeyword))
if (typeDeclaration.Modifiers.Any(SyntaxKind.PartialKeyword))
{
return;
}

var diagnostic = Diagnostic.Create(
NotPartial,
structDeclaration.Identifier.GetLocation(),
structDeclaration.Identifier.Text);
typeDeclaration.Identifier.GetLocation(),
typeDeclaration.Identifier.Text);

context.ReportDiagnostic(diagnostic);
}

private static void VerifyParentsPartial(SyntaxNodeAnalysisContext context, AttributeSyntax attributeSyntax)
{
if (attributeSyntax.Parent?.Parent is not StructDeclarationSyntax structDeclaration)
if (attributeSyntax.Parent?.Parent is not TypeDeclarationSyntax typeDeclaration)
{
return;
}

var parent = structDeclaration.Parent;
var parent = typeDeclaration.Parent;
while (parent is TypeDeclarationSyntax parentType)
{
if (!parentType.Modifiers.Any(SyntaxKind.PartialKeyword))
Expand Down Expand Up @@ -99,34 +97,6 @@ private void VerifyArgumentsExistence(SyntaxNodeAnalysisContext context, Attribu
context.ReportDiagnostic(diagnostic);
}

private void VerifyAllTypesAreStruct(SyntaxNodeAnalysisContext context, AttributeSyntax attributeSyntax)
{
var arguments = attributeSyntax.ArgumentList?.Arguments;
if (arguments == null || arguments.Value.Count == 0)
{
return;
}

foreach (var argument in arguments)
{
if (argument.Expression is not TypeOfExpressionSyntax typeOfExpression)
{
continue;
}

var typeInfo = context.SemanticModel.GetTypeInfo(typeOfExpression.Type);
if (typeInfo.Type?.TypeKind != TypeKind.Struct)
{
var diagnostic = Diagnostic.Create(
NotStruct,
typeOfExpression.Type.GetLocation(),
typeInfo.Type?.ToDisplayString() ?? "unknown");

context.ReportDiagnostic(diagnostic);
}
}
}

private void VerifyNoDuplicate(SyntaxNodeAnalysisContext context, AttributeSyntax attributeSyntax)
{
var arguments = attributeSyntax.ArgumentList?.Arguments;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
.SyntaxProvider
.ForAttributeWithMetadataName(
UnionAttributeName,
predicate: static (syntax, _) => syntax is StructDeclarationSyntax,
predicate: static (syntax, _) => syntax is TypeDeclarationSyntax,
transform: static (ctx, _) =>
{
var syntax = (StructDeclarationSyntax)ctx.TargetNode;
var syntax = (TypeDeclarationSyntax)ctx.TargetNode;
var symbol = ctx.SemanticModel.GetDeclaredSymbol(syntax);
var attribute = ctx.Attributes.First();
var types = attribute
.GetTypesFromConstructor(TypeKind.Struct)
.GetTypesFromConstructor()
.Select(c => new UnionTypeInfo(c))
.ToImmutableList();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Appegy.Union.Generator;

public record struct UnionAttributePartInput(StructDeclarationSyntax Syntax, IReadOnlyList<UnionTypeInfo> Types, bool ExplicitLayout);
public record struct UnionAttributePartInput(TypeDeclarationSyntax Syntax, IReadOnlyList<UnionTypeInfo> Types, bool ExplicitLayout);

public readonly struct UnionTypeInfo(INamedTypeSymbol symbol)
{
Expand Down
4 changes: 2 additions & 2 deletions Runtime/Appegy.Union.Generator.dll
Git LFS file not shown
Binary file modified Runtime/Appegy.Union.Generator.pdb
Binary file not shown.
2 changes: 1 addition & 1 deletion Runtime/ExposeAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Appegy.Union
{
[AttributeUsage(AttributeTargets.Struct)]
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class, Inherited = false)]
public class ExposeAttribute : Attribute
{
public Type[] Interfaces { get; }
Expand Down
2 changes: 1 addition & 1 deletion Runtime/UnionAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Appegy.Union
{
[AttributeUsage(AttributeTargets.Struct)]
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class, Inherited = false)]
public class UnionAttribute : Attribute
{
public Type[] Types { get; }
Expand Down