<commit_before>﻿using Serenity.ComponentModel;
using Serenity.Data;
using Serenity.Reflection;
using Serenity.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
#if ASPNETCORE
using Microsoft.AspNetCore.Mvc;
#else
using System.Web.Mvc;
#endif

namespace Serenity.CodeGeneration
{
    public abstract class ServerImportGeneratorBase : ImportGeneratorBase
    {
        private HashSet<Type> visited;
        private Queue<Type> generateQueue;
        protected List<Type> lookupScripts;
        protected HashSet<string> generatedTypes;
        protected string fileIdentifier;

        public ServerImportGeneratorBase(params Assembly[] assemblies)
            : base()
        {
            generatedTypes = new HashSet<string>();

            if (assemblies == null || assemblies.Length == 0)
                throw new ArgumentNullException("assembly");

            this.Assemblies = assemblies;
        }

        public Assembly[] Assemblies { get; private set; }

        protected virtual bool EnqueueType(Type type)
        {
            if (visited.Contains(type))
                return false;

            visited.Add(type);
            generateQueue.Enqueue(type);
            return true;
        }

        protected virtual void EnqueueTypeMembers(Type type)
        {
            foreach (var member in type.GetMembers(BindingFlags.Public | BindingFlags.Instance))
            {
                var pi = member as PropertyInfo;
                var fi = member as FieldInfo;

                if (pi == null && fi == null)
                    continue;

                var memberType = pi != null ? pi.PropertyType : fi.FieldType;
                if (memberType == null)
                    continue;

                var nullableType = Nullable.GetUnderlyingType(memberType);
                if (nullableType != null)
                    memberType = nullableType;

                if (memberType.GetIsEnum())
                    EnqueueType(memberType);
            }
        }

        protected virtual string GetNamespace(Type type)
        {
            var ns = type.Namespace ?? "";
            if (ns.EndsWith(".Entities"))
                return ns.Substring(0, ns.Length - ".Entities".Length);

            if (ns.EndsWith(".Endpoints"))
                return ns.Substring(0, ns.Length - ".Endpoints".Length);

            if (ns.EndsWith(".Forms"))
                return ns.Substring(0, ns.Length - ".Forms".Length);

            if (ns.EndsWith(".Columns"))
                return ns.Substring(0, ns.Length - ".Columns".Length);

            return ns;
        }
        protected virtual string GetControllerIdentifier(Type controller)
        {
            string className = controller.Name;

            if (className.EndsWith("Controller"))
                className = className.Substring(0, className.Length - 10);

            return className + "Service";
        }

        protected override void Reset()
        {
            base.Reset();

            this.cw.BraceOnSameLine = IsTS();
            this.generateQueue = new Queue<Type>();
            this.visited = new HashSet<Type>();
            this.lookupScripts = new List<Type>();
        }

        protected abstract bool IsTS();

