<commit_before>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Web.Compilation;
using System.Web.Hosting;
using System.Web.WebPages.Razor;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web.Cache;
using Umbraco.ModelsBuilder.Building;
using Umbraco.ModelsBuilder.Configuration;
using File = System.IO.File;

namespace Umbraco.ModelsBuilder.Umbraco
{
    class PureLiveModelFactory : IPublishedContentModelFactory
    {
        private Assembly _modelsAssembly;
        private Dictionary<string, Func<IPublishedContent, IPublishedContent>> _constructors;
        private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim();
        private bool _hasModels;
        private bool _pendingRebuild;
        private readonly ProfilingLogger _logger;

        public PureLiveModelFactory(ProfilingLogger logger)
        {
            _logger = logger;
            ContentTypeCacheRefresher.CacheUpdated += (sender, args) => ResetModels();
            DataTypeCacheRefresher.CacheUpdated += (sender, args) => ResetModels();
            RazorBuildProvider.CodeGenerationStarted += RazorBuildProvider_CodeGenerationStarted;
        }

        #region IPublishedContentModelFactory

        public IPublishedContent CreateModel(IPublishedContent content)
        {
            // get models, rebuilding them if needed
            var constructors = EnsureModels();
            if (constructors == null)
                return null;

            // be case-insensitive
            var contentTypeAlias = content.DocumentTypeAlias;

            // lookup model constructor (else null)
            Func<IPublishedContent, IPublishedContent> constructor;
            constructors.TryGetValue(contentTypeAlias, out constructor);

            // create model
            return constructor == null ? content : constructor(content);
        }

        #endregion

        #region Compilation

        private void RazorBuildProvider_CodeGenerationStarted(object sender, EventArgs e)
        {
            var provider = sender as RazorBuildProvider;
            provider?.AssemblyBuilder.AddAssemblyReference(_modelsAssembly);
        }

        // tells the factory that it should build a new generation of models
        private void ResetModels()
        {
            _logger.Logger.Debug<PureLiveModelFactory>("Resetting models.");
            _locker.EnterWriteLock();
            try
            {
                _hasModels = false;
                _pendingRebuild = true;
            }
            finally
            {
                _locker.ExitWriteLock();
            }
        }

        // ensure that the factory is running with the lastest generation of models
        internal Dictionary<string, Func<IPublishedContent, IPublishedContent>> EnsureModels()
        {
            _logger.Logger.Debug<PureLiveModelFactory>("Ensuring models.");
            _locker.EnterReadLock();
            try
            {
                if (_hasModels) return _constructors;
            }<commit_msg>Bugfix weird Razor analysis error on restarts<commit_after>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Web.Compilation;
using System.Web.Hosting;
using System.Web.WebPages.Razor;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web.Cache;
using Umbraco.ModelsBuilder.Building;
using Umbraco.ModelsBuilder.Configuration;
using File = System.IO.File;

namespace Umbraco.ModelsBuilder.Umbraco
{
    class PureLiveModelFactory : IPublishedContentModelFactory
    {
        private Assembly _modelsAssembly;
        private Dictionary<string, Func<IPublishedContent, IPublishedContent>> _constructors;
        private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim();
        private bool _hasModels;
        private bool _pendingRebuild;
        private readonly ProfilingLogger _logger;

        public PureLiveModelFactory(ProfilingLogger logger)
        {
            _logger = logger;
            ContentTypeCacheRefresher.CacheUpdated += (sender, args) => ResetModels();
            DataTypeCacheRefresher.CacheUpdated += (sender, args) => ResetModels();
            RazorBuildProvider.CodeGenerationStarted += RazorBuildProvider_CodeGenerationStarted;
        }

        #region IPublishedContentModelFactory

        public IPublishedContent CreateModel(IPublishedContent content)
        {
            // get models, rebuilding them if needed
            var constructors = EnsureModels();
            if (constructors == null)
                return null;

            // be case-insensitive
            var contentTypeAlias = content.DocumentTypeAlias;

            // lookup model constructor (else null)
            Func<IPublishedContent, IPublishedContent> constructor;
            constructors.TryGetValue(contentTypeAlias, out constructor);

            // create model
            return constructor == null ? content : constructor(content);
        }

        #endregion

        #region Compilation

        private void RazorBuildProvider_CodeGenerationStarted(object sender, EventArgs e)
        {
            // just be safe - can happen if the first view is not an Umbraco view
            if (_modelsAssembly == null) return;

            var provider = sender as RazorBuildProvider;
            provider?.AssemblyBuilder.AddAssemblyReference(_modelsAssembly);
        }

        // tells the factory that it should build a new generation of models
        private void ResetModels()
        {
            _logger.Logger.Debug<PureLiveModelFactory>("Resetting models.");
            _locker.EnterWriteLock();
            try
            {
                _hasModels = false;
                _pendingRebuild = true;
            }
            finally
            {
                _locker.ExitWriteLock();
            }
        }

        // ensure that the factory is running with the lastest generation of models
        internal Dictionary<string, Func<IPublishedContent, IPublishedContent>> EnsureModels()
        {
            _logger.Logger.Debug<PureLiveModelFactory>("Ensuring models.");
            _locker.EnterReadLock();
            try
            {
                if (_hasModels) return _constructors;
            }
{'fraction_non_alphanumeric': 0.07064083457526081, 'fraction_numerical': 0.0, 'mean_word_length': 2.4450718685831623, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 21, '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': '3014050', 'n_tokens_mistral': 1671, 'n_tokens_neox': 1617, 'n_words': 410}