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 TypeSyntax GetProxyTypeName(InvokableInterfaceDescription interfaceDescription) { var interfaceType = interfaceDescription.InterfaceType; var genericArity = interfaceType.GetAllTypeParameters().Count(); var name = ProxyGenerator.GetSimpleClassName(interfaceDescription); if (genericArity > 0) { name += $"<{new string(',', genericArity - 1)}>"; } return(ParseTypeName(interfaceDescription.GeneratedNamespace + "." + name)); }
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 MethodDescription(InvokableInterfaceDescription containingType, IMethodSymbol method, string name, bool hasCollision) { _iface = containingType; Method = method; Name = name; HasCollision = hasCollision; var names = new HashSet <string>(StringComparer.Ordinal); AllTypeParameters = new List <(string Name, ITypeParameterSymbol Parameter)>(); MethodTypeParameters = new List <(string Name, ITypeParameterSymbol Parameter)>(); foreach (var tp in _iface.InterfaceType.GetAllTypeParameters()) { var tpName = GetTypeParameterName(names, tp); AllTypeParameters.Add((tpName, tp)); } foreach (var tp in method.TypeParameters) { var tpName = GetTypeParameterName(names, tp); AllTypeParameters.Add((tpName, tp)); MethodTypeParameters.Add((tpName, tp)); } #pragma warning disable RS1024 // Compare symbols correctly TypeParameterSubstitutions = new(SymbolEqualityComparer.Default); #pragma warning restore RS1024 // Compare symbols correctly foreach (var tp in AllTypeParameters) { TypeParameterSubstitutions[tp.Parameter] = tp.Name; } #pragma warning disable RS1024 // Compare symbols correctly InvokableBaseTypes = new Dictionary <INamedTypeSymbol, INamedTypeSymbol>(SymbolEqualityComparer.Default); #pragma warning restore RS1024 // Compare symbols correctly // Set defaults from the interface type. foreach (var pair in containingType.InvokableBaseTypes) { InvokableBaseTypes[pair.Key] = pair.Value; } // Set overrides from user-defined attributes on the method. PopulateOverrides(containingType, method);
static Accessibility GetAccessibility(InvokableInterfaceDescription interfaceDescription) { var t = interfaceDescription.InterfaceType; Accessibility accessibility = t.DeclaredAccessibility; while (t is not null) { if ((int)t.DeclaredAccessibility < (int)accessibility) { accessibility = t.DeclaredAccessibility; } t = t.ContainingType; } return(accessibility); }
public GeneratedInvokerDescription( InvokableInterfaceDescription interfaceDescription, MethodDescription methodDescription, Accessibility accessibility, string generatedClassName, List <IMemberDescription> members, List <INamedTypeSymbol> serializationHooks, INamedTypeSymbol baseType, List <TypeSyntax> constructorArguments) { InterfaceDescription = interfaceDescription; _methodDescription = methodDescription; BaseType = baseType; Name = generatedClassName; Members = members; Accessibility = accessibility; SerializationHooks = serializationHooks; ActivatorConstructorParameters = constructorArguments; }
public GeneratedProxyDescription(InvokableInterfaceDescription interfaceDescription) { InterfaceDescription = interfaceDescription; TypeSyntax = GetProxyTypeName(interfaceDescription); }
public static string GetSimpleClassName(InvokableInterfaceDescription interfaceDescription) => $"Proxy_{interfaceDescription.Name}";
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);