<commit_before>﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.ILAst;
using JSIL.Ast;
using JSIL.Internal;
using JSIL.Transforms;
using JSIL.Translator;
using Mono.Cecil;
using ICSharpCode.Decompiler;
using MethodInfo = JSIL.Internal.MethodInfo;

namespace JSIL {
    public class AssemblyTranslator : IDisposable {
        struct MethodToAnalyze {
            public readonly MethodDefinition MD;
            public readonly MethodInfo MI;

            public MethodToAnalyze (MethodDefinition md) {
                MD = md;
                MI = null;
            }

            public MethodToAnalyze (MethodInfo mi) {
                MD = mi.Member;
                MI = mi;
            }
        }

        public const int LargeMethodThreshold = 20 * 1024;

        public readonly Configuration Configuration;

        public readonly SymbolProvider SymbolProvider = new SymbolProvider();
        public readonly AssemblyCache AssemblyCache;
        public readonly FunctionCache FunctionCache;
        public readonly AssemblyManifest Manifest;

        public event Action<string> AssemblyLoaded;

        public event Action<ProgressReporter> Decompiling;
        public event Action<ProgressReporter> Optimizing;
        public event Action<ProgressReporter> Writing;
        public event Action<string, ProgressReporter> DecompilingMethod;

        public event Action<string, Exception> CouldNotLoadSymbols;
        public event Action<string, Exception> CouldNotResolveAssembly;
        public event Action<string, Exception> CouldNotDecompileMethod;
        public event Action<string> Warning;

        internal readonly TypeInfoProvider _TypeInfoProvider;

        protected bool OwnsAssemblyCache;
        protected bool OwnsTypeInfoProvider;

        public AssemblyTranslator (
            Configuration configuration,
            TypeInfoProvider typeInfoProvider = null,
            AssemblyManifest manifest = null,
            AssemblyCache assemblyCache = null
        ) {
            Warning = (s) => {
                Console.Error.WriteLine("// {0}", s);
            };

            Configuration = configuration;
            bool useDefaultProxies = configuration.UseDefaultProxies.GetValueOrDefault(true);

            if (manifest != null)
                Manifest = manifest;
            else
                Manifest = new AssemblyManifest();

            if (typeInfoProvider != null) {
                _TypeInfoProvider = typeInfoProvider;
                OwnsTypeInfoProvider = false;

                if (configuration.Assemblies.Proxies.Count > 0)
                    throw new InvalidOperationException("Cannot reuse an existing type provider if explicitly loading proxies");
            } else {
              _TypeInfoProvider = new JSIL.TypeInfoProvider();
              OwnsTypeInfoProvider = true;

              if (useDefaultProxies) { 
                  Assembly proxyAssembly = null;
                  var myAssemblyPath = Util.GetPathOfAssembly(Assembly.GetExecutingAssembly());
                  var proxyFolder = Path.GetDirectoryName(myAssemblyPath);
                  string proxyPath = null;

                  try {
                      if (!configuration.FrameworkVersion.HasValue || configuration.FrameworkVersion == 4.0) {
                          proxyPath = Path.Combine(proxyFolder, "JSIL.Proxies.4.0.dll");
                      } else if (configuration.FrameworkVersion <= 3.5) {
                          proxyPath = Path.Combine(proxyFolder, "JSIL.Proxies.3.5.dll");
                      } else {
                          throw new ArgumentOutOfRangeException(
                              "FrameworkVersion",
                              String.Format("Framework version '{0}' not supported", configuration.FrameworkVersion.Value)
                          );
                      }

                      proxyAssembly = Assembly.LoadFile(proxyPath);
                  } catch (FileNotFoundException fnf) {
                      throw new FileNotFoundException(
                          String.Format("Could not load the .NET proxies assembly from '{0}'.", proxyPath),
                          fnf
                      );
                  }

                  if (proxyAssembly == null)
                      throw new InvalidOperationException("No core proxy assembly was loaded.");

                  AddProxyAssembly(proxyAssembly);
                }
              
                foreach (var fn in configuration.Assemblies.Proxies.Distinct())
                    AddProxyAssembly(fn);
            }

            OwnsAssemblyCache = (assemblyCache == null);
            if (assemblyCache != null)
                AssemblyCache = assemblyCache;
            else
                AssemblyCache = new AssemblyCache();

            FunctionCache = new FunctionCache(_TypeInfoProvider);
        }

        internal void WarningFormat (string format, params object[] args) {
            Warning(String.Format(format, args));
        }

        protected virtual ReaderParameters GetReaderParameters (bool useSymbols, string mainAssemblyPath = null) {
            var readerParameters = new ReaderParameters {
                ReadingMode = ReadingMode.Deferred,
                ReadSymbols = useSymbols
            };

            if (mainAssemblyPath != null) {
                readerParameters.AssemblyResolver = new AssemblyResolver(new string[] { 
                    Path.GetDirectoryName(mainAssemblyPath),
                    Path.GetDirectoryName(Util.GetPathOfAssembly(Assembly.GetExecutingAssembly())) 
                }, AssemblyCache);
                readerParameters.MetadataResolver = new CachingMetadataResolver(readerParameters.AssemblyResolver);
            }

            if (useSymbols)
                readerParameters.SymbolReaderProvider = SymbolProvider;

            return readerParameters;
        }

