<commit_before>﻿// Copyright (c) 2017 <NAME>. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.

namespace Abioc.Compilation
{
    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using Abioc.Composition;
    using Abioc.Registration;
    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.CSharp;
    using Microsoft.CodeAnalysis.Emit;

    /// <summary>
    /// Compiles generated code into a dynamic assembly.
    /// </summary>
    public static class CodeCompilation
    {
        private static readonly ConcurrentDictionary<string, Assembly> Compilations
            = new ConcurrentDictionary<string, Assembly>();

        /// <summary>
        /// Compiles the <paramref name="code"/> for the registration <paramref name="setup"/>.
        /// </summary>
        /// <typeparam name="TExtra">
        /// The type of the <see cref="ConstructionContext{TExtra}.Extra"/> construction context information.
        /// </typeparam>
        /// <param name="setup">The registration <paramref name="setup"/>.</param>
        /// <param name="code">The source code to compile.</param>
        /// <param name="fieldValues">The values of the fields to be initialized.</param>
        /// <param name="srcAssembly">The source assembly for the types top create.</param>
        /// <returns>The <see cref="CompositionContext"/>.</returns>
        public static AbiocContainer<TExtra> Compile<TExtra>(
            RegistrationSetup<TExtra> setup,
            string code,
            object[] fieldValues,
            Assembly srcAssembly)
        {
            if (setup == null)
                throw new ArgumentNullException(nameof(setup));
            if (code == null)
                throw new ArgumentNullException(nameof(code));
            if (fieldValues == null)
                throw new ArgumentNullException(nameof(fieldValues));
            if (srcAssembly == null)
                throw new ArgumentNullException(nameof(srcAssembly));

            ////Assembly assembly = Compilations.GetOrAdd(code, c => CompileCode(c, srcAssembly));
            Assembly assembly = CompileCode(code, srcAssembly);

            if (fieldValues.Length > 0)
            {
                var initializeFieldsMethod = GetInitializeFieldsMethodInfo(assembly);

                initializeFieldsMethod.Invoke(null, new object[] { fieldValues });
            }

            MethodInfo getCreateMapMethod = GetCreateMapMethodInfo(assembly);
            Dictionary<Type, Func<ConstructionContext<TExtra>, object>> createMap =
                (Dictionary<Type, Func<ConstructionContext<TExtra>, object>>)getCreateMapMethod.Invoke(null, null);

            IEnumerable<(Type type, Func<ConstructionContext<TExtra>, object>[] compositions)> iocMappings =
                from kvp in setup.Registrations
                let compositions = kvp.Value.Select(r => createMap[r.ImplementationType]).ToArray()
                select (kvp.Key, compositions);

            return iocMappings.ToDictionary(m => m.type, kvp => kvp.compositions).ToContainer();
        }

        /// <summary>
        /// Compiles the <paramref name="code"/> for the registration <paramref name="setup"/>.
        /// </summary>
        /// <param name="setup">The registration <paramref name="setup"/>.</param>
        /// <param name="code">The source code to compile.</param>
        /// <param name="fieldValues">The values of the fields to be initialized.</param>
        /// <param name="srcAssembly">The source assembly for the types top create.</param>
        /// <returns>The <see cref="CompositionContext"/>.</returns>
        public static AbiocContainer Compile(
            RegistrationSetup setup,
            string code,
            object[] fieldValues,
            Assembly srcAssembly)
        {
            if (setup == null)
                throw new ArgumentNullException(nameof(setup));
            if (code == null)
                throw new ArgumentNullException(nameof(code));
            if (fieldValues == null)
                throw new ArgumentNullException(nameof(fieldValues));
            if (srcAssembly == null)
                throw new ArgumentNullException(nameof(srcAssembly));

            ////Assembly assembly = Compilations.GetOrAdd(code, c => CompileCode(c, srcAssembly));
            Assembly assembly = CompileCode(code, srcAssembly);

            if (fieldValues.Length > 0)
            {
                var initializeFieldsMethod = GetInitializeFieldsMethodInfo(assembly);

                initializeFieldsMethod.Invoke(null, new object[] { fieldValues });
            }

            MethodInfo getCreateMapMethod = GetCreateMapMethodInfo(assembly);
            Dictionary<Type, Func<object>> createMap =
                (Dictionary<Type, Func<object>>)getCreateMapMethod.Invoke(null, null);

            IEnumerable<(Type type, Func<object>[] compositions)> iocMappings =
                from kvp in setup.Registrations
                let compositions = kvp.Value.Select(r => createMap[r.ImplementationType]).ToArray()
                select (kvp.Key, compositions);

            return iocMappings.ToDictionary(m => m.type, kvp => kvp.compositions).ToContainer();
        }

