private void AddAssemblyMetadata(AggregatedModel model)
        {
            var assembliesToScan = new List <IAssemblySymbol>();

            foreach (var asm in this.compilationAnalyzer.ReferencedAssemblies)
            {
                // Known assemblies are already handled.
                if (this.compilationAnalyzer.KnownAssemblies.Contains(asm))
                {
                    continue;
                }

                if (this.compilationAnalyzer.AssembliesExcludedFromCodeGeneration.Contains(asm) ||
                    this.compilationAnalyzer.AssembliesExcludedFromMetadataGeneration.Contains(asm))
                {
                    this.log.LogDebug($"Skipping adding known types for assembly {asm.Identity.Name} since a referenced assembly already includes its types.");
                    continue;
                }

                assembliesToScan.Add(asm);
            }

            foreach (var asm in assembliesToScan)
            {
                this.log.LogDebug($"Generating metadata for referenced assembly {asm.Identity.Name}.");
                foreach (var type in asm.GetDeclaredTypes())
                {
                    if (this.ValidForKnownTypes(type))
                    {
                        AddKnownType(model, type);
                    }
                }
            }
        }
示例#2
0
        private void AddAssemblyMetadata(AggregatedModel model)
        {
            var assembliesToScan = new List <IAssemblySymbol>();

            foreach (var asm in this.compilationAnalyzer.ReferencedAssemblies)
            {
                // Known assemblies are already handled.
                if (this.compilationAnalyzer.KnownAssemblies.Contains(asm))
                {
                    continue;
                }

                if (this.compilationAnalyzer.AssembliesExcludedFromCodeGeneration.Contains(asm) ||
                    this.compilationAnalyzer.AssembliesExcludedFromMetadataGeneration.Contains(asm))
                {
                    continue;
                }

                assembliesToScan.Add(asm);
            }

            foreach (var asm in assembliesToScan)
            {
                foreach (var type in asm.GetDeclaredTypes())
                {
                    if (this.ValidForKnownTypes(type))
                    {
                        AddKnownType(model, type);
                    }
                }
            }
        }
示例#3
0
        public async Task <AggregatedModel> RetrieveData(string serviceResource)
        {
            AggregatedModel aggregatedModel = new AggregatedModel();

            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(BaseUrl);

                client.DefaultRequestHeaders.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                //Sending request to find web api REST service resource using HttpClient
                HttpResponseMessage response = await client.GetAsync($"Api/movies/?{serviceResource}");

                //Checking the response is successful or not which is sent using HttpClient
                if (response.IsSuccessStatusCode)
                {
                    //Storing the response details recieved from web api
                    var aggregatedModelJson = response.Content.ReadAsStringAsync().Result;

                    //Deserializing the response recieved from web api and storing into the AggregatedModel list
                    aggregatedModel = JsonConvert.DeserializeObject <AggregatedModel>(aggregatedModelJson);
                }
            }
            return(aggregatedModel);
        }
示例#4
0
        private void ProcessGrainInterface(AggregatedModel model, INamedTypeSymbol type)
        {
            var accessible = this.semanticModelForAccessibility.IsAccessible(0, type);

            if (this.log.IsEnabled(LogLevel.Debug))
            {
                this.log.LogDebug($"Found grain interface: {type.ToDisplayString()} {(accessible ? "accessible" : "NOT accessible")}");
            }

            if (accessible)
            {
                var genericMethod = type.GetAllMembers <IMethodSymbol>().FirstOrDefault(m => m.IsGenericMethod);
                if (genericMethod != null && this.wellKnownTypes.GenericMethodInvoker is WellKnownTypes.None)
                {
                    if (this.log.IsEnabled(LogLevel.Warning))
                    {
                        var message = $"Grain interface {type} has a generic method, {genericMethod}." +
                                      " Support for generic methods requires the project to reference Microsoft.Orleans.Core, but this project does not reference it.";
                        this.log.LogError(message);
                        throw new CodeGenerationException(message);
                    }
                }

                var methods = GetGrainMethodDescriptions(type);

                model.GrainInterfaces.Add(new GrainInterfaceDescription(
                                              type,
                                              this.wellKnownTypes.GetTypeId(type),
                                              this.wellKnownTypes.GetVersion(type),
                                              methods));
            }

            // Returns a list of all methods in all interfaces on the provided type.
            IEnumerable <GrainMethodDescription> GetGrainMethodDescriptions(INamedTypeSymbol initialType)
            {
                IEnumerable <INamedTypeSymbol> GetAllInterfaces(INamedTypeSymbol s)
                {
                    if (s.TypeKind == TypeKind.Interface)
                    {
                        yield return(s);
                    }
                    foreach (var i in s.AllInterfaces)
                    {
                        yield return(i);
                    }
                }

                foreach (var iface in GetAllInterfaces(initialType))
                {
                    foreach (var member in iface.GetMembers())
                    {
                        if (!(member is IMethodSymbol method))
                        {
                            continue;
                        }
                        yield return(new GrainMethodDescription(this.wellKnownTypes.GetMethodId(method), method));
                    }
                }
            }
        }
