Skip to content

Commit

Permalink
Merge pull request #253 from Cysharp/ku/fix-default-value2
Browse files Browse the repository at this point in the history
Fix problem when default value expression contains namespace
  • Loading branch information
neuecc authored Mar 18, 2024
2 parents f2ce54e + 42e3456 commit 22e107f
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 9 deletions.
52 changes: 50 additions & 2 deletions src/MemoryPack.Generator/MemoryPackGenerator.Emitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ static void Generate(TypeDeclarationSyntax syntax, Compilation compilation, stri
}
var unionFormatter = (unionSymbol != null);

var typeMeta = new TypeMeta(typeSymbol, reference);
var typeMeta = new TypeMeta(semanticModel, typeSymbol, reference);
if (unionFormatter)
{
// replace original symbol
Expand Down Expand Up @@ -1383,5 +1383,53 @@ string EmitConstantValue(object? constantValue)
}
return "null";
}
}

string EmitExpression(ExpressionSyntax expression)
{
switch (expression.Kind())
{
case SyntaxKind.SimpleMemberAccessExpression:
{
var memberAccess = (MemberAccessExpressionSyntax)expression;
var memberSymbol = semanticModel.GetSymbolInfo(memberAccess.Name).Symbol;
if (memberSymbol is INamedTypeSymbol namedTypeSymbol && namedTypeSymbol.TypeKind == TypeKind.Enum)
{
return $"{GetTypeFullName(namedTypeSymbol, semanticModel)}.{memberAccess.Name}";
}
if (memberSymbol is IFieldSymbol fieldSymbol && fieldSymbol.ContainingType.TypeKind == TypeKind.Enum)
{
return $"{GetTypeFullName(fieldSymbol.ContainingType, semanticModel)}.{fieldSymbol.Name}";
}
break;
}

case SyntaxKind.ObjectCreationExpression:
{
var objectCreation = (ObjectCreationExpressionSyntax)expression;
var symbolInfo = semanticModel.GetSymbolInfo(objectCreation.Type);
if (symbolInfo.Symbol is INamedTypeSymbol x)
{
var arguments = string.Join(", ",
objectCreation.ArgumentList?.Arguments.Select(arg =>
EmitExpression(arg.Expression)) ?? Enumerable.Empty<string>());
return $"new {x.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}({arguments})";
}
break;
}

case SyntaxKind.TupleExpression:
var tupleExpression = (TupleExpressionSyntax)expression;
var tupleElements = string.Join(", ",
tupleExpression.Arguments.Select(arg => EmitExpression(arg.Expression)));
return $"({tupleElements})";
}
return expression.ToString();
}

string GetTypeFullName(ITypeSymbol typeSymbol, SemanticModel semanticModel)
{
var containingType = typeSymbol.ContainingType;
var containingTypeFullName = containingType == null ? "" : GetTypeFullName(containingType, semanticModel) + ".";
return containingTypeFullName + typeSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
}
}
14 changes: 8 additions & 6 deletions src/MemoryPack.Generator/MemoryPackGenerator.Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public partial class TypeMeta
public (ushort Tag, INamedTypeSymbol Type)[] UnionTags { get; }
public bool IsUseEmptyConstructor => Constructor == null || Constructor.Parameters.IsEmpty;

public TypeMeta(INamedTypeSymbol symbol, ReferenceSymbols reference)
public TypeMeta(SemanticModel semanticModel, INamedTypeSymbol symbol, ReferenceSymbols reference)
{
this.reference = reference;
this.Symbol = symbol;
Expand Down Expand Up @@ -104,7 +104,7 @@ public TypeMeta(INamedTypeSymbol symbol, ReferenceSymbols reference)
}
return true;
})
.Select((x, i) => new MemberMeta(x, Constructor, reference, i))
.Select((x, i) => new MemberMeta(semanticModel, x, Constructor, reference, i))
.OrderBy(x => x.Order)
.ToArray();

Expand Down Expand Up @@ -616,6 +616,7 @@ partial class MemberMeta
public bool HasExplicitOrder { get; }
public MemberKind Kind { get; }
public string DefaultValueExpression { get; } = "default!";
readonly SemanticModel semanticModel;

MemberMeta(int order)
{
Expand All @@ -626,8 +627,9 @@ partial class MemberMeta
this.Kind = MemberKind.Blank;
}

public MemberMeta(ISymbol symbol, IMethodSymbol? constructor, ReferenceSymbols references, int sequentialOrder)
public MemberMeta(SemanticModel semanticModel, ISymbol symbol, IMethodSymbol? constructor, ReferenceSymbols references, int sequentialOrder)
{
this.semanticModel = semanticModel;
this.Symbol = symbol;
this.Name = symbol.Name;
this.Order = sequentialOrder;
Expand Down Expand Up @@ -677,13 +679,13 @@ public MemberMeta(ISymbol symbol, IMethodSymbol? constructor, ReferenceSymbols r
{
if (variables.First().Initializer is { } initializer)
{
DefaultValueExpression = initializer.Value.ToString();
DefaultValueExpression = EmitExpression(initializer.Value);
break;
}
}
if (syntax is VariableDeclaratorSyntax { Initializer: { } initializer2 })
{
DefaultValueExpression = initializer2.Value.ToString();
DefaultValueExpression = EmitExpression(initializer2.Value);
break;
}
}
Expand All @@ -705,7 +707,7 @@ public MemberMeta(ISymbol symbol, IMethodSymbol? constructor, ReferenceSymbols r
{
if (syntaxReference.GetSyntax() is PropertyDeclarationSyntax { Initializer: { } initializer })
{
DefaultValueExpression = initializer.Value.ToString();
DefaultValueExpression = EmitExpression(initializer.Value);
break;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/MemoryPack.Generator/MemoryPackGenerator.TypeScript.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ partial class MemoryPackGenerator
return null;
}

var typeMeta = new TypeMeta(typeSymbol, reference);
var typeMeta = new TypeMeta(semanticModel, typeSymbol, reference);

if (typeMeta.GenerateType is not (GenerateType.Object or GenerateType.Union))
{
Expand Down
10 changes: 10 additions & 0 deletions tests/MemoryPack.Tests/Models/DefaultValues.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
using System.Collections.Generic;

namespace MemoryPack.Tests.Models;

enum TestEnum
{
A, B, C
}

[MemoryPackable]
partial class DefaultValuePlaceholder
{
Expand All @@ -24,6 +31,9 @@ partial class PropertyDefaultValue
public float Z { get; set; } = 678.9f;
public string S { get; set; } = "aaaaaaaaa";
public bool B { get; set; } = true;
public List<string> Alpha { get; set; } = new List<string>(new HashSet<string>());
public TestEnum TestEnum { get; set; } = TestEnum.A;
public (TestEnum, List<string>) Tuple { get; set; } = (TestEnum.A, new List<string>(new HashSet<string>()));
}

[MemoryPackable]
Expand Down

0 comments on commit 22e107f

Please sign in to comment.