<commit_before>﻿//# Author of original code ([Decompiled] MIT-License): Copyright (c) 2009-2015  <NAME>
//# Use Readme & LICENSE files for details.

//# Modifications: Copyright (c) 2016-2019  <NAME> < <EMAIL> > GitHub/3F
//$ Distributed under the MIT License (MIT)

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using Mono.Cecil;

namespace RGiesecke.DllExport
{
    internal class ExportAssemblyInspector: MarshalByRefObject, IExportAssemblyInspector
    {
        public string DllExportAttributeFullName
        {
            get {
                if(this.InputValues == null)
                {
                    return Utilities.DllExportAttributeFullName;
                }
                return this.InputValues.DllExportAttributeFullName;
            }
        }

        public IInputValues InputValues
        {
            get;
            private set;
        }

        public ExportAssemblyInspector(IInputValues inputValues)
        {
            if(inputValues == null)
            {
                throw new ArgumentNullException("inputValues");
            }
            this.InputValues = inputValues;
        }

        public AssemblyExports ExtractExports(AssemblyDefinition assemblyDefinition)
        {
            return this.ExtractExports(assemblyDefinition, new ExtractExportHandler(this.TryExtractExport));
        }

        public AssemblyExports ExtractExports()
        {
            return this.ExtractExports(this.LoadAssembly(this.InputValues.InputFileName));
        }

        public AssemblyExports ExtractExports(string fileName)
        {
            return this.ExtractExports(this.LoadAssembly(fileName));
        }

        private IList<TypeDefinition> TraverseNestedTypes(ICollection<TypeDefinition> types)
        {
            List<TypeDefinition> typeDefinitionList = new List<TypeDefinition>(types.Count);
            foreach(TypeDefinition type in (IEnumerable<TypeDefinition>)types)
            {
                typeDefinitionList.Add(type);
                if(type.HasNestedTypes)
                {
                    typeDefinitionList.AddRange((IEnumerable<TypeDefinition>)this.TraverseNestedTypes((ICollection<TypeDefinition>)type.NestedTypes));
                }
            }
            return (IList<TypeDefinition>)typeDefinitionList;
        }

        public AssemblyExports ExtractExports(AssemblyDefinition assemblyDefinition, ExtractExportHandler exportFilter)
        {
            IList<TypeDefinition> typeDefinitionList = this.TraverseNestedTypes((ICollection<TypeDefinition>)assemblyDefinition.Modules.SelectMany<ModuleDefinition, TypeDefinition>((Func<ModuleDefinition, IEnumerable<TypeDefinition>>)(m => (IEnumerable<TypeDefinition>)m.Types)).ToList<TypeDefinition>());
            AssemblyExports result = new AssemblyExports() {
                InputValues = this.InputValues
            };
            foreach(TypeDefinition td in (IEnumerable<TypeDefinition>)typeDefinitionList)
            {
                List<ExportedMethod> exportMethods = new List<ExportedMethod>();
                foreach(MethodDefinition method in td.Methods)
                {
                    TypeDefinition typeRefCopy = td;
                    this.CheckForExportedMethods((Func<ExportedMethod>)(() => new ExportedMethod(this.GetExportedClass(typeRefCopy, result))), exportFilter, exportMethods, method);
                }
                foreach(ExportedMethod exportedMethod in exportMethods)
                {
                    this.GetExportedClass(td, result).Methods.Add(exportedMethod);
                }
            }
            result.Refresh();
            return result;
        }

        private ExportedClass GetExportedClass(TypeDefinition td, AssemblyExports result)
        {
            ExportedClass exportedClass;
            if(!result.ClassesByName.TryGetValue(td.FullName, out exportedClass))
            {
                TypeDefinition typeDefinition = td;
                while(!typeDefinition.HasGenericParameters && typeDefinition.IsNested)
                {
                    typeDefinition = typeDefinition.DeclaringType;
                }
                exportedClass = new ExportedClass(td.FullName, typeDefinition.HasGenericParameters);
                result.ClassesByName.Add(exportedClass.FullTypeName, exportedClass);
            }
            return exportedClass;
        }

        public AssemblyExports ExtractExports(string fileName, ExtractExportHandler exportFilter)
        {
            string currentDirectory = Directory.GetCurrentDirectory();
            try
            {
                Directory.SetCurrentDirectory(Path.GetDirectoryName(fileName));
                return this.ExtractExports(this.LoadAssembly(fileName), exportFilter);
            }
            finally
            {
                Directory.SetCurrentDirectory(currentDirectory);
            }
        }

