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); } }
/// <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); }
/// <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 }); }
/// <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); }