static bool TryGetActivatorConstructor(INamedTypeSymbol type, LibraryTypes libraryTypes, out List <TypeSyntax> parameters) { parameters = null; if (type.IsAbstract) { return(false); } foreach (var constructor in type.GetAllMembers <IMethodSymbol>()) { if (constructor.MethodKind != MethodKind.Constructor || constructor.DeclaredAccessibility == Accessibility.Private || constructor.IsImplicitlyDeclared) { continue; } if (constructor.HasAttribute(libraryTypes.GeneratedActivatorConstructorAttribute)) { foreach (var parameter in constructor.Parameters) { var argumentType = parameter.Type.ToTypeSyntax(); (parameters ??= new()).Add(argumentType); } break; } } return(parameters is not null); }
private static ConstructorDeclarationSyntax GenerateConstructor( LibraryTypes libraryTypes, string simpleClassName, List <ConstructorArgument> orderedFields) { var parameters = new List <ParameterSyntax>(); var body = new List <StatementSyntax>(); foreach (var field in orderedFields) { parameters.Add(Parameter(field.ParameterName.ToIdentifier()).WithType(field.Type)); body.Add(ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, ThisExpression().Member(field.FieldName.ToIdentifierName()), Unwrapped(field.ParameterName.ToIdentifierName())))); } var constructorDeclaration = ConstructorDeclaration(simpleClassName) .AddModifiers(Token(SyntaxKind.PublicKeyword)) .AddParameterListParameters(parameters.ToArray()) .AddBodyStatements(body.ToArray()); return(constructorDeclaration);
private static IEnumerable <IMemberDescription> GetUnionCaseDataMembers(LibraryTypes libraryTypes, INamedTypeSymbol symbol) { List <IPropertySymbol> dataMembers = new(); foreach (var property in symbol.GetDeclaredInstanceMembers <IPropertySymbol>()) { if (!property.Name.StartsWith("Item", System.StringComparison.Ordinal)) { continue; } dataMembers.Add(property); } dataMembers.Sort(FSharpUnionCasePropertyNameComparer.Default); ushort id = 0; foreach (var field in dataMembers) { yield return(new FSharpUnionCaseFieldDescription(libraryTypes, field, id)); id++; } }
public static (ClassDeclarationSyntax, GeneratedProxyDescription) Generate( LibraryTypes libraryTypes, InvokableInterfaceDescription interfaceDescription, MetadataModel metadataModel) { var generatedClassName = GetSimpleClassName(interfaceDescription); var ctors = GenerateConstructors(generatedClassName, interfaceDescription.ProxyBaseType).ToArray(); var proxyMethods = CreateProxyMethods(libraryTypes, interfaceDescription, metadataModel).ToArray(); var classDeclaration = ClassDeclaration(generatedClassName) .AddBaseListTypes( SimpleBaseType(interfaceDescription.ProxyBaseType.ToTypeSyntax()), SimpleBaseType(interfaceDescription.InterfaceType.ToTypeSyntax())) .AddModifiers(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.SealedKeyword)) .AddAttributeLists( AttributeList(SingletonSeparatedList(CodeGenerator.GetGeneratedCodeAttributeSyntax()))) .AddMembers(ctors) .AddMembers(proxyMethods); var typeParameters = interfaceDescription.TypeParameters; if (typeParameters.Count > 0) { classDeclaration = SyntaxFactoryUtility.AddGenericTypeParameters(classDeclaration, typeParameters); } return(classDeclaration, new GeneratedProxyDescription(interfaceDescription)); }
private static List <GeneratedFieldDescription> GetFieldDescriptions( InvokableInterfaceDescription interfaceDescription, MetadataModel metadataModel, LibraryTypes libraryTypes) { var fields = new List <GeneratedFieldDescription>(); // Add a codec field for any method parameter which does not have a static codec. var allTypes = interfaceDescription.Methods .Where(method => method.MethodTypeParameters.Count == 0) .SelectMany(method => metadataModel.GeneratedInvokables[method].Members); fields.AddRange(GetCopierFieldDescriptions(allTypes, libraryTypes)); return(fields); }
private static IEnumerable <MemberDeclarationSyntax> CreateProxyMethods( LibraryTypes libraryTypes, InvokableInterfaceDescription interfaceDescription, MetadataModel metadataModel) { foreach (var methodDescription in interfaceDescription.Methods) { yield return(CreateProxyMethod(methodDescription)); } MethodDeclarationSyntax CreateProxyMethod(MethodDescription methodDescription) { var method = methodDescription.Method; var declaration = MethodDeclaration(method.ReturnType.ToTypeSyntax(methodDescription.TypeParameterSubstitutions), method.Name.EscapeIdentifier()) .AddParameterListParameters(method.Parameters.Select((p, i) => GetParameterSyntax(i, p, methodDescription.TypeParameterSubstitutions)).ToArray()) .WithBody( CreateAsyncProxyMethodBody(libraryTypes, metadataModel, methodDescription)); if (methodDescription.HasCollision) { declaration = declaration.WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))); // Type parameter constrains are not valid on explicit interface definitions var typeParameters = SyntaxFactoryUtility.GetTypeParameterConstraints(methodDescription.MethodTypeParameters); foreach (var(name, constraints) in typeParameters) { if (constraints.Count > 0) { declaration = declaration.AddConstraintClauses( TypeParameterConstraintClause(name).AddConstraints(constraints.ToArray())); } } } else { var explicitInterfaceSpecifier = ExplicitInterfaceSpecifier(methodDescription.Method.ContainingType.ToNameSyntax()); declaration = declaration.WithExplicitInterfaceSpecifier(explicitInterfaceSpecifier); } if (methodDescription.MethodTypeParameters.Count > 0) { declaration = declaration.WithTypeParameterList( TypeParameterList(SeparatedList(methodDescription.MethodTypeParameters.Select(tp => TypeParameter(tp.Name))))); } return(declaration); } }
public static ClassDeclarationSyntax GenerateActivator(LibraryTypes libraryTypes, ISerializableTypeDescription type) { var simpleClassName = GetSimpleClassName(type); var baseInterface = libraryTypes.IActivator_1.ToTypeSyntax(type.TypeSyntax); var orderedFields = new List <ConstructorArgument>(); var index = 0; if (type.ActivatorConstructorParameters is { Count : > 0 } parameters) { foreach (var arg in parameters) { orderedFields.Add(new ConstructorArgument { Type = arg, FieldName = $"_arg{index}", ParameterName = $"arg{index}" }); index++; } } var members = new List <MemberDeclarationSyntax>(); foreach (var field in orderedFields) { members.Add( FieldDeclaration(VariableDeclaration(field.Type, SingletonSeparatedList(VariableDeclarator(field.FieldName)))) .AddModifiers( Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))); } members.Add(GenerateConstructor(libraryTypes, simpleClassName, orderedFields)); members.Add(GenerateCreateMethod(libraryTypes, type, orderedFields)); var classDeclaration = ClassDeclaration(simpleClassName) .AddBaseListTypes(SimpleBaseType(baseInterface)) .AddModifiers(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.SealedKeyword)) .AddAttributeLists(AttributeList(SingletonSeparatedList(Attribute(libraryTypes.RegisterActivatorAttribute.ToNameSyntax())))) .AddAttributeLists(AttributeList(SingletonSeparatedList(CodeGenerator.GetGeneratedCodeAttributeSyntax()))) .AddMembers(members.ToArray()); if (type.IsGenericType) { classDeclaration = SyntaxFactoryUtility.AddGenericTypeParameters(classDeclaration, type.TypeParameters); } return(classDeclaration); }
public static List <AttributeListSyntax> GenerateSyntax(LibraryTypes wellKnownTypes, MetadataModel model) { var attributes = new List <AttributeListSyntax>(); foreach (var assemblyName in model.ApplicationParts) { // Generate an assembly-level attribute with an instance of that class. var attribute = AttributeList( AttributeTargetSpecifier(Token(SyntaxKind.AssemblyKeyword)), SingletonSeparatedList( Attribute(wellKnownTypes.ApplicationPartAttribute.ToNameSyntax()) .AddArgumentListArguments(AttributeArgument(assemblyName.GetLiteralExpression())))); attributes.Add(attribute); } return(attributes); }
public SerializableTypeDescription(SemanticModel semanticModel, INamedTypeSymbol type, IEnumerable <IMemberDescription> members, LibraryTypes libraryTypes) { Type = type; Members = members.ToList(); SemanticModel = semanticModel; _libraryTypes = libraryTypes; var t = type; Accessibility accessibility = t.DeclaredAccessibility; while (t is not null) { if ((int)t.DeclaredAccessibility < (int)accessibility) { accessibility = t.DeclaredAccessibility; } t = t.ContainingType; } Accessibility = accessibility; TypeParameters = new(); var names = new HashSet <string>(StringComparer.Ordinal); foreach (var tp in type.GetAllTypeParameters()) { var tpName = GetTypeParameterName(names, tp); TypeParameters.Add((tpName, tp)); } SerializationHooks = new(); if (type.GetAttributes(libraryTypes.SerializationCallbacksAttribute, out var hookAttributes)) { foreach (var hookAttribute in hookAttributes) { var hookType = (INamedTypeSymbol)hookAttribute.ConstructorArguments[0].Value; SerializationHooks.Add(hookType); } } if (TryGetActivatorConstructor(type, _libraryTypes, out var constructorParameters)) { HasActivatorConstructor = true; ActivatorConstructorParameters = constructorParameters; }
public static ClassDeclarationSyntax GenerateCopier( LibraryTypes libraryTypes, ISerializableTypeDescription type) { var simpleClassName = GetSimpleClassName(type); var members = new List <ISerializableMember>(); foreach (var member in type.Members) { if (member is ISerializableMember serializable) { members.Add(serializable); } else if (member is IFieldDescription or IPropertyDescription) { members.Add(new SerializableMember(libraryTypes, type, member, members.Count)); }
public static bool IsUnionCase(LibraryTypes libraryTypes, INamedTypeSymbol symbol, out INamedTypeSymbol sumType) { sumType = default; var compilationAttributeType = libraryTypes.FSharpCompilationMappingAttributeOrDefault; var sourceConstructFlagsType = libraryTypes.FSharpSourceConstructFlagsOrDefault; var baseType = symbol.BaseType; if (compilationAttributeType is null || sourceConstructFlagsType is null || baseType is null) { return(false); } if (!baseType.GetAttributes(compilationAttributeType, out var compilationAttributes) || compilationAttributes.Length == 0) { return(false); } var compilationAttribute = compilationAttributes[0]; var foundArg = false; TypedConstant sourceConstructFlagsArgument = default; foreach (var arg in compilationAttribute.ConstructorArguments) { if (SymbolEqualityComparer.Default.Equals(arg.Type, sourceConstructFlagsType)) { sourceConstructFlagsArgument = arg; foundArg = true; break; } } if (!foundArg) { return(false); } if ((int)sourceConstructFlagsArgument.Value != SourceConstructFlagsSumTypeValue) { return(false); } sumType = baseType; return(true); }
private static IEnumerable <IMemberDescription> GetRecordDataMembers(LibraryTypes libraryTypes, INamedTypeSymbol symbol) { List <(IPropertySymbol, ushort)> dataMembers = new(); foreach (var property in symbol.GetDeclaredInstanceMembers <IPropertySymbol>()) { var id = CodeGenerator.GetId(libraryTypes, property); if (!id.HasValue) { continue; } dataMembers.Add((property, id.Value)); } foreach (var(property, id) in dataMembers) { yield return(new FSharpRecordPropertyDescription(libraryTypes, property, id)); } }
public FSharpRecordPropertyDescription(LibraryTypes libraryTypes, IPropertySymbol property, ushort ordinal) { _libraryTypes = libraryTypes; FieldId = ordinal; _property = property; }
public FSharpRecordTypeDescription(SemanticModel semanticModel, INamedTypeSymbol type, LibraryTypes libraryTypes) : base(semanticModel, type, GetRecordDataMembers(libraryTypes, type), libraryTypes) { }
private static BlockSyntax CreateAsyncProxyMethodBody( LibraryTypes libraryTypes, MetadataModel metadataModel, MethodDescription methodDescription) { var statements = new List <StatementSyntax>(); var requestVar = IdentifierName("request"); var requestDescription = metadataModel.GeneratedInvokables[methodDescription]; var createRequestExpr = InvocationExpression(ThisExpression().Member("GetInvokable", requestDescription.TypeSyntax)) .WithArgumentList(ArgumentList(SeparatedList <ArgumentSyntax>())); statements.Add( LocalDeclarationStatement( VariableDeclaration( ParseTypeName("var"), SingletonSeparatedList( VariableDeclarator( Identifier("request")) .WithInitializer( EqualsValueClause(createRequestExpr)))))); // Set request object fields from method parameters. var parameterIndex = 0; foreach (var parameter in methodDescription.Method.Parameters) { statements.Add( ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, requestVar.Member($"arg{parameterIndex}"), IdentifierName(SyntaxFactoryUtility.GetSanitizedName(parameter, parameterIndex))))); parameterIndex++; } var invokeMethodName = "InvokeAsync"; foreach (var attr in methodDescription.Method.GetAttributes()) { if (attr.AttributeClass.GetAttributes(libraryTypes.InvokeMethodNameAttribute, out var attrs)) { foreach (var methodAttr in attrs) { invokeMethodName = (string)methodAttr.ConstructorArguments.First().Value; } } } ITypeSymbol resultType; var methodReturnType = (INamedTypeSymbol)methodDescription.Method.ReturnType; if (methodReturnType.TypeArguments.Length == 1) { // Task<T> / ValueTask<T> resultType = methodReturnType.TypeArguments[0]; } else if (SymbolEqualityComparer.Default.Equals(methodReturnType, libraryTypes.Void)) { // void resultType = libraryTypes.Object; } else { // Task / ValueTask resultType = libraryTypes.Object; } // C#: base.InvokeAsync<TReturn>(request); var invocationExpression = InvocationExpression( BaseExpression().Member(invokeMethodName, resultType.ToTypeSyntax(methodDescription.TypeParameterSubstitutions)), ArgumentList(SeparatedList(new[] { Argument(requestVar) }))); var rt = methodReturnType.ConstructedFrom; if (SymbolEqualityComparer.Default.Equals(rt, libraryTypes.Task_1) || SymbolEqualityComparer.Default.Equals(methodReturnType, libraryTypes.Task)) { // C#: return <invocation>.AsTask() statements.Add(ReturnStatement(InvocationExpression(invocationExpression.Member("AsTask"), ArgumentList()))); } else if (SymbolEqualityComparer.Default.Equals(rt, libraryTypes.ValueTask_1)) { // C#: return <invocation> statements.Add(ReturnStatement(invocationExpression)); } else if (SymbolEqualityComparer.Default.Equals(methodReturnType, libraryTypes.ValueTask)) { // C#: return new ValueTask(<invocation>) statements.Add(ReturnStatement(ObjectCreationExpression(libraryTypes.ValueTask.ToTypeSyntax()).WithArgumentList(ArgumentList(SeparatedList(new[] { Argument(InvocationExpression(invocationExpression.Member("AsTask"), ArgumentList())) }))))); } else { // C#: _ = <invocation> statements.Add(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName("_"), invocationExpression))); } return(Block(statements)); }
public static (ClassDeclarationSyntax, GeneratedInvokerDescription) Generate( LibraryTypes libraryTypes, InvokableInterfaceDescription interfaceDescription, MethodDescription method) { var generatedClassName = GetSimpleClassName(interfaceDescription, method); INamedTypeSymbol baseClassType = GetBaseClassType(method); var fieldDescriptions = GetFieldDescriptions(method, interfaceDescription); var fields = GetFieldDeclarations(method, fieldDescriptions, libraryTypes); var(ctor, ctorArgs) = GenerateConstructor(libraryTypes, generatedClassName, method, fieldDescriptions, baseClassType); Accessibility accessibility = GetAccessibility(interfaceDescription); var targetField = fieldDescriptions.OfType <TargetFieldDescription>().Single(); var accessibilityKind = accessibility switch { Accessibility.Public => SyntaxKind.PublicKeyword, _ => SyntaxKind.InternalKeyword, }; var classDeclaration = ClassDeclaration(generatedClassName) .AddBaseListTypes(SimpleBaseType(baseClassType.ToTypeSyntax(method.TypeParameterSubstitutions))) .AddModifiers(Token(accessibilityKind), Token(SyntaxKind.SealedKeyword), Token(SyntaxKind.PartialKeyword)) .AddAttributeLists( AttributeList(SingletonSeparatedList(CodeGenerator.GetGeneratedCodeAttributeSyntax()))) .AddMembers(fields) .AddMembers(ctor) .AddMembers( GenerateGetArgumentCount(libraryTypes, method), GenerateGetMethodName(libraryTypes, method), GenerateGetInterfaceName(libraryTypes, method), GenerateGetInterfaceType(libraryTypes, method), GenerateGetInterfaceTypeArguments(libraryTypes, method), GenerateGetMethodTypeArguments(libraryTypes, method), GenerateGetParameterTypes(libraryTypes, method), GenerateGetMethod(libraryTypes), GenerateSetTargetMethod(libraryTypes, interfaceDescription, targetField), GenerateGetTargetMethod(targetField), GenerateDisposeMethod(libraryTypes, method, fieldDescriptions, baseClassType), GenerateGetArgumentMethod(libraryTypes, method, fieldDescriptions), GenerateSetArgumentMethod(libraryTypes, method, fieldDescriptions), GenerateInvokeInnerMethod(libraryTypes, method, fieldDescriptions, targetField)); var typeParametersWithNames = method.AllTypeParameters; if (typeParametersWithNames.Count > 0) { classDeclaration = SyntaxFactoryUtility.AddGenericTypeParameters(classDeclaration, typeParametersWithNames); } List <INamedTypeSymbol> serializationHooks = new(); if (baseClassType.GetAttributes(libraryTypes.SerializationCallbacksAttribute, out var hookAttributes)) { foreach (var hookAttribute in hookAttributes) { var hookType = (INamedTypeSymbol)hookAttribute.ConstructorArguments[0].Value; serializationHooks.Add(hookType); } } var invokerDescription = new GeneratedInvokerDescription( interfaceDescription, method, accessibility, generatedClassName, fieldDescriptions.OfType <IMemberDescription>().ToList(), serializationHooks, baseClassType, ctorArgs); return(classDeclaration, invokerDescription);
public static ClassDeclarationSyntax GenerateCopier( LibraryTypes libraryTypes, ISerializableTypeDescription type) { var simpleClassName = GetSimpleClassName(type); var members = new List <ISerializableMember>(); foreach (var member in type.Members) { if (member is ISerializableMember serializable) { members.Add(serializable); } else if (member is IFieldDescription field) { members.Add(new SerializableMember(libraryTypes, type, field, members.Count)); } else if (member is MethodParameterFieldDescription methodParameter) { members.Add(new SerializableMethodMember(methodParameter)); } } var accessibility = type.Accessibility switch { Accessibility.Public => SyntaxKind.PublicKeyword, _ => SyntaxKind.InternalKeyword, }; var classDeclaration = ClassDeclaration(simpleClassName) .AddBaseListTypes(SimpleBaseType(libraryTypes.DeepCopier_1.ToTypeSyntax(type.TypeSyntax))) .AddModifiers(Token(accessibility), Token(SyntaxKind.SealedKeyword)) .AddAttributeLists(AttributeList(SingletonSeparatedList(CodeGenerator.GetGeneratedCodeAttributeSyntax()))); if (type.IsImmutable) { var copyMethod = GenerateImmutableTypeCopyMethod(type, libraryTypes); classDeclaration = classDeclaration.AddMembers(copyMethod); } else { var fieldDescriptions = GetFieldDescriptions(type, members, libraryTypes); var fieldDeclarations = GetFieldDeclarations(fieldDescriptions); var ctor = GenerateConstructor(libraryTypes, simpleClassName, fieldDescriptions); var copyMethod = GenerateMemberwiseDeepCopyMethod(type, fieldDescriptions, members, libraryTypes); classDeclaration = classDeclaration .AddMembers(copyMethod) .AddMembers(fieldDeclarations) .AddMembers(ctor); if (!type.IsSealedType) { classDeclaration = classDeclaration .AddMembers(GenerateBaseCopierDeepCopyMethod(type, fieldDescriptions, members, libraryTypes)) .AddBaseListTypes(SimpleBaseType(libraryTypes.BaseCopier_1.ToTypeSyntax(type.TypeSyntax))); } } if (type.IsGenericType) { classDeclaration = SyntaxFactoryUtility.AddGenericTypeParameters(classDeclaration, type.TypeParameters); } return(classDeclaration); }
public static ClassDeclarationSyntax GenerateMetadata(Compilation compilation, MetadataModel metadataModel, LibraryTypes libraryTypes) { var configParam = "config".ToIdentifierName(); var addSerializerMethod = configParam.Member("Serializers").Member("Add"); var addCopierMethod = configParam.Member("Copiers").Member("Add"); var body = new List <StatementSyntax>(); body.AddRange( metadataModel.SerializableTypes.Select( type => (StatementSyntax)ExpressionStatement( InvocationExpression( addSerializerMethod, ArgumentList( SingletonSeparatedList( Argument(TypeOfExpression(GetCodecTypeName(type))))))) )); body.AddRange( metadataModel.SerializableTypes.Select( type => (StatementSyntax)ExpressionStatement( InvocationExpression( addCopierMethod, ArgumentList( SingletonSeparatedList( Argument(TypeOfExpression(GetCopierTypeName(type))))))) )); body.AddRange( metadataModel.DetectedCopiers.Select( type => (StatementSyntax)ExpressionStatement( InvocationExpression( addCopierMethod, ArgumentList( SingletonSeparatedList( Argument(TypeOfExpression(type.ToOpenTypeSyntax())))))) )); body.AddRange( metadataModel.DetectedSerializers.Select( type => (StatementSyntax)ExpressionStatement( InvocationExpression( addSerializerMethod, ArgumentList( SingletonSeparatedList( Argument(TypeOfExpression(type.ToOpenTypeSyntax())))))) )); var addProxyMethod = configParam.Member("InterfaceProxies").Member("Add"); body.AddRange( metadataModel.GeneratedProxies.Select( type => (StatementSyntax)ExpressionStatement( InvocationExpression( addProxyMethod, ArgumentList( SingletonSeparatedList( Argument(TypeOfExpression(type.TypeSyntax)))))) )); var addInvokableInterfaceMethod = configParam.Member("Interfaces").Member("Add"); body.AddRange( metadataModel.InvokableInterfaces.Select( type => (StatementSyntax)ExpressionStatement( InvocationExpression( addInvokableInterfaceMethod, ArgumentList( SingletonSeparatedList( Argument(TypeOfExpression(type.InterfaceType.ToOpenTypeSyntax())))))) )); var addInvokableInterfaceImplementationMethod = configParam.Member("InterfaceImplementations").Member("Add"); body.AddRange( metadataModel.InvokableInterfaceImplementations.Select( type => (StatementSyntax)ExpressionStatement( InvocationExpression( addInvokableInterfaceImplementationMethod, ArgumentList( SingletonSeparatedList( Argument(TypeOfExpression(type.ToOpenTypeSyntax())))))) )); var addActivatorMethod = configParam.Member("Activators").Member("Add"); body.AddRange( metadataModel.ActivatableTypes.Select( type => (StatementSyntax)ExpressionStatement( InvocationExpression( addActivatorMethod, ArgumentList( SingletonSeparatedList( Argument(TypeOfExpression(GetActivatorTypeName(type))))))) )); body.AddRange( metadataModel.DetectedActivators.Select( type => (StatementSyntax)ExpressionStatement( InvocationExpression( addActivatorMethod, ArgumentList( SingletonSeparatedList( Argument(TypeOfExpression(type.ToOpenTypeSyntax())))))) )); var addWellKnownTypeIdMethod = configParam.Member("WellKnownTypeIds").Member("Add"); body.AddRange( metadataModel.WellKnownTypeIds.Select( type => (StatementSyntax)ExpressionStatement( InvocationExpression( addWellKnownTypeIdMethod, ArgumentList(SeparatedList( new[] { Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(type.Id))), Argument(TypeOfExpression(type.Type)) })))) )); var addTypeAliasMethod = configParam.Member("WellKnownTypeAliases").Member("Add"); body.AddRange( metadataModel.TypeAliases.Select( type => (StatementSyntax)ExpressionStatement( InvocationExpression( addTypeAliasMethod, ArgumentList(SeparatedList( new[] { Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(type.Alias))), Argument(TypeOfExpression(type.Type)) })))) )); var configType = libraryTypes.TypeManifestOptions; var configureMethod = MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), "Configure") .AddModifiers(Token(SyntaxKind.PublicKeyword)) .AddParameterListParameters( Parameter(configParam.Identifier).WithType(configType.ToTypeSyntax())) .AddBodyStatements(body.ToArray()); var interfaceType = libraryTypes.ITypeManifestProvider; return(ClassDeclaration("Metadata_" + SyntaxGeneration.Identifier.SanitizeIdentifierName(compilation.AssemblyName)) .AddBaseListTypes(SimpleBaseType(interfaceType.ToTypeSyntax())) .AddModifiers(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.SealedKeyword)) .AddAttributeLists(AttributeList(SingletonSeparatedList(CodeGenerator.GetGeneratedCodeAttributeSyntax()))) .AddMembers(configureMethod)); }
private static BlockSyntax CreateProxyMethodBody( LibraryTypes libraryTypes, MetadataModel metadataModel, MethodDescription methodDescription) { var statements = new List <StatementSyntax>(); var completionVar = IdentifierName("completion"); var requestVar = IdentifierName("request"); var requestDescription = metadataModel.GeneratedInvokables[methodDescription]; var createRequestExpr = InvocationExpression(libraryTypes.InvokablePool.ToTypeSyntax().Member("Get", requestDescription.TypeSyntax)) .WithArgumentList(ArgumentList(SeparatedList <ArgumentSyntax>())); statements.Add( LocalDeclarationStatement( VariableDeclaration( ParseTypeName("var"), SingletonSeparatedList( VariableDeclarator( Identifier("request")) .WithInitializer( EqualsValueClause(createRequestExpr)))))); // Set request object fields from method parameters. var parameterIndex = 0; foreach (var parameter in methodDescription.Method.Parameters) { statements.Add( ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, requestVar.Member($"arg{parameterIndex}"), IdentifierName(SyntaxFactoryUtility.GetSanitizedName(parameter, parameterIndex))))); parameterIndex++; } ITypeSymbol returnType; var methodReturnType = (INamedTypeSymbol)methodDescription.Method.ReturnType; if (methodReturnType.TypeParameters.Length == 1) { returnType = methodReturnType.TypeArguments[0]; } else { returnType = libraryTypes.Object; } var createCompletionExpr = InvocationExpression(libraryTypes.ResponseCompletionSourcePool.ToTypeSyntax().Member("Get", returnType.ToTypeSyntax(methodDescription.TypeParameterSubstitutions))) .WithArgumentList(ArgumentList(SeparatedList <ArgumentSyntax>())); statements.Add( LocalDeclarationStatement( VariableDeclaration( ParseTypeName("var"), SingletonSeparatedList( VariableDeclarator( Identifier("completion")) .WithInitializer( EqualsValueClause(createCompletionExpr)))))); var sendRequestMethodName = "SendRequest"; foreach (var attr in methodDescription.Method.GetAttributes()) { if (attr.AttributeClass.GetAttributes(libraryTypes.InvokeMethodNameAttribute, out var attrs)) { foreach (var methodAttr in attrs) { sendRequestMethodName = (string)methodAttr.ConstructorArguments.First().Value; } } } // Issue request statements.Add( ExpressionStatement( InvocationExpression( BaseExpression().Member(sendRequestMethodName), ArgumentList(SeparatedList(new[] { Argument(completionVar), Argument(requestVar) }))))); // Return result string valueTaskMethodName; if (methodReturnType.TypeArguments.Length == 1) { valueTaskMethodName = "AsValueTask"; } else if (SymbolEqualityComparer.Default.Equals(methodReturnType, libraryTypes.Void)) { valueTaskMethodName = null; } else { valueTaskMethodName = "AsVoidValueTask"; } if (valueTaskMethodName is not null) { var returnVal = InvocationExpression(completionVar.Member(valueTaskMethodName)); if (SymbolEqualityComparer.Default.Equals(methodReturnType.ConstructedFrom, libraryTypes.Task_1) || SymbolEqualityComparer.Default.Equals(methodReturnType, libraryTypes.Task)) { returnVal = InvocationExpression(returnVal.Member("AsTask")); } statements.Add(ReturnStatement(returnVal)); } return(Block(statements)); }