<commit_before>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Reinforced.Typings.Attributes;
using Reinforced.Typings.Fluent;
using Reinforced.Typings.Xmldoc;

namespace Reinforced.Typings
{
    /// <summary>
    ///     Facade for final TypeScript export. This class supplies assemblies names or assemblies itself as parameter and
    ///     exports resulting TypeScript file to file or to string
    /// </summary>
    public class TsExporter : MarshalByRefObject
    {
        private readonly FilesOperations _fileOps;
        private readonly StringBuilder _referenceBuilder = new StringBuilder();
        private readonly ExportSettings _settings;
        private List<Type> _allTypes;
        private HashSet<Type> _allTypesHash;
        private ConfigurationRepository _configurationRepository;
        private bool _isAnalyzed;
        private Dictionary<string, List<Type>> _namespace = new Dictionary<string, List<Type>>();

        #region Constructors

        /// <summary>
        ///     Constructs new instance of TypeScript exporter
        /// </summary>
        /// <param name="settings"></param>
        public TsExporter(ExportSettings settings)
        {
            _settings = settings;
            _fileOps = new FilesOperations(settings);
        }

        #endregion

        private void ExtractReferences()
        {
            if (_isAnalyzed) return;
            _settings.Documentation =
                new DocumentationManager(_settings.GenerateDocumentation ? _settings.DocumentationFilePath : null);
            var fluentConfigurationPresents = _settings.ConfigurationMethod != null;
            if (fluentConfigurationPresents)
            {
                var configurationBuilder = new ConfigurationBuilder();
                _settings.ConfigurationMethod(configurationBuilder);
                _configurationRepository = configurationBuilder.Build();
                ConfigurationRepository.Instance = _configurationRepository;

                foreach (var additionalDocumentationPath in _configurationRepository.AdditionalDocumentationPathes)
                {
                    _settings.Documentation.CacheDocumentation(additionalDocumentationPath);
                }
            }

            _allTypes = _settings.SourceAssemblies
                .SelectMany(c => c.GetTypes().Where(d => d.GetCustomAttribute<TsAttributeBase>(false) != null))
                .Union(ConfigurationRepository.Instance.AttributesForType.Keys).Distinct()
                .ToList();

            _allTypesHash = new HashSet<Type>(_allTypes);

            if (_settings.Hierarchical)
            {
                foreach (var type in _allTypesHash)
                {
                    ConfigurationRepository.Instance.AddFileSeparationSettings(type);
                }
            }

            var grp = _allTypes.GroupBy(c => c.GetNamespace(true));
            _namespace = grp.Where(g => !string.IsNullOrEmpty(g.Key)) // avoid anonymous types
                .ToDictionary(k => k.Key, v => v.ToList());

            _settings.SourceAssemblies.Where(c => c.GetCustomAttributes<TsReferenceAttribute>().Any())
                .SelectMany(c => c.GetCustomAttributes<TsReferenceAttribute>())
                .Select(c => string.Format("/// <reference path=\"{0}\"/>", c.Path))
                .Union(
                    ConfigurationRepository.Instance.References.Select(
                        c => string.Format("/// <reference path=\"{0}\"/>", c)))
                .ToList()
                .ForEach(a => _referenceBuilder.AppendLine(a));

            _settings.References = _referenceBuilder.ToString();


            _isAnalyzed = true;
        }

        /// <summary>
        ///     Exports TypeScript source to specified TextWriter according to settings
        /// </summary>
        /// <param name="sw">TextWriter</param>
        /// <param name="tr">TypeResolver object</param>
        /// <param name="types">Types to export</param>
        public void ExportTypes(TextWriter sw, TypeResolver tr, IEnumerable<Type> types = null)
        {
            ExportReferences(sw, types);
            if (types == null) types = _allTypes;
            ExportNamespaces(types, tr, sw);
        }

        private void ExportReferences(TextWriter tw, IEnumerable<Type> types = null)
        {
            tw.WriteLine(_referenceBuilder.ToString());
            WriteWarning(tw);
            if (types != null)
            {
                var atLeast = false;
                foreach (var type in types)
                {
                    var inspected = _fileOps.GenerateInspectedReferences(type, _allTypesHash);
                    if (!string.IsNullOrEmpty(inspected) && !string.IsNullOrWhiteSpace(inspected))
                    {
                        tw.WriteLine(inspected);
                        atLeast = true;
                    }
                }
                if (atLeast) tw.WriteLine();
            }
        }