        protected override void GenerateAll()
        {
            foreach (var assembly in this.Assemblies)
                foreach (var fromType in assembly.GetTypes())
                {
                    if (fromType.GetIsAbstract())
                        continue;

                    if (fromType.IsSubclassOf(typeof(ServiceRequest)) ||
                        fromType.IsSubclassOf(typeof(ServiceResponse)) ||
                        fromType.IsSubclassOf(typeof(Row)) ||
                        fromType.GetCustomAttribute<ScriptIncludeAttribute>() != null ||
                        fromType.GetCustomAttribute<FormScriptAttribute>() != null ||
                        fromType.GetCustomAttribute<ColumnsScriptAttribute>() != null ||
                        fromType.IsSubclassOf(typeof(ServiceEndpoint)) ||
                        (fromType.IsSubclassOf(typeof(Controller)) && // backwards compability
                         fromType.Namespace != null &&
                         fromType.Namespace.EndsWith(".Endpoints")))
                    {
                        EnqueueType(fromType);
                        continue;
                    }

                    if (fromType.GetCustomAttribute<LookupScriptAttribute>() != null)
                    {
                        lookupScripts.Add(fromType);
                        continue;
                    }
                }

            while (generateQueue.Count > 0)
            {
                var type = generateQueue.Dequeue();

                if (!this.Assemblies.Contains(type.GetAssembly()))
                    continue;

                var ns = GetNamespace(type);
                this.fileIdentifier = type.Name;<commit_msg>skip assemblies that doesn't like to list its types, closes #2340<commit_after>﻿using Serenity.ComponentModel;
using Serenity.Data;
using Serenity.Reflection;
using Serenity.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
#if ASPNETCORE
using Microsoft.AspNetCore.Mvc;
#else
using System.Web.Mvc;
#endif

namespace Serenity.CodeGeneration
{
    public abstract class ServerImportGeneratorBase : ImportGeneratorBase
    {
        private HashSet<Type> visited;
        private Queue<Type> generateQueue;
        protected List<Type> lookupScripts;
        protected HashSet<string> generatedTypes;
        protected string fileIdentifier;

        public ServerImportGeneratorBase(params Assembly[] assemblies)
            : base()
        {
            generatedTypes = new HashSet<string>();

            if (assemblies == null || assemblies.Length == 0)
                throw new ArgumentNullException("assembly");

            this.Assemblies = assemblies;
        }

        public Assembly[] Assemblies { get; private set; }

        protected virtual bool EnqueueType(Type type)
        {
            if (visited.Contains(type))
                return false;

            visited.Add(type);
            generateQueue.Enqueue(type);
            return true;
        }

        protected virtual void EnqueueTypeMembers(Type type)
        {
            foreach (var member in type.GetMembers(BindingFlags.Public | BindingFlags.Instance))
            {
                var pi = member as PropertyInfo;
                var fi = member as FieldInfo;

                if (pi == null && fi == null)
                    continue;

                var memberType = pi != null ? pi.PropertyType : fi.FieldType;
                if (memberType == null)
                    continue;

                var nullableType = Nullable.GetUnderlyingType(memberType);
                if (nullableType != null)
                    memberType = nullableType;

                if (memberType.GetIsEnum())
                    EnqueueType(memberType);
            }
        }

        protected virtual string GetNamespace(Type type)
        {
            var ns = type.Namespace ?? "";
            if (ns.EndsWith(".Entities"))
                return ns.Substring(0, ns.Length - ".Entities".Length);

            if (ns.EndsWith(".Endpoints"))
                return ns.Substring(0, ns.Length - ".Endpoints".Length);

            if (ns.EndsWith(".Forms"))
                return ns.Substring(0, ns.Length - ".Forms".Length);

            if (ns.EndsWith(".Columns"))
                return ns.Substring(0, ns.Length - ".Columns".Length);

            return ns;
        }
        protected virtual string GetControllerIdentifier(Type controller)
        {
            string className = controller.Name;

            if (className.EndsWith("Controller"))
                className = className.Substring(0, className.Length - 10);

            return className + "Service";
        }

        protected override void Reset()
        {
            base.Reset();

            this.cw.BraceOnSameLine = IsTS();
            this.generateQueue = new Queue<Type>();
            this.visited = new HashSet<Type>();
            this.lookupScripts = new List<Type>();
        }

        protected abstract bool IsTS();

        protected override void GenerateAll()
        {
            foreach (var assembly in this.Assemblies)
            {
                Type[] types;
                try
                {
                    types = assembly.GetTypes();
                }
                catch
                {
                    // skip assemblies that doesn't like to list its types (e.g. some SignalR reported in #2340)
                    continue;
                }

                foreach (var fromType in types)
                {
                    if (fromType.GetIsAbstract())
                        continue;

                    if (fromType.IsSubclassOf(typeof(ServiceRequest)) ||
                        fromType.IsSubclassOf(typeof(ServiceResponse)) ||
                        fromType.IsSubclassOf(typeof(Row)) ||
                        fromType.GetCustomAttribute<ScriptIncludeAttribute>() != null ||
                        fromType.GetCustomAttribute<FormScriptAttribute>() != null ||
                        fromType.GetCustomAttribute<ColumnsScriptAttribute>() != null ||
                        fromType.IsSubclassOf(typeof(ServiceEndpoint)) ||
                        (fromType.IsSubclassOf(typeof(Controller)) && // backwards compability
                         fromType.Namespace != null &&
                         fromType.Namespace.EndsWith(".Endpoints")))
                    {
                        EnqueueType(fromType);
                        continue;
                    }

                    if (fromType.GetCustomAttribute<LookupScriptAttribute>() != null)
                    {
                        lookupScripts.Add(fromType);
                        continue;
                    }
                }
            }

            while (generateQueue.Count > 0)
            {
                var type = generateQueue.Dequeue();

                if (!this.Assemblies.Contains(type.GetAssembly()))
                    continue;

                var ns = GetNamespace(type);
                this.fileIdentifier = type.Name;
{'fraction_non_alphanumeric': 0.09148385860714628, 'fraction_numerical': 0.0024906600249066002, 'mean_word_length': 1.5217391304347827, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 29, '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': '4331307', 'n_tokens_mistral': 2539, 'n_tokens_neox': 2368, 'n_words': 549}