        private static MethodInfo GetCreateMapMethodInfo(Assembly assembly)
        {
            if (assembly == null)
                throw new ArgumentNullException(nameof(assembly));

            Type type = assembly.GetType("Abioc.Generated.Construction");

            MethodInfo getCreateMapMethod =
                type.GetTypeInfo().GetMethod("GetCreateMap", BindingFlags.NonPublic | BindingFlags.Static);

            return getCreateMapMethod;
        }

        private static MethodInfo GetInitializeFieldsMethodInfo(Assembly assembly)
        {
            if (assembly == null)
                throw new ArgumentNullException(nameof(assembly));

            Type type = assembly.GetType("Abioc.Generated.Construction");

            MethodInfo getCreateMapMethod =
                type.GetTypeInfo().GetMethod("InitializeFields", BindingFlags.NonPublic | BindingFlags.Static);<commit_msg>Only populate IoC map with external Registrations<commit_after>﻿// Copyright (c) 2017 <NAME>. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.

namespace Abioc.Compilation
{
    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using Abioc.Composition;
    using Abioc.Registration;
    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.CSharp;
    using Microsoft.CodeAnalysis.Emit;

    /// <summary>
    /// Compiles generated code into a dynamic assembly.
    /// </summary>
    public static class CodeCompilation
    {
        private static readonly ConcurrentDictionary<string, Assembly> Compilations
            = new ConcurrentDictionary<string, Assembly>();

        /// <summary>
        /// Compiles the <paramref name="code"/> for the registration <paramref name="setup"/>.
        /// </summary>
        /// <typeparam name="TExtra">
        /// The type of the <see cref="ConstructionContext{TExtra}.Extra"/> construction context information.
        /// </typeparam>
        /// <param name="setup">The registration <paramref name="setup"/>.</param>
        /// <param name="code">The source code to compile.</param>
        /// <param name="fieldValues">The values of the fields to be initialized.</param>
        /// <param name="srcAssembly">The source assembly for the types top create.</param>
        /// <returns>The <see cref="CompositionContext"/>.</returns>
        public static AbiocContainer<TExtra> Compile<TExtra>(
            RegistrationSetup<TExtra> setup,
            string code,
            object[] fieldValues,
            Assembly srcAssembly)
        {
            if (setup == null)
                throw new ArgumentNullException(nameof(setup));
            if (code == null)
                throw new ArgumentNullException(nameof(code));
            if (fieldValues == null)
                throw new ArgumentNullException(nameof(fieldValues));
            if (srcAssembly == null)
                throw new ArgumentNullException(nameof(srcAssembly));

            ////Assembly assembly = Compilations.GetOrAdd(code, c => CompileCode(c, srcAssembly));
            Assembly assembly = CompileCode(code, srcAssembly);

            if (fieldValues.Length > 0)
            {
                var initializeFieldsMethod = GetInitializeFieldsMethodInfo(assembly);

                initializeFieldsMethod.Invoke(null, new object[] { fieldValues });
            }

            MethodInfo getCreateMapMethod = GetCreateMapMethodInfo(assembly);
            Dictionary<Type, Func<ConstructionContext<TExtra>, object>> createMap =
                (Dictionary<Type, Func<ConstructionContext<TExtra>, object>>)getCreateMapMethod.Invoke(null, null);

            IEnumerable<(Type type, Func<ConstructionContext<TExtra>, object>[] compositions)> iocMappings =
                from kvp in setup.Registrations.Where(kvp => kvp.Value.Any(r => !r.Internal))
                let compositions = kvp.Value.Select(r => createMap[r.ImplementationType]).ToArray()
                select (kvp.Key, compositions);

            return iocMappings.ToDictionary(m => m.type, kvp => kvp.compositions).ToContainer();
        }

        /// <summary>
        /// Compiles the <paramref name="code"/> for the registration <paramref name="setup"/>.
        /// </summary>
        /// <param name="setup">The registration <paramref name="setup"/>.</param>
        /// <param name="code">The source code to compile.</param>
        /// <param name="fieldValues">The values of the fields to be initialized.</param>
        /// <param name="srcAssembly">The source assembly for the types top create.</param>
        /// <returns>The <see cref="CompositionContext"/>.</returns>
        public static AbiocContainer Compile(
            RegistrationSetup setup,
            string code,
            object[] fieldValues,
            Assembly srcAssembly)
        {
            if (setup == null)
                throw new ArgumentNullException(nameof(setup));
            if (code == null)
                throw new ArgumentNullException(nameof(code));
            if (fieldValues == null)
                throw new ArgumentNullException(nameof(fieldValues));
            if (srcAssembly == null)
                throw new ArgumentNullException(nameof(srcAssembly));

            ////Assembly assembly = Compilations.GetOrAdd(code, c => CompileCode(c, srcAssembly));
            Assembly assembly = CompileCode(code, srcAssembly);

            if (fieldValues.Length > 0)
            {
                var initializeFieldsMethod = GetInitializeFieldsMethodInfo(assembly);

                initializeFieldsMethod.Invoke(null, new object[] { fieldValues });
            }

            MethodInfo getCreateMapMethod = GetCreateMapMethodInfo(assembly);
            Dictionary<Type, Func<object>> createMap =
                (Dictionary<Type, Func<object>>)getCreateMapMethod.Invoke(null, null);

            IEnumerable<(Type type, Func<object>[] compositions)> iocMappings =
                from kvp in setup.Registrations.Where(kvp => kvp.Value.Any(r => !r.Internal))
                let compositions = kvp.Value.Select(r => createMap[r.ImplementationType]).ToArray()
                select (kvp.Key, compositions);

            return iocMappings.ToDictionary(m => m.type, kvp => kvp.compositions).ToContainer();
        }

        private static MethodInfo GetCreateMapMethodInfo(Assembly assembly)
        {
            if (assembly == null)
                throw new ArgumentNullException(nameof(assembly));

            Type type = assembly.GetType("Abioc.Generated.Construction");

            MethodInfo getCreateMapMethod =
                type.GetTypeInfo().GetMethod("GetCreateMap", BindingFlags.NonPublic | BindingFlags.Static);

            return getCreateMapMethod;
        }

        private static MethodInfo GetInitializeFieldsMethodInfo(Assembly assembly)
        {
            if (assembly == null)
                throw new ArgumentNullException(nameof(assembly));

            Type type = assembly.GetType("Abioc.Generated.Construction");

            MethodInfo getCreateMapMethod =
                type.GetTypeInfo().GetMethod("InitializeFields", BindingFlags.NonPublic | BindingFlags.Static);
{'fraction_non_alphanumeric': 0.10799812177179527, 'fraction_numerical': 0.0012521521364845828, 'mean_word_length': 2.394156706507304, 'pattern_counts': {'":': 0, '<': 119, '<?xml version=': 0, '>': 143, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '963389', 'n_tokens_mistral': 3183, 'n_tokens_neox': 3071, 'n_words': 779}