Skip to content

Commit

Permalink
add fully qualified Names for method return types, new constructor ca…
Browse files Browse the repository at this point in the history
…ll and generic types closes riok#298
  • Loading branch information
ismaeel-ch committed Apr 11, 2023
1 parent 7cb51b8 commit d0b9158
Show file tree
Hide file tree
Showing 106 changed files with 532 additions and 472 deletions.
3 changes: 2 additions & 1 deletion src/Riok.Mapperly/Descriptors/Mappings/ArrayCloneMapping.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Riok.Mapperly.Helpers;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using static Riok.Mapperly.Emit.SyntaxFactoryHelper;

Expand All @@ -22,7 +23,7 @@ public ArrayCloneMapping(
public override ExpressionSyntax Build(TypeMappingBuildContext ctx)
{
return CastExpression(
IdentifierName(TargetType.ToDisplayString()),
TargetType.GetFullyQualifiedTypeSyntax(),
InvocationExpression(MemberAccess(ctx.Source, CloneMethodName)));
}
}
3 changes: 2 additions & 1 deletion src/Riok.Mapperly/Descriptors/Mappings/ArrayForMapping.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Riok.Mapperly.Helpers;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using static Riok.Mapperly.Emit.SyntaxFactoryHelper;

Expand Down Expand Up @@ -32,7 +33,7 @@ public override IEnumerable<StatementSyntax> BuildBody(TypeMappingBuildContext c
// var target = new T[source.Length];
var sourceLengthArrayRank = ArrayRankSpecifier(SingletonSeparatedList<ExpressionSyntax>(MemberAccess(ctx.Source, ArrayLengthProperty)));
var targetInitializationValue = ArrayCreationExpression(
ArrayType(IdentifierName(_targetArrayElementType.ToDisplayString()))
ArrayType(_targetArrayElementType.GetFullyQualifiedTypeSyntax())
.WithRankSpecifiers(SingletonList(sourceLengthArrayRank)));
yield return DeclareLocalVariable(targetVariableName, targetInitializationValue);

Expand Down
3 changes: 2 additions & 1 deletion src/Riok.Mapperly/Descriptors/Mappings/CastMapping.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Riok.Mapperly.Helpers;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;

namespace Riok.Mapperly.Descriptors.Mappings;
Expand All @@ -22,6 +23,6 @@ public override ExpressionSyntax Build(TypeMappingBuildContext ctx)
var objToCast = _delegateMapping != null
? _delegateMapping.Build(ctx)
: ctx.Source;
return CastExpression(IdentifierName(TargetType.ToDisplayString()), objToCast);
return CastExpression(TargetType.GetFullyQualifiedTypeSyntax(), objToCast);
}
}
4 changes: 2 additions & 2 deletions src/Riok.Mapperly/Descriptors/Mappings/CtorMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public CtorMapping(ITypeSymbol sourceType, ITypeSymbol targetType)

public override ExpressionSyntax Build(TypeMappingBuildContext ctx)
{
var type = IdentifierName(TargetType.NonNullable().ToDisplayString());
return ObjectCreationExpression(type).WithArgumentList(ArgumentList(ctx.Source));
return ObjectCreationExpression(TargetType.GetFullyQualifiedTypeSyntax()).WithArgumentList(ArgumentList(ctx.Source));

}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Riok.Mapperly.Helpers;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using static Riok.Mapperly.Emit.SyntaxFactoryHelper;

Expand Down Expand Up @@ -38,15 +39,15 @@ public override ExpressionSyntax Build(TypeMappingBuildContext ctx)
return GenericInvocation(
EnumClassName,
ParseMethodName,
new[] { IdentifierName(TargetType.ToDisplayString()) },
new[] { TargetType.GetFullyQualifiedTypeSyntax() },
ctx.Source,
BooleanLiteral(_ignoreCase));
}