        public void AddProxyAssembly (string path) {
            var assemblies = LoadAssembly(path, Configuration.UseSymbols.GetValueOrDefault(true), false);
<commit_msg>Pull default proxy assembly loading out into a static function<commit_after>﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.ILAst;
using JSIL.Ast;
using JSIL.Internal;
using JSIL.Transforms;
using JSIL.Translator;
using Mono.Cecil;
using ICSharpCode.Decompiler;
using MethodInfo = JSIL.Internal.MethodInfo;

namespace JSIL {
    public class AssemblyTranslator : IDisposable {
        struct MethodToAnalyze {
            public readonly MethodDefinition MD;
            public readonly MethodInfo MI;

            public MethodToAnalyze (MethodDefinition md) {
                MD = md;
                MI = null;
            }

            public MethodToAnalyze (MethodInfo mi) {
                MD = mi.Member;
                MI = mi;
            }
        }

        public const int LargeMethodThreshold = 20 * 1024;

        public readonly Configuration Configuration;

        public readonly SymbolProvider SymbolProvider = new SymbolProvider();
        public readonly AssemblyCache AssemblyCache;
        public readonly FunctionCache FunctionCache;
        public readonly AssemblyManifest Manifest;

        public event Action<string> AssemblyLoaded;

        public event Action<ProgressReporter> Decompiling;
        public event Action<ProgressReporter> Optimizing;
        public event Action<ProgressReporter> Writing;
        public event Action<string, ProgressReporter> DecompilingMethod;

        public event Action<string, Exception> CouldNotLoadSymbols;
        public event Action<string, Exception> CouldNotResolveAssembly;
        public event Action<string, Exception> CouldNotDecompileMethod;
        public event Action<string> Warning;

        internal readonly TypeInfoProvider _TypeInfoProvider;

        protected bool OwnsAssemblyCache;
        protected bool OwnsTypeInfoProvider;

        public AssemblyTranslator (
            Configuration configuration,
            TypeInfoProvider typeInfoProvider = null,
            AssemblyManifest manifest = null,
            AssemblyCache assemblyCache = null
        ) {
            Warning = (s) => {
                Console.Error.WriteLine("// {0}", s);
            };

            Configuration = configuration;
            bool useDefaultProxies = configuration.UseDefaultProxies.GetValueOrDefault(true);

            if (manifest != null)
                Manifest = manifest;
            else
                Manifest = new AssemblyManifest();

            if (typeInfoProvider != null) {
                _TypeInfoProvider = typeInfoProvider;
                OwnsTypeInfoProvider = false;

                if (configuration.Assemblies.Proxies.Count > 0)
                    throw new InvalidOperationException("Cannot reuse an existing type provider if explicitly loading proxies");
            } else {
                _TypeInfoProvider = new JSIL.TypeInfoProvider();
                OwnsTypeInfoProvider = true;

                if (useDefaultProxies) {
                    var defaultProxyAssembly =
                        GetDefaultProxyAssembly(configuration.FrameworkVersion.GetValueOrDefault(4.0));

                    if (defaultProxyAssembly == null)
                        throw new InvalidOperationException("No default proxy assembly was loaded.");

                    AddProxyAssembly(defaultProxyAssembly);    
                }
              
                foreach (var fn in configuration.Assemblies.Proxies.Distinct())
                    AddProxyAssembly(fn);
            }

            OwnsAssemblyCache = (assemblyCache == null);
            if (assemblyCache != null)
                AssemblyCache = assemblyCache;
            else
                AssemblyCache = new AssemblyCache();

            FunctionCache = new FunctionCache(_TypeInfoProvider);
        }

        public static Assembly GetDefaultProxyAssembly (double frameworkVersion) {
            var myAssemblyPath = Util.GetPathOfAssembly(Assembly.GetExecutingAssembly());
            var proxyFolder = Path.GetDirectoryName(myAssemblyPath);
            string proxyPath = null;

            try {
                if (frameworkVersion == 4.0) {
                    proxyPath = Path.Combine(proxyFolder, "JSIL.Proxies.4.0.dll");
                } else if (frameworkVersion <= 3.5) {
                    proxyPath = Path.Combine(proxyFolder, "JSIL.Proxies.3.5.dll");
                } else {
                    throw new ArgumentOutOfRangeException(
                        "FrameworkVersion",
                        String.Format("Framework version '{0}' not supported", frameworkVersion)
                    );
                }

                return Assembly.LoadFile(proxyPath);
            } catch (FileNotFoundException fnf) {
                throw new FileNotFoundException(
                    String.Format("Could not load the .NET proxies assembly from '{0}'.", proxyPath),
                    fnf
                );
            }        
        }

        internal void WarningFormat (string format, params object[] args) {
            Warning(String.Format(format, args));
        }

        protected virtual ReaderParameters GetReaderParameters (bool useSymbols, string mainAssemblyPath = null) {
            var readerParameters = new ReaderParameters {
                ReadingMode = ReadingMode.Deferred,
                ReadSymbols = useSymbols
            };

            if (mainAssemblyPath != null) {
                readerParameters.AssemblyResolver = new AssemblyResolver(new string[] { 
                    Path.GetDirectoryName(mainAssemblyPath),
                    Path.GetDirectoryName(Util.GetPathOfAssembly(Assembly.GetExecutingAssembly())) 
                }, AssemblyCache);
                readerParameters.MetadataResolver = new CachingMetadataResolver(readerParameters.AssemblyResolver);
            }

            if (useSymbols)
                readerParameters.SymbolReaderProvider = SymbolProvider;

            return readerParameters;
        }

        public void AddProxyAssembly (string path) {
            var assemblies = LoadAssembly(path, Configuration.UseSymbols.GetValueOrDefault(true), false);

{'fraction_non_alphanumeric': 0.06819246992657398, 'fraction_numerical': 0.002968286205280425, 'mean_word_length': 1.9760576476057647, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 25, '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': '3188976', 'n_tokens_mistral': 2957, 'n_tokens_neox': 2773, 'n_words': 732}