        public AssemblyBinaryProperties GetAssemblyBinaryProperties(string assemblyFileName)
        {
            AssemblyBinaryProperties binaryProperties;
            if(!File.Exists(assemblyFileName))
            {
                binaryProperties = AssemblyBinaryProperties.GetEmpty();
            }
            else
            {
                AssemblyDefinition assemblyDefinition = this.LoadAssembly(assemblyFileName);
                ModuleDefinition mainModule = assemblyDefinition.MainModule;
                string keyFileName = (string)null;
                string keyContainer = (string)null;
                foreach(CustomAttribute customAttribute in assemblyDefinition.CustomAttributes)
                {
                    switch(customAttribute.Constructor.DeclaringType.FullName)
                    {
                        case "System.Reflection.AssemblyKeyFileAttribute":
                        keyFileName = Convert.ToString((object)customAttribute.ConstructorArguments[0], (IFormatProvider)CultureInfo.InvariantCulture);
                        break;

                        case "System.Reflection.AssemblyKeyNameAttribute":
                        keyContainer = Convert.ToString((object)customAttribute.ConstructorArguments[0], (IFormatProvider)CultureInfo.InvariantCulture);
                        break;
                    }
                    if(!string.IsNullOrEmpty(keyFileName))
                    {
                        if(!string.IsNullOrEmpty(keyContainer))
                        {
                            break;
                        }
                    }
                }
                binaryProperties = new AssemblyBinaryProperties(mainModule.Attributes, mainModule.Architecture, assemblyDefinition.Name.HasPublicKey, keyFileName, keyContainer);
            }
            return binaryProperties;
        }

        public AssemblyDefinition LoadAssembly(string fileName)
        {
            return AssemblyDefinition.ReadAssembly(fileName);
        }

        public bool SafeExtractExports(string fileName, Stream stream)
        {
            AssemblyExports exports = this.ExtractExports(fileName);
            bool flag;
            if(exports.Count == 0)
            {
                flag = false;
            }
            else
            {
                new BinaryFormatter().Serialize(stream, (object)exports);
                flag = true;
            }
            return flag;
        }

