Beispiel #1
0
        private static void ConsiderType(
            Type type,
            bool runtime,
            Assembly targetAssembly,
            ISet <Type> includedTypes)
        {
            // The module containing the serializer.
            var module   = runtime ? null : type.Module;
            var typeInfo = type.GetTypeInfo();

            // Every type which is encountered must be considered for serialization.
            if (!typeInfo.IsNested && !typeInfo.IsGenericParameter && typeInfo.IsSerializable)
            {
                // If a type was encountered which can be accessed, process it for serialization.
                if (SerializerGenerationManager.RecordTypeToGenerate(type, module, targetAssembly))
                {
                    includedTypes.Add(type);
                }
            }

            // Collect the types which require code generation.
            if (GrainInterfaceData.IsGrainInterface(type))
            {
                if (Logger.IsVerbose2)
                {
                    Logger.Verbose2("Will generate code for: {0}", type.GetParseableName());
                }

                includedTypes.Add(type);
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="RoslynCodeGenerator"/> class.
        /// </summary>
        /// <param name="serializationManager">The serialization manager.</param>
        /// <param name="loggerFactory">logger factory to use</param>
        public RoslynCodeGenerator(SerializationManager serializationManager, ApplicationPartManager applicationPartManager, ILoggerFactory loggerFactory)
        {
            this.knownTypes = GetKnownTypes();
            this.serializerGenerationManager = new SerializerGenerationManager(serializationManager, loggerFactory);
            Logger = new LoggerWrapper <RoslynCodeGenerator>(loggerFactory);

            HashSet <string> GetKnownTypes()
            {
                var serializerFeature = applicationPartManager.CreateAndPopulateFeature <SerializerFeature>();

                var result = new HashSet <string>();

                foreach (var kt in serializerFeature.KnownTypes)
                {
                    result.Add(kt.Type);
                }
                foreach (var serializer in serializerFeature.SerializerTypes)
                {
                    result.Add(RuntimeTypeNameFormatter.Format(serializer.Target));
                    result.Add(RuntimeTypeNameFormatter.Format(serializer.Serializer));
                }

                foreach (var serializer in serializerFeature.SerializerDelegates)
                {
                    result.Add(RuntimeTypeNameFormatter.Format(serializer.Target));
                }

                return(result);
            }
        }
 private static void RecordType(Type type, Module module, Assembly targetAssembly, ISet <Type> includedTypes)
 {
     if (SerializerGenerationManager.RecordTypeToGenerate(type, module, targetAssembly))
     {
         includedTypes.Add(type);
     }
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="RoslynCodeGenerator"/> class.
        /// </summary>
        /// <param name="partManager"></param>
        /// <param name="loggerFactory">The logger factory.</param>
        public RoslynCodeGenerator(IApplicationPartManager partManager, ILoggerFactory loggerFactory)
        {
            var serializerFeature     = partManager.CreateAndPopulateFeature <SerializerFeature>();
            var grainClassFeature     = partManager.CreateAndPopulateFeature <GrainClassFeature>();
            var grainInterfaceFeature = partManager.CreateAndPopulateFeature <GrainInterfaceFeature>();

            this.knownTypes        = GetKnownTypes();
            this.serializableTypes = new SerializerGenerationManager(GetExistingSerializers(), loggerFactory);
            this.logger            = loggerFactory.CreateLogger <RoslynCodeGenerator>();

            var knownInterfaces = grainInterfaceFeature.Interfaces.Select(i => i.InterfaceType);
            var knownClasses    = grainClassFeature.Classes.Select(c => c.ClassType);

            this.knownGrainTypes = new HashSet <Type>(knownInterfaces.Concat(knownClasses));

            HashSet <string> GetKnownTypes()
            {
                var result = new HashSet <string>();

                foreach (var kt in serializerFeature.KnownTypes)
                {
                    result.Add(kt.Type);
                }
                foreach (var serializer in serializerFeature.SerializerTypes)
                {
                    result.Add(RuntimeTypeNameFormatter.Format(serializer.Target));
                    result.Add(RuntimeTypeNameFormatter.Format(serializer.Serializer));
                }

                foreach (var serializer in serializerFeature.SerializerDelegates)
                {
                    result.Add(RuntimeTypeNameFormatter.Format(serializer.Target));
                }

                return(result);
            }

            HashSet <Type> GetExistingSerializers()
            {
                var result = new HashSet <Type>();

                foreach (var serializer in serializerFeature.SerializerDelegates)
                {
                    result.Add(serializer.Target);
                }

                foreach (var serializer in serializerFeature.SerializerTypes)
                {
                    result.Add(serializer.Target);
                }

                return(result);
            }
        }
Beispiel #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RoslynCodeGenerator"/> class.
 /// </summary>
 /// <param name="serializationManager">The serialization manager.</param>
 public RoslynCodeGenerator(SerializationManager serializationManager)
 {
     this.serializerGenerationManager = new SerializerGenerationManager(serializationManager);
 }
Beispiel #6
0
        /// <summary>
        /// Generates a syntax tree for the provided assemblies.
        /// </summary>
        /// <param name="assemblies">The assemblies to generate code for.</param>
        /// <param name="runtime">Whether or not runtime code generation is being performed.</param>
        /// <returns>The generated syntax tree.</returns>
        private static GeneratedSyntax GenerateForAssemblies(List <Assembly> assemblies, bool runtime)
        {
            if (Logger.IsVerbose)
            {
                Logger.Verbose(
                    "Generating code for assemblies: {0}",
                    string.Join(", ", assemblies.Select(_ => _.FullName)));
            }

            Assembly       targetAssembly;
            HashSet <Type> ignoredTypes;

            if (runtime)
            {
                // Ignore types which have already been accounted for.
                ignoredTypes = CodeGeneratorCommon.GetTypesWithImplementations(
                    typeof(MethodInvokerAttribute),
                    typeof(GrainReferenceAttribute),
                    typeof(GrainStateAttribute),
                    typeof(SerializerAttribute));
                targetAssembly = null;
            }
            else
            {
                ignoredTypes   = new HashSet <Type>();
                targetAssembly = assemblies.FirstOrDefault();
            }

            var members = new List <MemberDeclarationSyntax>();

            // Get types from assemblies which reference Orleans and are not generated assemblies.
            var includedTypes = new HashSet <Type>();

            foreach (var type in assemblies.SelectMany(_ => _.GetTypes()))
            {
                // The module containing the serializer.
                var module = runtime ? null : type.Module;

                // Every type which is encountered must be considered for serialization.
                if (!type.IsNested && !type.IsGenericParameter && type.IsSerializable)
                {
                    // If a type was encountered which can be accessed, process it for serialization.
                    var isAccessibleForSerialization =
                        !TypeUtilities.IsTypeIsInaccessibleForSerialization(type, module, targetAssembly);
                    if (isAccessibleForSerialization)
                    {
                        includedTypes.Add(type);
                        SerializerGenerationManager.RecordTypeToGenerate(type);
                    }
                }

                // Collect the types which require code generation.
                if (GrainInterfaceData.IsGrainInterface(type))
                {
                    if (Logger.IsVerbose2)
                    {
                        Logger.Verbose2("Will generate code for: {0}", type.GetParseableName());
                    }

                    includedTypes.Add(type);
                }
            }

            includedTypes.RemoveWhere(_ => ignoredTypes.Contains(_));

            // Group the types by namespace and generate the required code in each namespace.
            foreach (var group in includedTypes.GroupBy(_ => CodeGeneratorCommon.GetGeneratedNamespace(_)))
            {
                var namespaceMembers = new List <MemberDeclarationSyntax>();
                foreach (var type in group)
                {
                    // The module containing the serializer.
                    var module = runtime ? null : type.Module;

                    // Every type which is encountered must be considered for serialization.
                    Action <Type> onEncounteredType = encounteredType =>
                    {
                        // If a type was encountered which can be accessed, process it for serialization.
                        var isAccessibleForSerialization =
                            !TypeUtilities.IsTypeIsInaccessibleForSerialization(encounteredType, module, targetAssembly);
                        if (isAccessibleForSerialization)
                        {
                            SerializerGenerationManager.RecordTypeToGenerate(encounteredType);
                        }
                    };

                    if (Logger.IsVerbose2)
                    {
                        Logger.Verbose2("Generating code for: {0}", type.GetParseableName());
                    }

                    if (GrainInterfaceData.IsGrainInterface(type))
                    {
                        if (Logger.IsVerbose2)
                        {
                            Logger.Verbose2(
                                "Generating GrainReference and MethodInvoker for {0}",
                                type.GetParseableName());
                        }

                        namespaceMembers.Add(GrainReferenceGenerator.GenerateClass(type, onEncounteredType));
                        namespaceMembers.Add(GrainMethodInvokerGenerator.GenerateClass(type));
                    }

                    // Generate serializers.
                    var  first = true;
                    Type toGen;
                    while (SerializerGenerationManager.GetNextTypeToProcess(out toGen))
                    {
                        // Filter types which are inaccessible by the serialzation module/assembly.
                        var skipSerialzerGeneration =
                            toGen.GetAllFields()
                            .Any(
                                field =>
                                TypeUtilities.IsTypeIsInaccessibleForSerialization(
                                    field.FieldType,
                                    module,
                                    targetAssembly));
                        if (skipSerialzerGeneration)
                        {
                            continue;
                        }

                        if (!runtime)
                        {
                            if (first)
                            {
                                ConsoleText.WriteStatus("ClientGenerator - Generating serializer classes for types:");
                                first = false;
                            }

                            ConsoleText.WriteStatus(
                                "\ttype " + toGen.FullName + " in namespace " + toGen.Namespace
                                + " defined in Assembly " + toGen.Assembly.GetName());
                        }

                        if (Logger.IsVerbose2)
                        {
                            Logger.Verbose2(
                                "Generating & Registering Serializer for Type {0}",
                                toGen.GetParseableName());
                        }

                        namespaceMembers.AddRange(SerializerGenerator.GenerateClass(toGen, onEncounteredType));
                    }
                }

                if (namespaceMembers.Count == 0)
                {
                    if (Logger.IsVerbose)
                    {
                        Logger.Verbose2("Skipping namespace: {0}", group.Key);
                    }

                    continue;
                }

                members.Add(
                    SF.NamespaceDeclaration(SF.ParseName(group.Key))
                    .AddUsings(
                        TypeUtils.GetNamespaces(typeof(TaskUtility), typeof(GrainExtensions))
                        .Select(_ => SF.UsingDirective(SF.ParseName(_)))
                        .ToArray())
                    .AddMembers(namespaceMembers.ToArray()));
            }

            return(new GeneratedSyntax
            {
                SourceAssemblies = assemblies,
                Syntax = members.Count > 0 ? SF.CompilationUnit().AddMembers(members.ToArray()) : null
            });
        }
Beispiel #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RoslynCodeGenerator"/> class.
 /// </summary>
 /// <param name="serializationManager">The serialization manager.</param>
 /// <param name="loggerFactory">logger factory to use</param>
 public RoslynCodeGenerator(SerializationManager serializationManager, ILoggerFactory loggerFactory)
 {
     this.serializerGenerationManager = new SerializerGenerationManager(serializationManager, loggerFactory);
     this.Logger = new LoggerWrapper <RoslynCodeGenerator>(loggerFactory);
 }