// (TargetType)System.Enum.Parse(typeof(TargetType), source, ignoreCase)
var enumParseInvocation = Invocation(
MemberAccess(EnumClassName, ParseMethodName),
TypeOfExpression(IdentifierName(TargetType.ToDisplayString())), ctx.Source, BooleanLiteral(_ignoreCase));
return CastExpression(IdentifierName(TargetType.ToDisplayString()), enumParseInvocation);
TypeOfExpression(TargetType.GetFullyQualifiedTypeSyntax()), ctx.Source, BooleanLiteral(_ignoreCase));
return CastExpression(TargetType.GetFullyQualifiedTypeSyntax(), enumParseInvocation);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ private SwitchExpressionArmSyntax BuildArmIgnoreCase(string ignoreCaseSwitchDesi

// source.Value1
var typeMemberAccess = MemberAccess(
IdentifierName(field.ContainingType.WithNullableAnnotation(NullableAnnotation.None).ToDisplayString()),
IdentifierName(field.ContainingType.WithNullableAnnotation(NullableAnnotation.None).GetFullyQualifiedIdentifierName()),
field.Name);

// when s.Equals(nameof(source.Value1), StringComparison.OrdinalIgnoreCase)
Expand All @@ -87,7 +87,7 @@ private SwitchExpressionArmSyntax BuildArm(IFieldSymbol field)
{
// nameof(source.Value1) => source.Value1;
var typeMemberAccess = MemberAccess(
IdentifierName(field.ContainingType.NonNullable().ToDisplayString()),
IdentifierName(field.ContainingType.NonNullable().GetFullyQualifiedIdentifierName()),
field.Name);
var pattern = ConstantPattern(NameOf(typeMemberAccess));
return SwitchExpressionArm(pattern, typeMemberAccess);
Expand Down
5 changes: 3 additions & 2 deletions src/Riok.Mapperly/Descriptors/Mappings/EnumNameMapping.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Riok.Mapperly.Helpers;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using static Riok.Mapperly.Emit.SyntaxFactoryHelper;

Expand Down Expand Up @@ -44,8 +45,8 @@ public override IEnumerable<StatementSyntax> BuildBody(TypeMappingBuildContext c

private SwitchExpressionArmSyntax BuildArm(KeyValuePair<string, string> sourceTargetField)
{
var sourceMember = MemberAccess(SourceType.ToDisplayString(), sourceTargetField.Key);
var targetMember = MemberAccess(TargetType.ToDisplayString(), sourceTargetField.Value);
var sourceMember = MemberAccess(SourceType.GetFullyQualifiedIdentifierName(), sourceTargetField.Key);
var targetMember = MemberAccess(TargetType.GetFullyQualifiedIdentifierName(), sourceTargetField.Value);
var pattern = ConstantPattern(sourceMember);
return SwitchExpressionArm(pattern, targetMember);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public override IEnumerable<StatementSyntax> BuildBody(TypeMappingBuildContext c
private SwitchExpressionArmSyntax BuildArm(IFieldSymbol field)
{
var typeMemberAccess = MemberAccess(
IdentifierName(field.ContainingType.NonNullable().ToDisplayString()),
IdentifierName(field.ContainingType.NonNullable().GetFullyQualifiedIdentifierName()),
field.Name);
var pattern = ConstantPattern(typeMemberAccess);
var nameOf = NameOf(typeMemberAccess);
Expand Down
2 changes: 1 addition & 1 deletion src/Riok.Mapperly/Descriptors/Mappings/MethodMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public MethodDeclarationSyntax BuildMethod(SourceEmitterContext ctx)
{
TypeSyntax returnType = ReturnType == null
? PredefinedType(Token(SyntaxKind.VoidKeyword))
: IdentifierName(TargetType.ToDisplayString());
: TargetType.GetFullyQualifiedTypeSyntax();

var typeMappingBuildContext = new TypeMappingBuildContext(
SourceParameter.Name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public override ExpressionSyntax Build(TypeMappingBuildContext ctx)
// if the target type is a nullable value type, there needs to be an additional cast in some cases
// (eg. in a linq expression, int => int?)
return TargetType.IsNullableValueType()
? CastExpression(IdentifierName(TargetType.ToDisplayString()), _delegateMapping.Build(ctx))
? CastExpression(TargetType.GetFullyQualifiedTypeSyntax(), _delegateMapping.Build(ctx))
: _delegateMapping.Build(ctx);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public override ExpressionSyntax Build(TypeMappingBuildContext ctx)
if (Method.ReceiverType?.TypeKind != TypeKind.Interface)
return Invocation(Method.Name, _sourceParameter.WithArgument(ctx.Source), _referenceHandlerParameter?.WithArgument(ctx.ReferenceHandler));

var castedThis = CastExpression(IdentifierName(Method.ReceiverType!.ToDisplayString()), ThisExpression());
var castedThis = CastExpression(Method.ReceiverType!.GetFullyQualifiedTypeSyntax(), ThisExpression());
var method = MemberAccess(ParenthesizedExpression(castedThis), Method.Name);
return Invocation(method, _sourceParameter.WithArgument(ctx.Source), _referenceHandlerParameter?.WithArgument(ctx.ReferenceHandler));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Riok.Mapperly.Abstractions.ReferenceHandling;
using Riok.Mapperly.Descriptors.Mappings;
using Riok.Mapperly.Helpers;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using static Riok.Mapperly.Emit.SyntaxFactoryHelper;

Expand All @@ -18,7 +19,7 @@ public static IfStatementSyntax TryGetReference(
// GetReference<TSource, TTarget>
var refHandler = ctx.ReferenceHandler ?? throw new ArgumentNullException(nameof(ctx.ReferenceHandler));
var methodName = GenericName(Identifier(nameof(IReferenceHandler.TryGetReference)))
.WithTypeArgumentList(TypeArgumentList(IdentifierName(mapping.SourceType.ToDisplayString()), IdentifierName(mapping.TargetType.ToDisplayString())));
.WithTypeArgumentList(TypeArgumentList(mapping.SourceType.GetFullyQualifiedTypeSyntax(), mapping.TargetType.GetFullyQualifiedTypeSyntax()));
var method = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, refHandler, methodName);

// out var target
Expand Down Expand Up @@ -46,7 +47,7 @@ public static ExpressionSyntax SetReference(
// SetReference<TSource, TTarget>
var refHandler = ctx.ReferenceHandler ?? throw new ArgumentNullException(nameof(ctx.ReferenceHandler));
var methodName = GenericName(Identifier(nameof(IReferenceHandler.SetReference)))
.WithTypeArgumentList(TypeArgumentList(IdentifierName(mapping.SourceType.ToDisplayString()), IdentifierName(mapping.TargetType.ToDisplayString())));
.WithTypeArgumentList(TypeArgumentList(mapping.SourceType.GetFullyQualifiedTypeSyntax(), (mapping.TargetType.GetFullyQualifiedTypeSyntax())));
var method = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, refHandler, methodName);

return Invocation(method, ctx.Source, target);
Expand Down
11 changes: 3 additions & 8 deletions src/Riok.Mapperly/Emit/SyntaxFactoryHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,13 +216,8 @@ public static ParameterListSyntax ParameterList(bool extensionMethod, params Met

public static ParameterSyntax Parameter(bool addThisKeyword, MethodParameter parameter)
{
var parameterTypeSyntax = IdentifierName(parameter.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));
var param = SyntaxFactory.Parameter(Identifier(parameter.Name))
.WithType(
parameter.Type.NullableAnnotation == NullableAnnotation.Annotated ?
SyntaxFactory.NullableType(parameterTypeSyntax) :
parameterTypeSyntax
);
.WithType(parameter.Type.GetFullyQualifiedTypeSyntax());

if (addThisKeyword && parameter.Ordinal == 0)
{
Expand All @@ -241,7 +236,7 @@ public static InvocationExpressionSyntax StaticInvocation(string receiverType, s

public static InvocationExpressionSyntax StaticInvocation(IMethodSymbol method, params ExpressionSyntax[] arguments)
=> StaticInvocation(
method.ReceiverType?.NonNullable().ToDisplayString() ?? throw new ArgumentNullException(nameof(method.ReceiverType)),
method.ReceiverType?.NonNullable().GetFullyQualifiedIdentifierName() ?? throw new ArgumentNullException(nameof(method.ReceiverType)),
method.Name,
arguments);

Expand Down Expand Up @@ -330,7 +325,7 @@ public static SeparatedSyntaxList<T> CommaSeparatedList<T>(IEnumerable<T> nodes,
=> SeparatedList<T>(JoinByComma(nodes, insertTrailingComma));

public static IdentifierNameSyntax NonNullableIdentifier(ITypeSymbol t)
=> IdentifierName(t.NonNullable().ToDisplayString());
=> IdentifierName(t.NonNullable().GetFullyQualifiedIdentifierName());

private static IEnumerable<SyntaxNodeOrToken> JoinByComma(IEnumerable<SyntaxNode> nodes, bool insertTrailingComma = false)
=> Join(Token(SyntaxKind.CommaToken), insertTrailingComma, nodes);
Expand Down
60 changes: 60 additions & 0 deletions src/Riok.Mapperly/Helpers/SymbolExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.Diagnostics.CodeAnalysis;

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Riok.Mapperly.Helpers;

Expand Down Expand Up @@ -100,4 +102,62 @@ internal static bool CanConsumeType(this ITypeParameterSymbol typeParameter, Com

return true;
}

internal static TypeSyntax GetFullyQualifiedTypeSyntax(this ITypeSymbol typeSymbol)
{
if (typeSymbol is IArrayTypeSymbol arrayTypeSymbol)
{
var arrayFullName = arrayTypeSymbol.ToDisplayString();

string arrayQualifiedName = default!;
var rr = arrayTypeSymbol.ElementType.ToString();
if (IsPrimitiveType(arrayTypeSymbol.ElementType))
arrayQualifiedName = arrayFullName;
else
arrayQualifiedName = $"global::{arrayFullName}";
var identifierSyntax = SyntaxFactory.IdentifierName(arrayQualifiedName);
return arrayTypeSymbol.NullableAnnotation == NullableAnnotation.Annotated ?
SyntaxFactory.NullableType(identifierSyntax) :
identifierSyntax;
}
var returnTypeIdentifierSyntax = SyntaxFactory.IdentifierName(typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));
var isNullableType = typeSymbol.NullableAnnotation == NullableAnnotation.Annotated;
if (isNullableType)
{
if (typeSymbol is INamedTypeSymbol namedTypeSymbol && namedTypeSymbol.ConstructedFrom.ToDisplayString() == "System.Nullable<T>")
{
return returnTypeIdentifierSyntax;
}
else
return SyntaxFactory.NullableType(returnTypeIdentifierSyntax);
}
return returnTypeIdentifierSyntax;
}

internal static string GetFullyQualifiedIdentifierName(this ITypeSymbol typeSymbol)
{
return typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);

}

// Method to check if a type is a primitive type
private static bool IsPrimitiveType(ITypeSymbol typeSymbol)
{
return typeSymbol.SpecialType is
SpecialType.System_Char
or SpecialType.System_SByte
or SpecialType.System_Single
or SpecialType.System_String
or SpecialType.System_Boolean
or SpecialType.System_UInt16
or SpecialType.System_UInt32
or SpecialType.System_UInt64
or SpecialType.System_UInt32
or SpecialType.System_UIntPtr
or SpecialType.System_Int32
or SpecialType.System_Int64
or SpecialType.System_IntPtr
or SpecialType.System_Decimal
or SpecialType.System_Double;
}
}
Loading

0 comments on commit d0b9158

Please sign in to comment.