        private void CheckForExportedMethods(Func<ExportedMethod> createExportMethod, ExtractExportHandler exportFilter, List<ExportedMethod> exportMethods, MethodDefinition mi)
        {<commit_msg>AssemblyDefinition fixes for Mono.Cecil 0.10.x use. Related: #106<commit_after>﻿//# Author of original code ([Decompiled] MIT-License): Copyright (c) 2009-2015  <NAME>
//# Use Readme & LICENSE files for details.

//# Modifications: Copyright (c) 2016-2019  <NAME> < <EMAIL> > GitHub/3F
//$ Distributed under the MIT License (MIT)

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using Mono.Cecil;

namespace RGiesecke.DllExport
{
    internal class ExportAssemblyInspector: MarshalByRefObject, IExportAssemblyInspector
    {
        public string DllExportAttributeFullName
        {
            get {
                if(this.InputValues == null)
                {
                    return Utilities.DllExportAttributeFullName;
                }
                return this.InputValues.DllExportAttributeFullName;
            }
        }

        public IInputValues InputValues
        {
            get;
            private set;
        }

        public ExportAssemblyInspector(IInputValues inputValues)
        {
            if(inputValues == null)
            {
                throw new ArgumentNullException("inputValues");
            }
            this.InputValues = inputValues;
        }

        public AssemblyExports ExtractExports(AssemblyDefinition assemblyDefinition)
        {
            return ExtractExports(assemblyDefinition, new ExtractExportHandler(TryExtractExport));
        }

        public AssemblyExports ExtractExports()
        {
            return ExtractExports(InputValues.InputFileName);
        }

        public AssemblyExports ExtractExports(string fileName)
        {
            AssemblyDefinition def = LoadAssembly(fileName);
            try
            {
                return ExtractExports(def);
            }
            finally
            {
                def.Dispose(); // 0.10.x
            }
        }

        private IList<TypeDefinition> TraverseNestedTypes(ICollection<TypeDefinition> types)
        {
            List<TypeDefinition> typeDefinitionList = new List<TypeDefinition>(types.Count);
            foreach(TypeDefinition type in (IEnumerable<TypeDefinition>)types)
            {
                typeDefinitionList.Add(type);
                if(type.HasNestedTypes)
                {
                    typeDefinitionList.AddRange((IEnumerable<TypeDefinition>)this.TraverseNestedTypes((ICollection<TypeDefinition>)type.NestedTypes));
                }
            }
            return (IList<TypeDefinition>)typeDefinitionList;
        }

        public AssemblyExports ExtractExports(AssemblyDefinition assemblyDefinition, ExtractExportHandler exportFilter)
        {
            IList<TypeDefinition> typeDefinitionList = this.TraverseNestedTypes((ICollection<TypeDefinition>)assemblyDefinition.Modules.SelectMany<ModuleDefinition, TypeDefinition>((Func<ModuleDefinition, IEnumerable<TypeDefinition>>)(m => (IEnumerable<TypeDefinition>)m.Types)).ToList<TypeDefinition>());
            AssemblyExports result = new AssemblyExports() {
                InputValues = this.InputValues
            };
            foreach(TypeDefinition td in (IEnumerable<TypeDefinition>)typeDefinitionList)
            {
                List<ExportedMethod> exportMethods = new List<ExportedMethod>();
                foreach(MethodDefinition method in td.Methods)
                {
                    TypeDefinition typeRefCopy = td;
                    this.CheckForExportedMethods((Func<ExportedMethod>)(() => new ExportedMethod(this.GetExportedClass(typeRefCopy, result))), exportFilter, exportMethods, method);
                }
                foreach(ExportedMethod exportedMethod in exportMethods)
                {
                    this.GetExportedClass(td, result).Methods.Add(exportedMethod);
                }
            }
            result.Refresh();
            return result;
        }

        private ExportedClass GetExportedClass(TypeDefinition td, AssemblyExports result)
        {
            ExportedClass exportedClass;
            if(!result.ClassesByName.TryGetValue(td.FullName, out exportedClass))
            {
                TypeDefinition typeDefinition = td;
                while(!typeDefinition.HasGenericParameters && typeDefinition.IsNested)
                {
                    typeDefinition = typeDefinition.DeclaringType;
                }
                exportedClass = new ExportedClass(td.FullName, typeDefinition.HasGenericParameters);
                result.ClassesByName.Add(exportedClass.FullTypeName, exportedClass);
            }
            return exportedClass;
        }

        public AssemblyExports ExtractExports(string fileName, ExtractExportHandler exportFilter)
        {
            AssemblyDefinition def  = null;
            string currentDirectory = Directory.GetCurrentDirectory();

            try
            {
                Directory.SetCurrentDirectory(Path.GetDirectoryName(fileName));

                def = LoadAssembly(fileName);
                return ExtractExports(def, exportFilter);
            }
            finally
            {
                Directory.SetCurrentDirectory(currentDirectory);
                def.Dispose(); // 0.10.x
            }
        }

        public AssemblyBinaryProperties GetAssemblyBinaryProperties(string assemblyFileName)
        {
            if(!File.Exists(assemblyFileName)) {
                return AssemblyBinaryProperties.GetEmpty();
            }

            AssemblyDefinition assemblyDefinition = LoadAssembly(assemblyFileName);
            ModuleDefinition mainModule = assemblyDefinition.MainModule;

            string keyFileName  = null;
            string keyContainer = null;

            foreach(CustomAttribute customAttribute in assemblyDefinition.CustomAttributes)
            {
                switch(customAttribute.Constructor.DeclaringType.FullName)
                {
                    case "System.Reflection.AssemblyKeyFileAttribute":
                    keyFileName = Convert.ToString(customAttribute.ConstructorArguments[0], CultureInfo.InvariantCulture);
                    break;

                    case "System.Reflection.AssemblyKeyNameAttribute":
                    keyContainer = Convert.ToString(customAttribute.ConstructorArguments[0], CultureInfo.InvariantCulture);
                    break;
                }

                if(!string.IsNullOrEmpty(keyFileName) && !string.IsNullOrEmpty(keyContainer)) {
                    break;
                }
            }

            try
            {
                return new AssemblyBinaryProperties
                (
                    mainModule.Attributes, 
                    mainModule.Architecture, 
                    assemblyDefinition.Name.HasPublicKey, 
                    keyFileName, 
                    keyContainer
                );
            }
            finally
            {
                assemblyDefinition.Dispose(); // 0.10.x
            }
        }

        public AssemblyDefinition LoadAssembly(string fileName)
        {
            return AssemblyDefinition.ReadAssembly
            (
                fileName, 
                new ReaderParameters(ReadingMode.Immediate) { InMemory = true, ReadWrite = true }
            );
        }

        public bool SafeExtractExports(string fileName, Stream stream)
        {
            AssemblyExports exports = this.ExtractExports(fileName);
            bool flag;
            if(exports.Count == 0)
            {
                flag = false;
            }
            else
            {
                new BinaryFormatter().Serialize(stream, (object)exports);
                flag = true;
            }
            return flag;
        }

        private void CheckForExportedMethods(Func<ExportedMethod> createExportMethod, ExtractExportHandler exportFilter, List<ExportedMethod> exportMethods, MethodDefinition mi)
        {
{'fraction_non_alphanumeric': 0.07259034238339346, 'fraction_numerical': 0.003480792354914246, 'mean_word_length': 1.8983859134262655, 'pattern_counts': {'":': 4, '<': 53, '<?xml version=': 0, '>': 57, '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': '969344', 'n_tokens_mistral': 3672, 'n_tokens_neox': 3458, 'n_words': 624}