示例#1
0
        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));
        }
示例#3
0
        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);
        }
示例#4
0
        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);
            }
        }
示例#5
0
        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);
示例#6
0
            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);
            }
示例#7
0
        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);
 }
示例#9
0
 public static string GetSimpleClassName(InvokableInterfaceDescription interfaceDescription) => $"Proxy_{interfaceDescription.Name}";
示例#10
0
        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);