<commit_before>﻿// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//-----------------------------------------------------------------------
// </copyright>
// <summary>Abstract base class for objects reading toolsets.</summary>
//-----------------------------------------------------------------------

using System;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.Build.Shared;
using Microsoft.Build.Collections;
using Microsoft.Build.Execution;
using Microsoft.Build.Internal;
using error = Microsoft.Build.Shared.ErrorUtilities;
using InvalidProjectFileException = Microsoft.Build.Exceptions.InvalidProjectFileException;
using InvalidToolsetDefinitionException = Microsoft.Build.Exceptions.InvalidToolsetDefinitionException;
using ReservedPropertyNames = Microsoft.Build.Internal.ReservedPropertyNames;

namespace Microsoft.Build.Evaluation
{
    /// <summary>
    /// The abstract base class for all Toolset readers.
    /// </summary>
    internal abstract class ToolsetReader
    {
        /// <summary>
        /// The global properties used to read the toolset.
        /// </summary>
        private PropertyDictionary<ProjectPropertyInstance> _globalProperties;

        /// <summary>
        /// The environment properties used to read the toolset.
        /// </summary>
        private readonly PropertyDictionary<ProjectPropertyInstance> _environmentProperties;

        /// <summary>
        /// Constructor
        /// </summary>
        protected ToolsetReader(
            PropertyDictionary<ProjectPropertyInstance> environmentProperties,
            PropertyDictionary<ProjectPropertyInstance> globalProperties)
        {
            _environmentProperties = environmentProperties;
            _globalProperties = globalProperties;
        }

        /// <summary>
        /// Returns the list of tools versions
        /// </summary>
        protected abstract IEnumerable<ToolsetPropertyDefinition> ToolsVersions
        {
            get;
        }

        /// <summary>
        /// Returns the default tools version, or null if none was specified
        /// </summary>
        protected abstract string DefaultToolsVersion
        {
            get;
        }

        /// <summary>
        /// Returns the path to find override tasks, or null if none was specified
        /// </summary>
        protected abstract string MSBuildOverrideTasksPath
        {
            get;
        }

        /// <summary>
        /// ToolsVersion to use as the default ToolsVersion for this version of MSBuild
        /// </summary>
        protected abstract string DefaultOverrideToolsVersion
        {
            get;
        }

#if FEATURE_WIN32_REGISTRY || FEATURE_SYSTEM_CONFIGURATION
        /// <summary>
        /// Gathers toolset data from the registry and configuration file, if any:
        /// allows you to specify which of the registry and configuration file to
        /// read from by providing ToolsetInitialization
        /// </summary>
        internal static string ReadAllToolsets(Dictionary<string, Toolset> toolsets, PropertyDictionary<ProjectPropertyInstance> environmentProperties, PropertyDictionary<ProjectPropertyInstance> globalProperties, ToolsetDefinitionLocations locations)
        {
            return ReadAllToolsets(toolsets,
#if FEATURE_WIN32_REGISTRY
                null,
#endif
#if FEATURE_SYSTEM_CONFIGURATION
                null,
#endif
                environmentProperties, globalProperties, locations);
        }
#endif