        /// <summary>
        ///     Exports TypeScript source according to settings
        /// </summary>
        public void Export()
        {
            _fileOps.ClearTempRegistry();
            ExtractReferences();
            var tr = new TypeResolver(_settings);
            _settings.Lock();

            if (!_settings.Hierarchical)
            {
                var file = _fileOps.GetTmpFile(_settings.TargetFile);<commit_msg>references fix<commit_after>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Reinforced.Typings.Attributes;
using Reinforced.Typings.Fluent;
using Reinforced.Typings.Xmldoc;

namespace Reinforced.Typings
{
    /// <summary>
    ///     Facade for final TypeScript export. This class supplies assemblies names or assemblies itself as parameter and
    ///     exports resulting TypeScript file to file or to string
    /// </summary>
    public class TsExporter : MarshalByRefObject
    {
        private readonly FilesOperations _fileOps;
        private readonly StringBuilder _referenceBuilder = new StringBuilder();
        private readonly ExportSettings _settings;
        private List<Type> _allTypes;
        private HashSet<Type> _allTypesHash;
        private ConfigurationRepository _configurationRepository;
        private bool _isAnalyzed;
        private Dictionary<string, List<Type>> _namespace = new Dictionary<string, List<Type>>();

        #region Constructors

        /// <summary>
        ///     Constructs new instance of TypeScript exporter
        /// </summary>
        /// <param name="settings"></param>
        public TsExporter(ExportSettings settings)
        {
            _settings = settings;
            _fileOps = new FilesOperations(settings);
        }

        #endregion

        private void ExtractReferences()
        {
            if (_isAnalyzed) return;
            _settings.Documentation =
                new DocumentationManager(_settings.GenerateDocumentation ? _settings.DocumentationFilePath : null);
            var fluentConfigurationPresents = _settings.ConfigurationMethod != null;
            if (fluentConfigurationPresents)
            {
                var configurationBuilder = new ConfigurationBuilder();
                _settings.ConfigurationMethod(configurationBuilder);
                _configurationRepository = configurationBuilder.Build();
                ConfigurationRepository.Instance = _configurationRepository;

                foreach (var additionalDocumentationPath in _configurationRepository.AdditionalDocumentationPathes)
                {
                    _settings.Documentation.CacheDocumentation(additionalDocumentationPath);
                }
            }

            _allTypes = _settings.SourceAssemblies
                .SelectMany(c => c.GetTypes().Where(d => d.GetCustomAttribute<TsAttributeBase>(false) != null))
                .Union(ConfigurationRepository.Instance.AttributesForType.Keys).Distinct()
                .ToList();

            _allTypesHash = new HashSet<Type>(_allTypes);

            if (_settings.Hierarchical)
            {
                foreach (var type in _allTypesHash)
                {
                    ConfigurationRepository.Instance.AddFileSeparationSettings(type);
                }
            }

            var grp = _allTypes.GroupBy(c => c.GetNamespace(true));
            _namespace = grp.Where(g => !string.IsNullOrEmpty(g.Key)) // avoid anonymous types
                .ToDictionary(k => k.Key, v => v.ToList());

            _settings.SourceAssemblies.Where(c => c.GetCustomAttributes<TsReferenceAttribute>().Any())
                .SelectMany(c => c.GetCustomAttributes<TsReferenceAttribute>())
                .Select(c => string.Format("/// <reference path=\"{0}\"/>", c.Path))
                .Union(
                    ConfigurationRepository.Instance.References.Select(
                        c => string.Format("/// <reference path=\"{0}\"/>", c)))
                .ToList()
                .ForEach(a => _referenceBuilder.AppendLine(a));

            _settings.References = _referenceBuilder.ToString();


            _isAnalyzed = true;
        }

        /// <summary>
        ///     Exports TypeScript source to specified TextWriter according to settings
        /// </summary>
        /// <param name="sw">TextWriter</param>
        /// <param name="tr">TypeResolver object</param>
        /// <param name="types">Types to export</param>
        public void ExportTypes(TextWriter sw, TypeResolver tr, IEnumerable<Type> types = null)
        {
            ExportReferences(sw, types);
            if (types == null) types = _allTypes;
            ExportNamespaces(types, tr, sw);
        }

        private void ExportReferences(TextWriter tw, IEnumerable<Type> types = null)
        {
            WriteWarning(tw);
            tw.WriteLine(_referenceBuilder.ToString());
            if (types != null)
            {
            
                foreach (var type in types)
                {
                    var inspected = _fileOps.GenerateInspectedReferences(type, _allTypesHash);
                    if (!string.IsNullOrEmpty(inspected) && !string.IsNullOrWhiteSpace(inspected)) tw.WriteLine(inspected);
                }
            
            }
        }

        /// <summary>
        ///     Exports TypeScript source according to settings
        /// </summary>
        public void Export()
        {
            _fileOps.ClearTempRegistry();
            ExtractReferences();
            var tr = new TypeResolver(_settings);
            _settings.Lock();

            if (!_settings.Hierarchical)
            {
                var file = _fileOps.GetTmpFile(_settings.TargetFile);
{'fraction_non_alphanumeric': 0.09624781045450355, 'fraction_numerical': 0.00036876555729694845, 'mean_word_length': 1.9470252648736757, 'pattern_counts': {'":': 0, '<': 63, '<?xml version=': 0, '>': 85, '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': '499286', 'n_tokens_mistral': 2640, 'n_tokens_neox': 2505, 'n_words': 568}