示例#5
0
        private CompilationUnitSyntax GenerateSyntax(AggregatedModel model)
        {
            var namespaceGroupings = new Dictionary <INamespaceSymbol, List <MemberDeclarationSyntax> >();

            // Pass the relevent elements of the model to each of the code generators.
            foreach (var grainInterface in model.GrainInterfaces)
            {
                var nsMembers = GetNamespace(namespaceGroupings, grainInterface.Type.ContainingNamespace);
                nsMembers.Add(GrainMethodInvokerGenerator.GenerateClass(this.wellKnownTypes, grainInterface));
                nsMembers.Add(GrainReferenceGenerator.GenerateClass(this.wellKnownTypes, grainInterface));
            }

            var serializersToGenerate = model.Serializers.SerializerTypes
                                        .Where(s => s.SerializerTypeSyntax == null)
                                        .Distinct(SerializerTypeDescription.TargetComparer);

            foreach (var serializerType in serializersToGenerate)
            {
                var nsMembers = GetNamespace(namespaceGroupings, serializerType.Target.ContainingNamespace);
                TypeDeclarationSyntax generated;
                (generated, serializerType.SerializerTypeSyntax) = SerializerGenerator.GenerateClass(this.wellKnownTypes, this.semanticModelForAccessibility, serializerType);
                nsMembers.Add(generated);
            }

            var compilationMembers = new List <MemberDeclarationSyntax>();

            // Group the generated code by namespace since serialized types, such as the generated GrainReference classes must have a stable namespace.
            foreach (var group in namespaceGroupings)
            {
                var ns      = group.Key;
                var members = group.Value;
                if (ns.IsGlobalNamespace)
                {
                    compilationMembers.AddRange(members);
                }
                else
                {
                    compilationMembers.Add(NamespaceDeclaration(ParseName(ns.ToDisplayString())).AddMembers(members.ToArray()));
                }
            }

            // Add and generate feature populators to tie everything together.
            var(attributes, featurePopulators) = FeaturePopulatorGenerator.GenerateSyntax(this.wellKnownTypes, model);
            compilationMembers.AddRange(featurePopulators);

            return(CompilationUnit()
                   .AddUsings(UsingDirective(ParseName("global::Orleans")))
                   .WithAttributeLists(List(attributes))
                   .WithMembers(List(compilationMembers)));

            List <MemberDeclarationSyntax> GetNamespace(Dictionary <INamespaceSymbol, List <MemberDeclarationSyntax> > namespaces, INamespaceSymbol ns)
            {
                if (namespaces.TryGetValue(ns, out var result))
                {
                    return(result);
                }
                return(namespaces[ns] = new List <MemberDeclarationSyntax>());
            }
        }