        /// <summary>
        /// Gathers toolset data from the registry and configuration file, if any.
        /// NOTE:  this method is internal for unit testing purposes only.
        /// </summary>
        internal static string ReadAllToolsets
            (
            Dictionary<string, Toolset> toolsets,
#if FEATURE_WIN32_REGISTRY
            ToolsetRegistryReader registryReader,
#endif
#if FEATURE_SYSTEM_CONFIGURATION
            ToolsetConfigurationReader configurationReader,
#endif
            PropertyDictionary<ProjectPropertyInstance> environmentProperties,
            PropertyDictionary<ProjectPropertyInstance> globalProperties,
            ToolsetDefinitionLocations locations
            )
        {
            var initialProperties =
                new PropertyDictionary<ProjectPropertyInstance>(environmentProperties);

            initialProperties.ImportProperties(globalProperties);

            // The ordering here is important because the configuration file should have greater precedence
            // than the registry, and we do a check and don't read in the new toolset if there's already one. 
            string defaultToolsVersionFromConfiguration = null;
            string overrideTasksPathFromConfiguration = null;
            string defaultOverrideToolsVersionFromConfiguration = null;

#if FEATURE_SYSTEM_CONFIGURATION
            if ((locations & ToolsetDefinitionLocations.ConfigurationFile) == ToolsetDefinitionLocations.ConfigurationFile)
            {
                if (configurationReader == null && ToolsetConfigurationReaderHelpers.ConfigurationFileMayHaveToolsets())
                {
                    // We haven't been passed in a fake configuration reader by a unit test,
                    // and it looks like we have a .config file to read, so create a real
                    // configuration reader
                    configurationReader = new ToolsetConfigurationReader(environmentProperties, globalProperties);
                }

                if (configurationReader != null)
                {
                    // Accumulation of properties is okay in the config file because it's deterministically ordered
                    defaultToolsVersionFromConfiguration = configurationReader.ReadToolsets(toolsets, globalProperties,
                        initialProperties, true /* accumulate properties */, out overrideTasksPathFromConfiguration,
                        out defaultOverrideToolsVersionFromConfiguration);
                }
            }<commit_msg>[mono] ToolsetReader: allow app.config to be read when running tests<commit_after>﻿// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//-----------------------------------------------------------------------
// </copyright>
// <summary>Abstract base class for objects reading toolsets.</summary>
//-----------------------------------------------------------------------

using System;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.Build.Shared;
using Microsoft.Build.Collections;
using Microsoft.Build.Execution;
using Microsoft.Build.Internal;
using error = Microsoft.Build.Shared.ErrorUtilities;
using InvalidProjectFileException = Microsoft.Build.Exceptions.InvalidProjectFileException;
using InvalidToolsetDefinitionException = Microsoft.Build.Exceptions.InvalidToolsetDefinitionException;
using ReservedPropertyNames = Microsoft.Build.Internal.ReservedPropertyNames;

namespace Microsoft.Build.Evaluation
{
    /// <summary>
    /// The abstract base class for all Toolset readers.
    /// </summary>
    internal abstract class ToolsetReader
    {
        /// <summary>
        /// The global properties used to read the toolset.
        /// </summary>
        private PropertyDictionary<ProjectPropertyInstance> _globalProperties;

        /// <summary>
        /// The environment properties used to read the toolset.
        /// </summary>
        private readonly PropertyDictionary<ProjectPropertyInstance> _environmentProperties;

        /// <summary>
        /// Constructor
        /// </summary>
        protected ToolsetReader(
            PropertyDictionary<ProjectPropertyInstance> environmentProperties,
            PropertyDictionary<ProjectPropertyInstance> globalProperties)
        {
            _environmentProperties = environmentProperties;
            _globalProperties = globalProperties;
        }

        /// <summary>
        /// Returns the list of tools versions
        /// </summary>
        protected abstract IEnumerable<ToolsetPropertyDefinition> ToolsVersions
        {
            get;
        }

        /// <summary>
        /// Returns the default tools version, or null if none was specified
        /// </summary>
        protected abstract string DefaultToolsVersion
        {
            get;
        }

        /// <summary>
        /// Returns the path to find override tasks, or null if none was specified
        /// </summary>
        protected abstract string MSBuildOverrideTasksPath
        {
            get;
        }

        /// <summary>
        /// ToolsVersion to use as the default ToolsVersion for this version of MSBuild
        /// </summary>
        protected abstract string DefaultOverrideToolsVersion
        {
            get;
        }

#if FEATURE_WIN32_REGISTRY || FEATURE_SYSTEM_CONFIGURATION
        /// <summary>
        /// Gathers toolset data from the registry and configuration file, if any:
        /// allows you to specify which of the registry and configuration file to
        /// read from by providing ToolsetInitialization
        /// </summary>
        internal static string ReadAllToolsets(Dictionary<string, Toolset> toolsets, PropertyDictionary<ProjectPropertyInstance> environmentProperties, PropertyDictionary<ProjectPropertyInstance> globalProperties, ToolsetDefinitionLocations locations)
        {
            return ReadAllToolsets(toolsets,
#if FEATURE_WIN32_REGISTRY
                null,
#endif
#if FEATURE_SYSTEM_CONFIGURATION
                null,
#endif
                environmentProperties, globalProperties, locations);
        }
#endif

        /// <summary>
        /// Gathers toolset data from the registry and configuration file, if any.
        /// NOTE:  this method is internal for unit testing purposes only.
        /// </summary>
        internal static string ReadAllToolsets
            (
            Dictionary<string, Toolset> toolsets,
#if FEATURE_WIN32_REGISTRY
            ToolsetRegistryReader registryReader,
#endif
#if FEATURE_SYSTEM_CONFIGURATION
            ToolsetConfigurationReader configurationReader,
#endif
            PropertyDictionary<ProjectPropertyInstance> environmentProperties,
            PropertyDictionary<ProjectPropertyInstance> globalProperties,
            ToolsetDefinitionLocations locations
            )
        {
            var initialProperties =
                new PropertyDictionary<ProjectPropertyInstance>(environmentProperties);

            initialProperties.ImportProperties(globalProperties);

            // The ordering here is important because the configuration file should have greater precedence
            // than the registry, and we do a check and don't read in the new toolset if there's already one. 
            string defaultToolsVersionFromConfiguration = null;
            string overrideTasksPathFromConfiguration = null;
            string defaultOverrideToolsVersionFromConfiguration = null;

#if FEATURE_SYSTEM_CONFIGURATION
            if ((locations & ToolsetDefinitionLocations.ConfigurationFile) == ToolsetDefinitionLocations.ConfigurationFile)
            {
                if (configurationReader == null)
                {
                    configurationReader = new ToolsetConfigurationReader(environmentProperties, globalProperties);
                }

                // Accumulation of properties is okay in the config file because it's deterministically ordered
                defaultToolsVersionFromConfiguration = configurationReader.ReadToolsets(toolsets, globalProperties,
                    initialProperties, true /* accumulate properties */, out overrideTasksPathFromConfiguration,
                    out defaultOverrideToolsVersionFromConfiguration);
            }
{'fraction_non_alphanumeric': 0.08924296210682738, 'fraction_numerical': 0.0009906711797242633, 'mean_word_length': 2.2829268292682925, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 73, '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': '3383342', 'n_tokens_mistral': 2556, 'n_tokens_neox': 2483, 'n_words': 797}