示例#6
0
        private AggregatedModel AnalyzeCompilation()
        {
            // Inspect the target assembly to discover known assemblies and known types.
            if (log.IsEnabled(LogLevel.Debug))
            {
                log.LogDebug($"Main assembly {this.compilation.Assembly}");
            }
            this.compilationAnalyzer.InspectAssembly(this.compilation.Assembly);

            // Create a list of all distinct types from all known assemblies.
            var types = this.compilationAnalyzer
                        .KnownAssemblies.SelectMany(a => a.GetDeclaredTypes())
                        .Concat(this.compilationAnalyzer.KnownTypes)
                        .Distinct()
                        .ToList();

            var model = new AggregatedModel();

            // Inspect all types
            foreach (var type in types)
            {
                this.compilationAnalyzer.InspectType(type);
            }

            // Get the types which need processing.
            var(grainClasses, grainInterfaces, serializationTypes) = this.compilationAnalyzer.GetTypesToProcess();

            // Process each of the types into the model.
            foreach (var grainInterface in grainInterfaces)
            {
                this.ProcessGrainInterface(model, grainInterface);
            }
            foreach (var grainClass in grainClasses)
            {
                this.ProcessGrainClass(model, grainClass);
                this.ProcessSerializableType(model, grainClass);
            }

            foreach (var type in serializationTypes)
            {
                this.ProcessSerializableType(model, type);
            }

            var otherAssemblies = this.compilation.References
                                  .Select(a => this.compilation.GetAssemblyOrModuleSymbol(a))
                                  .OfType <IAssemblySymbol>()
                                  .Where(a => !this.compilationAnalyzer.KnownAssemblies.Contains(a));

            foreach (var type in otherAssemblies.SelectMany(a => a.GetDeclaredTypes()))
            {
                if (this.ValidForKnownTypes(type))
                {
                    AddKnownType(model, type);
                }
            }

            return(model);
        }
        private static void AddKnownType(AggregatedModel model, INamedTypeSymbol type)
        {
            // Many types which will never have a serializer generated are still added to known types so that they can be used to identify the type
            // in a serialized payload. For example, when serializing List<SomeAbstractType>, SomeAbstractType must be known. The same applies to
            // interfaces (which are encoded as abstract).
            var serializerModel = model.Serializers;
            var strippedType    = type.WithoutTypeParameters();

            serializerModel.KnownTypes.Add(new KnownTypeDescription(strippedType));
        }
    public ActionResult SomeAction()
    {
        var model = new AggregatedModel
        {
            Model1 = new Model1(),
            Model2 = new Model2()
        };

        Response.ContentType = "text/javascript";
        return(PartialView(model));
    }
 private void ValidateModel(AggregatedModel model)
 {
     // Check that all types which the developer marked as requiring code generation have had code generation.
     foreach (var required in this.compilationAnalyzer.CodeGenerationRequiredTypes)
     {
         if (!model.Serializers.SerializerTypes.Any(t => SymbolEqualityComparer.Default.Equals(t.Target, required)))
         {
             throw new CodeGenerationException(
                       $"Found {this.wellKnownTypes.ConsiderForCodeGenerationAttribute} with ThrowOnFailure set for type {required}, but a serializer" +
                       " could not be generated. Ensure that the type is accessible.");
         }
     }
 }
示例#10
0
        private void ProcessGrainClass(AggregatedModel model, INamedTypeSymbol type)
        {
            var accessible = this.semanticModelForAccessibility.IsAccessible(0, type);

            if (accessible)
            {
                model.GrainClasses.Add(new GrainClassDescription(type, this.wellKnownTypes.GetTypeId(type)));
            }
            else
            {
                var declaration = type.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax() as TypeDeclarationSyntax;
                this.context.ReportDiagnostic(InaccessibleGrainClassDiagnostic.CreateDiagnostic(declaration));
            }
        }
        private void ProcessGrainClass(AggregatedModel model, INamedTypeSymbol type)
        {
            var accessible = this.semanticModelForAccessibility.IsAccessible(0, type);

            if (this.log.IsEnabled(LogLevel.Debug))
            {
                this.log.LogDebug($"Found grain class {type.ToDisplayString()}{(accessible ? string.Empty : ", but it is inaccessible")}");
            }

            if (accessible)
            {
                model.GrainClasses.Add(new GrainClassDescription(type, this.wellKnownTypes.GetTypeId(type)));
            }
        }
示例#12
0
        private AggregatedModel AnalyzeCompilation(CancellationToken cancellationToken)
        {
            // Inspect the target assembly to discover known assemblies and known types.
            this.compilationAnalyzer.Analyze(cancellationToken);

            // Create a list of all distinct types from all known assemblies.
            var types = this.compilationAnalyzer
                        .KnownAssemblies.SelectMany(a => a.GetDeclaredTypes())
                        .Concat(this.compilationAnalyzer.KnownTypes)
                        .Distinct(SymbolEqualityComparer.Default)
                        .Cast <INamedTypeSymbol>()
                        .ToList();

            var model = new AggregatedModel();

            // Inspect all types
            foreach (var type in types)
            {
                this.compilationAnalyzer.InspectType(type);
            }

            // Get the types which need processing.
            var(grainClasses, grainInterfaces, serializationTypes) = this.compilationAnalyzer.GetTypesToProcess();

            // Process each of the types into the model.
            foreach (var grainInterface in grainInterfaces)
            {
                this.ProcessGrainInterface(model, grainInterface);
            }
            foreach (var grainClass in grainClasses)
            {
                this.ProcessGrainClass(model, grainClass);
                this.ProcessSerializableType(model, grainClass);
            }

            foreach (var type in serializationTypes)
            {
                this.ProcessSerializableType(model, type);
            }

            foreach (var part in this.compilationAnalyzer.ApplicationParts)
            {
                model.ApplicationParts.Add(part);
            }

            this.AddAssemblyMetadata(model);

            return(model);
        }
        public void Save()
        {
            var aggregatedModel = new AggregatedModel();

            foreach (var s in m_services)
            {
                s.SaveTo(aggregatedModel);
            }

            if (File.Exists(SaveFilePath))
            {
                File.Delete(BackupSaveFilePath);
                File.Move(SaveFilePath, BackupSaveFilePath);
            }
            Global.Helper.WriteJsonFile(SaveFilePath, aggregatedModel);
        }
        private AggregatedModel AnalyzeCompilation()
        {
            // Inspect the target assembly to discover known assemblies and known types.
            if (log.IsEnabled(LogLevel.Debug))
            {
                log.LogDebug($"Main assembly {this.compilation.Assembly}");
            }
            this.compilationAnalyzer.Analyze();

            // Create a list of all distinct types from all known assemblies.
            var types = this.compilationAnalyzer
                        .KnownAssemblies.SelectMany(a => a.GetDeclaredTypes())
                        .Concat(this.compilationAnalyzer.KnownTypes)
                        .Distinct()
                        .ToList();

            var model = new AggregatedModel();

            // Inspect all types
            foreach (var type in types)
            {
                this.compilationAnalyzer.InspectType(type);
            }

            // Get the types which need processing.
            var(grainClasses, grainInterfaces, serializationTypes) = this.compilationAnalyzer.GetTypesToProcess();

            // Process each of the types into the model.
            foreach (var grainInterface in grainInterfaces)
            {
                this.ProcessGrainInterface(model, grainInterface);
            }
            foreach (var grainClass in grainClasses)
            {
                this.ProcessGrainClass(model, grainClass);
                this.ProcessSerializableType(model, grainClass);
            }

            foreach (var type in serializationTypes)
            {
                this.ProcessSerializableType(model, type);
            }

            this.AddAssemblyMetadata(model);

            return(model);
        }
示例#15
0
        private void ProcessGrainInterface(AggregatedModel model, INamedTypeSymbol type)
        {
            var accessible = this.semanticModelForAccessibility.IsAccessible(0, type);

            if (accessible)
            {
                var genericMethod = type.GetInstanceMembers <IMethodSymbol>().FirstOrDefault(m => m.IsGenericMethod);
                if (genericMethod != null && this.wellKnownTypes.GenericMethodInvoker is WellKnownTypes.None)
                {
                    var declaration = genericMethod.GetDeclarationSyntax();
                    this.context.ReportDiagnostic(GenericMethodRequireOrleansCoreDiagnostic.CreateDiagnostic(declaration));
                }

                var methods = GetGrainMethodDescriptions(type);

                model.GrainInterfaces.Add(new GrainInterfaceDescription(
                                              type,
                                              this.wellKnownTypes.GetTypeId(type),
                                              this.wellKnownTypes.GetVersion(type),
                                              methods));
            }

            // Returns a list of all methods in all interfaces on the provided type.
            IEnumerable <GrainMethodDescription> GetGrainMethodDescriptions(INamedTypeSymbol initialType)
            {
                IEnumerable <INamedTypeSymbol> GetAllInterfaces(INamedTypeSymbol s)
                {
                    if (s.TypeKind == TypeKind.Interface)
                    {
                        yield return(s);
                    }
                    foreach (var i in s.AllInterfaces)
                    {
                        yield return(i);
                    }
                }

                foreach (var iface in GetAllInterfaces(initialType))
                {
                    foreach (var method in iface.GetDeclaredInstanceMembers <IMethodSymbol>())
                    {
                        yield return(new GrainMethodDescription(this.wellKnownTypes.GetMethodId(method), method));
                    }
                }
            }
        }
示例#16
0
        public static (List <AttributeListSyntax>, List <MemberDeclarationSyntax>) GenerateSyntax(
            WellKnownTypes wellKnownTypes,
            AggregatedModel model,
            Compilation compilation)
        {
            var attributes = new List <AttributeListSyntax>();
            var members    = new List <MemberDeclarationSyntax>();
            var className  = GetFeaturePopulatorClassName(compilation);

            // Generate a class for populating the metadata.
            var classSyntax = ClassDeclaration(className)
                              .AddBaseListTypes(
                SimpleBaseType(wellKnownTypes.IFeaturePopulator_1.Construct(wellKnownTypes.GrainInterfaceFeature).ToTypeSyntax()),
                SimpleBaseType(wellKnownTypes.IFeaturePopulator_1.Construct(wellKnownTypes.GrainClassFeature).ToTypeSyntax()),
                SimpleBaseType(wellKnownTypes.IFeaturePopulator_1.Construct(wellKnownTypes.SerializerFeature).ToTypeSyntax()))
                              .AddModifiers(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.SealedKeyword))
                              .AddMembers(
                GeneratePopulateMethod(wellKnownTypes, model.GrainInterfaces),
                GeneratePopulateMethod(wellKnownTypes, model.GrainClasses),
                GeneratePopulateMethod(wellKnownTypes, model.Serializers))
                              .AddAttributeLists(AttributeList(SingletonSeparatedList(GeneratedCodeAttributeGenerator.GetGeneratedCodeAttributeSyntax(wellKnownTypes))));

            var namespaceSyntax = NamespaceDeclaration(NamespaceName.ToIdentifierName()).AddMembers(classSyntax);

            members.Add(namespaceSyntax);

            // Generate an assembly-level attribute with an instance of that class.
            var attribute = AttributeList(
                AttributeTargetSpecifier(Token(SyntaxKind.AssemblyKeyword)),
                SingletonSeparatedList(
                    Attribute(wellKnownTypes.FeaturePopulatorAttribute.ToNameSyntax())
                    .AddArgumentListArguments(AttributeArgument(TypeOfExpression(ParseTypeName(NamespaceName + "." + className))))));

            attributes.Add(attribute);

            return(attributes, members);
        }
 public virtual void SaveTo(AggregatedModel model)
 {
     m_modelSetter(model, DumpSaveModel());
 }
 public virtual void LoadFrom(AggregatedModel model)
 {
     DoLoad(m_modelGetter(model));
 }
        private void ProcessSerializableType(AggregatedModel model, INamedTypeSymbol type)
        {
            if (!ValidForKnownTypes(type))
            {
                if (this.log.IsEnabled(LogLevel.Trace))
                {
                    this.log.LogTrace($"{nameof(ProcessSerializableType)} skipping abstract type {type}");
                }
                return;
            }

            AddKnownType(model, type);

            var serializerModel = model.Serializers;

            if (type.IsAbstract)
            {
                if (this.log.IsEnabled(LogLevel.Trace))
                {
                    this.log.LogTrace($"{nameof(ProcessSerializableType)} skipping abstract type {type}");
                }
                return;
            }

            // Ensure that the type is accessible from generated code.
            var accessible = this.semanticModelForAccessibility.IsAccessible(0, type);

            if (!accessible)
            {
                if (this.log.IsEnabled(LogLevel.Trace))
                {
                    this.log.LogTrace($"{nameof(ProcessSerializableType)} skipping inaccessible type {type}");
                }
                return;
            }

            if (type.HasBaseType(this.wellKnownTypes.Exception))
            {
                if (this.log.IsEnabled(LogLevel.Trace))
                {
                    this.log.LogTrace($"{nameof(ProcessSerializableType)} skipping Exception type {type}");
                }
                return;
            }

            if (type.HasBaseType(this.wellKnownTypes.Delegate))
            {
                if (this.log.IsEnabled(LogLevel.Trace))
                {
                    this.log.LogTrace($"{nameof(ProcessSerializableType)} skipping Delegate type {type}");
                }
                return;
            }

            if (type.AllInterfaces.Contains(this.wellKnownTypes.IAddressable))
            {
                if (this.log.IsEnabled(LogLevel.Trace))
                {
                    this.log.LogTrace($"{nameof(ProcessSerializableType)} skipping IAddressable type {type}");
                }
                return;
            }

            // Account for types that serialize themselves and/or are serializers for other types.
            var selfSerializing = false;

            if (this.serializerTypeAnalyzer.IsSerializer(type, out var serializerTargets))
            {
                var typeSyntax = type.ToTypeSyntax();
                foreach (var target in serializerTargets)
                {
                    if (this.log.IsEnabled(LogLevel.Trace))
                    {
                        this.log.LogTrace($"{nameof(ProcessSerializableType)} type {type} is a serializer for {target}");
                    }

                    if (SymbolEqualityComparer.Default.Equals(target, type))
                    {
                        selfSerializing = true;
                        typeSyntax      = type.WithoutTypeParameters().ToTypeSyntax();
                    }

                    serializerModel.SerializerTypes.Add(new SerializerTypeDescription
                    {
                        Target = target,
                        SerializerTypeSyntax       = typeSyntax,
                        OverrideExistingSerializer = true
                    });
                }
            }

            if (selfSerializing)
            {
                if (this.log.IsEnabled(LogLevel.Trace))
                {
                    this.log.LogTrace($"{nameof(ProcessSerializableType)} skipping serializer generation for self-serializing type {type}");
                }
                return;
            }

            if (type.HasAttribute(this.wellKnownTypes.GeneratedCodeAttribute))
            {
                if (this.log.IsEnabled(LogLevel.Trace))
                {
                    this.log.LogTrace($"{nameof(ProcessSerializableType)} type {type} is a generated type and no serializer will be generated for it");
                }

                return;
            }

            if (type.IsStatic)
            {
                if (this.log.IsEnabled(LogLevel.Trace))
                {
                    this.log.LogTrace($"{nameof(ProcessSerializableType)} type {type} is a static type and no serializer will be generated for it");
                }

                return;
            }

            if (type.TypeKind == TypeKind.Enum)
            {
                if (this.log.IsEnabled(LogLevel.Trace))
                {
                    this.log.LogTrace($"{nameof(ProcessSerializableType)} type {type} is an enum type and no serializer will be generated for it");
                }

                return;
            }

            if (type.TypeParameters.Any(p => p.ConstraintTypes.Any(c => SymbolEqualityComparer.Default.Equals(c, this.wellKnownTypes.Delegate))))
            {
                if (this.log.IsEnabled(LogLevel.Trace))
                {
                    this.log.LogTrace($"{nameof(ProcessSerializableType)} skipping type with Delegate parameter constraint, {type}");
                }
                return;
            }

            var isSerializable = this.compilationAnalyzer.IsSerializable(type);

            if (isSerializable && this.compilationAnalyzer.IsFromKnownAssembly(type))
            {
                // Skip types which have fields whose types are inaccessible from generated code.
                foreach (var field in type.GetInstanceMembers <IFieldSymbol>())
                {
                    // Ignore fields which won't be serialized anyway.
                    if (!this.serializerGenerator.ShouldSerializeField(field))
                    {
                        if (this.log.IsEnabled(LogLevel.Trace))
                        {
                            this.log.LogTrace($"{nameof(ProcessSerializableType)} skipping non-serialized field {field} in type {type}");
                        }

                        continue;
                    }

                    // Check field type accessibility.
                    var fieldAccessible = this.semanticModelForAccessibility.IsAccessible(0, field.Type);
                    if (!fieldAccessible)
                    {
                        if (this.log.IsEnabled(LogLevel.Trace))
                        {
                            this.log.LogTrace($"{nameof(ProcessSerializableType)} skipping type {type} with inaccessible field type {field.Type} (field: {field})");
                        }

                        return;
                    }
                }

                // Add the type that needs generation.
                // The serializer generator will fill in the missing SerializerTypeSyntax field with the
                // generated type.
                if (this.log.IsEnabled(LogLevel.Trace))
                {
                    this.log.LogTrace($"{nameof(ProcessSerializableType)} will generate a serializer for type {type}");
                }

                serializerModel.SerializerTypes.Add(new SerializerTypeDescription
                {
                    Target = type
                });
            }
            else if (this.log.IsEnabled(LogLevel.Trace))
            {
                this.log.LogTrace($"{nameof(ProcessSerializableType)} will not generate a serializer for type {type}");
            }
        }
        public static List <AttributeListSyntax> GenerateSyntax(WellKnownTypes wellKnownTypes, AggregatedModel 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.ToLiteralExpression()))));
                attributes.Add(attribute);
            }

            return(attributes);
        }
        private CompilationUnitSyntax GenerateSyntax(AggregatedModel model)
        {
            var namespaceGroupings = new Dictionary <INamespaceSymbol, List <MemberDeclarationSyntax> >();

            // Pass the relevant elements of the model to each of the code generators.
            foreach (var grainInterface in model.GrainInterfaces)
            {
                var nsMembers = GetNamespace(namespaceGroupings, grainInterface.Type.ContainingNamespace);
                nsMembers.Add(grainMethodInvokerGenerator.GenerateClass(grainInterface));
                nsMembers.Add(grainReferenceGenerator.GenerateClass(grainInterface));
            }

            var serializersToGenerate = model.Serializers.SerializerTypes
                                        .Where(s => s.SerializerTypeSyntax == null)
                                        .Distinct(SerializerTypeDescription.TargetComparer);

            foreach (var serializerType in serializersToGenerate)
            {
                var nsMembers = GetNamespace(namespaceGroupings, serializerType.Target.ContainingNamespace);
                TypeDeclarationSyntax generated;
                (generated, serializerType.SerializerTypeSyntax) = this.serializerGenerator.GenerateClass(this.semanticModelForAccessibility, serializerType, this.log);
                nsMembers.Add(generated);
            }

            var compilationMembers = new List <MemberDeclarationSyntax>();

            // Group the generated code by namespace since serialized types, such as the generated GrainReference classes must have a stable namespace.
            foreach (var group in namespaceGroupings)
            {
                var ns      = group.Key;
                var members = group.Value;
                if (ns.IsGlobalNamespace)
                {
                    compilationMembers.AddRange(members);
                }
                else
                {
                    compilationMembers.Add(NamespaceDeclaration(ParseName(ns.ToDisplayString())).AddMembers(members.ToArray()));
                }
            }

            // Add and generate feature populators to tie everything together.
            var(attributes, featurePopulators) = FeaturePopulatorGenerator.GenerateSyntax(this.wellKnownTypes, model);
            compilationMembers.AddRange(featurePopulators);

            // Add some attributes detailing which assemblies this generated code targets.
            attributes.Add(AttributeList(
                               AttributeTargetSpecifier(Token(SyntaxKind.AssemblyKeyword)),
                               SeparatedList(GetCodeGenerationTargetAttribute().ToArray())));

            return(CompilationUnit()
                   .AddUsings(UsingDirective(ParseName("global::Orleans")))
                   .WithAttributeLists(List(attributes))
                   .WithMembers(List(compilationMembers)));

            List <MemberDeclarationSyntax> GetNamespace(Dictionary <INamespaceSymbol, List <MemberDeclarationSyntax> > namespaces, INamespaceSymbol ns)
            {
                if (namespaces.TryGetValue(ns, out var result))
                {
                    return(result);
                }
                return(namespaces[ns] = new List <MemberDeclarationSyntax>());
            }

            IEnumerable <AttributeSyntax> GetCodeGenerationTargetAttribute()
            {
                yield return(GenerateAttribute(this.compilation.Assembly));

                foreach (var assembly in this.compilationAnalyzer.ReferencedAssemblies)
                {
                    if (this.compilationAnalyzer.AssembliesExcludedFromCodeGeneration.Contains(assembly) ||
                        this.compilationAnalyzer.AssembliesExcludedFromMetadataGeneration.Contains(assembly))
                    {
                        continue;
                    }

                    yield return(GenerateAttribute(assembly));
                }

                AttributeSyntax GenerateAttribute(IAssemblySymbol assembly)
                {
                    var assemblyName = assembly.Identity.GetDisplayName(fullKey: true);

                    this.log.LogTrace($"Adding [assembly: OrleansCodeGenerationTarget(\"{assemblyName}\")]");
                    var nameSyntax = this.wellKnownTypes.OrleansCodeGenerationTargetAttribute.ToNameSyntax();

                    return(Attribute(nameSyntax)
                           .AddArgumentListArguments(AttributeArgument(assemblyName.ToLiteralExpression())));
                }
            }
        }