Example #1
0
 private static async System.Threading.Tasks.Task RunCoverToolAsync(CoverageProject project)
 {
     if (project.IsDotNetSdkStyle())
     {
         await CoverletUtil.RunCoverletAsync(project, true);
     }
     else
     {
         await OpenCoverUtil.RunOpenCoverAsync(project, true);
     }
 }
Example #2
0
        private static List <ReferencedProject> GetReferencedProjects(CoverageProject project)
        {
            /*
             * <ItemGroup>
             *      <ProjectReference Include="..\BranchCoverage\Branch_Coverage.csproj" />
             *      <ProjectReference Include="..\FxClassLibrary1\FxClassLibrary1.csproj"></ProjectReference>
             * </ItemGroup>
             */

            var referencedProjects = new List <ReferencedProject>();

            var xprojectReferences = project.ProjectFileXElement.XPathSelectElements($"/ItemGroup/ProjectReference[@Include]");

            foreach (var xprojectReference in xprojectReferences)
            {
                var referencedProject = new ReferencedProject();

                // ProjectFile

                referencedProject.ProjectFile = xprojectReference.Attribute("Include").Value;

                if (!Path.IsPathRooted(referencedProject.ProjectFile))
                {
                    referencedProject.ProjectFile = Path.GetFullPath(Path.Combine(project.ProjectFolder, referencedProject.ProjectFile));
                }

                // ProjectFileXElement

                referencedProject.ProjectFileXElement = XElementUtil.Load(referencedProject.ProjectFile, true);

                // HasExcludeFromCodeCoverageAssemblyAttribute

                referencedProject.HasExcludeFromCodeCoverageAssemblyAttribute = HasExcludeFromCodeCoverageAssemblyAttribute(referencedProject.ProjectFileXElement);

                // AssemblyName

                referencedProject.AssemblyName = GetAssemblyName(referencedProject.ProjectFileXElement, Path.GetFileNameWithoutExtension(referencedProject.ProjectFile));

                // add

                referencedProjects.Add(referencedProject);
            }

            return(referencedProjects);
        }
Example #3
0
        private static AppOptions GetSettings(CoverageProject project)
        {
            // get global settings

            var settings = AppOptions.Get();

            /*
             * ========================================
             * Process PropertyGroup settings
             * ========================================
             * <PropertyGroup Label="FineCodeCoverage">
             *      ...
             * </PropertyGroup>
             */

            var settingsPropertyGroup = project.ProjectFileXElement.XPathSelectElement($"/PropertyGroup[@Label='{Vsix.Code}']");

            if (settingsPropertyGroup != null)
            {
                foreach (var property in settings.GetType().GetProperties())
                {
                    try
                    {
                        var xproperty = settingsPropertyGroup.Descendants().FirstOrDefault(x => x.Name.LocalName.Equals(property.Name, StringComparison.OrdinalIgnoreCase));

                        if (xproperty == null)
                        {
                            continue;
                        }

                        var strValue = xproperty.Value;

                        if (string.IsNullOrWhiteSpace(strValue))
                        {
                            continue;
                        }

                        var strValueArr = strValue.Split('\n', '\r').Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim()).ToArray();

                        if (!strValue.Any())
                        {
                            continue;
                        }

                        if (TypeMatch(property.PropertyType, typeof(string)))
                        {
                            property.SetValue(settings, strValueArr.FirstOrDefault());
                        }
                        else if (TypeMatch(property.PropertyType, typeof(string[])))
                        {
                            property.SetValue(settings, strValueArr);
                        }

                        else if (TypeMatch(property.PropertyType, typeof(bool), typeof(bool?)))
                        {
                            if (bool.TryParse(strValueArr.FirstOrDefault(), out bool value))
                            {
                                property.SetValue(settings, value);
                            }
                        }
                        else if (TypeMatch(property.PropertyType, typeof(bool[]), typeof(bool?[])))
                        {
                            var arr = strValueArr.Where(x => bool.TryParse(x, out var _)).Select(x => bool.Parse(x));
                            if (arr.Any())
                            {
                                property.SetValue(settings, arr);
                            }
                        }

                        else if (TypeMatch(property.PropertyType, typeof(int), typeof(int?)))
                        {
                            if (int.TryParse(strValueArr.FirstOrDefault(), out var value))
                            {
                                property.SetValue(settings, value);
                            }
                        }
                        else if (TypeMatch(property.PropertyType, typeof(int[]), typeof(int?[])))
                        {
                            var arr = strValueArr.Where(x => int.TryParse(x, out var _)).Select(x => int.Parse(x));
                            if (arr.Any())
                            {
                                property.SetValue(settings, arr);
                            }
                        }

                        else if (TypeMatch(property.PropertyType, typeof(short), typeof(short?)))
                        {
                            if (short.TryParse(strValueArr.FirstOrDefault(), out var vaue))
                            {
                                property.SetValue(settings, vaue);
                            }
                        }
                        else if (TypeMatch(property.PropertyType, typeof(short[]), typeof(short?[])))
                        {
                            var arr = strValueArr.Where(x => short.TryParse(x, out var _)).Select(x => short.Parse(x));
                            if (arr.Any())
                            {
                                property.SetValue(settings, arr);
                            }
                        }

                        else if (TypeMatch(property.PropertyType, typeof(long), typeof(long?)))
                        {
                            if (long.TryParse(strValueArr.FirstOrDefault(), out var value))
                            {
                                property.SetValue(settings, value);
                            }
                        }
                        else if (TypeMatch(property.PropertyType, typeof(long[]), typeof(long?[])))
                        {
                            var arr = strValueArr.Where(x => long.TryParse(x, out var _)).Select(x => long.Parse(x));
                            if (arr.Any())
                            {
                                property.SetValue(settings, arr);
                            }
                        }

                        else if (TypeMatch(property.PropertyType, typeof(decimal), typeof(decimal?)))
                        {
                            if (decimal.TryParse(strValueArr.FirstOrDefault(), out var value))
                            {
                                property.SetValue(settings, value);
                            }
                        }
                        else if (TypeMatch(property.PropertyType, typeof(decimal[]), typeof(decimal?[])))
                        {
                            var arr = strValueArr.Where(x => decimal.TryParse(x, out var _)).Select(x => decimal.Parse(x));
                            if (arr.Any())
                            {
                                property.SetValue(settings, arr);
                            }
                        }

                        else if (TypeMatch(property.PropertyType, typeof(double), typeof(double?)))
                        {
                            if (double.TryParse(strValueArr.FirstOrDefault(), out var value))
                            {
                                property.SetValue(settings, value);
                            }
                        }
                        else if (TypeMatch(property.PropertyType, typeof(double[]), typeof(double?[])))
                        {
                            var arr = strValueArr.Where(x => double.TryParse(x, out var _)).Select(x => double.Parse(x));
                            if (arr.Any())
                            {
                                property.SetValue(settings, arr);
                            }
                        }

                        else if (TypeMatch(property.PropertyType, typeof(float), typeof(float?)))
                        {
                            if (float.TryParse(strValueArr.FirstOrDefault(), out var value))
                            {
                                property.SetValue(settings, value);
                            }
                        }
                        else if (TypeMatch(property.PropertyType, typeof(float[]), typeof(float?[])))
                        {
                            var arr = strValueArr.Where(x => float.TryParse(x, out var _)).Select(x => float.Parse(x));
                            if (arr.Any())
                            {
                                property.SetValue(settings, arr);
                            }
                        }

                        else if (TypeMatch(property.PropertyType, typeof(char), typeof(char?)))
                        {
                            if (char.TryParse(strValueArr.FirstOrDefault(), out var value))
                            {
                                property.SetValue(settings, value);
                            }
                        }
                        else if (TypeMatch(property.PropertyType, typeof(char[]), typeof(char?[])))
                        {
                            var arr = strValueArr.Where(x => char.TryParse(x, out var _)).Select(x => char.Parse(x));
                            if (arr.Any())
                            {
                                property.SetValue(settings, arr);
                            }
                        }

                        else
                        {
                            throw new Exception($"Cannot handle '{property.PropertyType.Name}' yet");
                        }
                    }
                    catch (Exception exception)
                    {
                        Logger.Log($"Failed to override '{property.Name}' setting", exception);
                    }
                }
            }

            // return

            return(settings);
        }
Example #4
0
        private static bool IsDotNetSdkStyle(CoverageProject project)
        {
            return(project.ProjectFileXElement
                   .DescendantsAndSelf()
                   .Where(x =>
            {
                //https://docs.microsoft.com/en-us/visualstudio/msbuild/how-to-use-project-sdk?view=vs-2019

                /*
                 * <Project Sdk="My.Custom.Sdk">
                 *      ...
                 * </Project>
                 * <Project Sdk="My.Custom.Sdk/1.2.3">
                 *      ...
                 * </Project>
                 */
                if
                (
                    x?.Name?.LocalName?.Equals("Project", StringComparison.OrdinalIgnoreCase) == true &&
                    x?.Parent == null
                )
                {
                    var sdkAttr = x?.Attributes()?.FirstOrDefault(attr => attr?.Name?.LocalName?.Equals("Sdk", StringComparison.OrdinalIgnoreCase) == true);

                    if (sdkAttr?.Value?.Trim()?.StartsWith("Microsoft.NET.Sdk", StringComparison.OrdinalIgnoreCase) == true)
                    {
                        return true;
                    }
                }

                /*
                 * <Project>
                 *      <Sdk Name="My.Custom.Sdk" Version="1.2.3" />
                 *      ...
                 * </Project>
                 */
                if
                (
                    x?.Name?.LocalName?.Equals("Sdk", StringComparison.OrdinalIgnoreCase) == true &&
                    x?.Parent?.Name?.LocalName?.Equals("Project", StringComparison.OrdinalIgnoreCase) == true &&
                    x?.Parent?.Parent == null
                )
                {
                    var nameAttr = x?.Attributes()?.FirstOrDefault(attr => attr?.Name?.LocalName?.Equals("Name", StringComparison.OrdinalIgnoreCase) == true);

                    if (nameAttr?.Value?.Trim()?.StartsWith("Microsoft.NET.Sdk", StringComparison.OrdinalIgnoreCase) == true)
                    {
                        return true;
                    }
                }

                /*
                 * <Project>
                 *      <PropertyGroup>
                 *              <MyProperty>Value</MyProperty>
                 *      </PropertyGroup>
                 *      <Import Project="Sdk.props" Sdk="My.Custom.Sdk" />
                 *              ...
                 *      <Import Project="Sdk.targets" Sdk="My.Custom.Sdk" />
                 * </Project>
                 */
                if
                (
                    x?.Name?.LocalName?.Equals("Import", StringComparison.OrdinalIgnoreCase) == true &&
                    x?.Parent?.Name?.LocalName?.Equals("Project", StringComparison.OrdinalIgnoreCase) == true &&
                    x?.Parent?.Parent == null
                )
                {
                    var sdkAttr = x?.Attributes()?.FirstOrDefault(attr => attr?.Name?.LocalName?.Equals("Sdk", StringComparison.OrdinalIgnoreCase) == true);

                    if (sdkAttr?.Value?.Trim()?.StartsWith("Microsoft.NET.Sdk", StringComparison.OrdinalIgnoreCase) == true)
                    {
                        return true;
                    }
                }

                return false;
            })
                   .Any());
        }
        public static bool RunOpenCover(CoverageProject project, bool throwError = false)
        {
            var title = $"OpenCover Run ({project.ProjectName})";

            var opencoverSettings = new List <string>();

            opencoverSettings.Add($@" -mergebyhash ");

            opencoverSettings.Add($@" -hideskipped:all ");

            {
                // -register:

                var registerValue = "path32";

                if (project.Is64Bit)
                {
                    registerValue = "path64";
                }

                opencoverSettings.Add($@" -register:{registerValue} ");
            }

            {
                // -target:

                opencoverSettings.Add($@" ""-target:{MsTestPlatformUtil.MsTestPlatformExePath}"" ");
            }

            {
                // -filter:

                var filters       = new List <string>();
                var defaultFilter = "+[*]*";

                foreach (var value in (project.Settings.Include ?? new string[0]).Where(x => !string.IsNullOrWhiteSpace(x)))
                {
                    filters.Add($@"+{value.Replace("\"", "\\\"").Trim(' ', '\'')}");
                }

                if (!filters.Any())
                {
                    filters.Add(defaultFilter);
                }

                foreach (var value in (project.Settings.Exclude ?? new string[0]).Where(x => !string.IsNullOrWhiteSpace(x)))
                {
                    filters.Add($@"-{value.Replace("\"", "\\\"").Trim(' ', '\'')}");
                }

                foreach (var referenceProjectWithExcludeAttribute in project.ReferencedProjects.Where(x => x.HasExcludeFromCodeCoverageAssemblyAttribute))
                {
                    filters.Add($@"-[{referenceProjectWithExcludeAttribute.AssemblyName}]*");
                }

                if (filters.Any(x => !x.Equals(defaultFilter)))
                {
                    opencoverSettings.Add($@" ""-filter:{string.Join(" ", filters.Distinct())}"" ");
                }
            }

            {
                // -excludebyfile:

                var excludes = new List <string>();

                foreach (var value in (project.Settings.ExcludeByFile ?? new string[0]).Where(x => !string.IsNullOrWhiteSpace(x)))
                {
                    excludes.Add(value.Replace("\"", "\\\"").Trim(' ', '\''));
                }

                if (excludes.Any())
                {
                    opencoverSettings.Add($@" ""-excludebyfile:{string.Join(";", excludes)}"" ");
                }
            }

            {
                // -excludebyattribute:

                var excludes = new List <string>()
                {
                    // coverlet knows these implicitly
                    "ExcludeFromCoverage",
                    "ExcludeFromCodeCoverage"
                };

                foreach (var value in (project.Settings.ExcludeByAttribute ?? new string[0]).Where(x => !string.IsNullOrWhiteSpace(x)))
                {
                    excludes.Add(value.Replace("\"", "\\\"").Trim(' ', '\''));
                }

                foreach (var exclude in excludes.ToArray())
                {
                    var excludeAlternateName = default(string);

                    if (exclude.EndsWith("Attribute", StringComparison.OrdinalIgnoreCase))
                    {
                        // remove 'Attribute' suffix
                        excludeAlternateName = exclude.Substring(0, exclude.IndexOf("Attribute", StringComparison.OrdinalIgnoreCase));
                    }
                    else
                    {
                        // add 'Attribute' suffix
                        excludeAlternateName = $"{exclude}Attribute";
                    }

                    excludes.Add(excludeAlternateName);
                }

                excludes = excludes.Distinct(StringComparer.OrdinalIgnoreCase).OrderBy(x => x).ToList();

                if (excludes.Any())
                {
                    opencoverSettings.Add($@" ""-excludebyattribute:(*.{string.Join(")|(*.", excludes)})"" ");
                }
            }

            if (!project.Settings.IncludeTestAssembly)
            {
                // deleting the pdb of the test assembly seems to work; this is a VERY VERY shameful hack :(

                var testDllPdbFile = Path.Combine(project.ProjectOutputFolder, Path.GetFileNameWithoutExtension(project.TestDllFile)) + ".pdb";
                File.Delete(testDllPdbFile);

                // filtering out the test-assembly blows up the entire process and nothing gets instrumented or analysed

                //var nameOnlyOfDll = Path.GetFileNameWithoutExtension(project.TestDllFileInWorkFolder);
                //filters.Add($@"-[{nameOnlyOfDll}]*");
            }

            var runSettings = !string.IsNullOrWhiteSpace(project.RunSettingsFile) ? $@"/Settings:\""{project.RunSettingsFile}\""" : default;

            opencoverSettings.Add($@" ""-targetargs:\""{project.TestDllFile}\"" {runSettings}"" ");

            opencoverSettings.Add($@" ""-output:{ project.CoverageOutputFile }"" ");

            Logger.Log($"{title} Arguments {Environment.NewLine}{string.Join($"{Environment.NewLine}", opencoverSettings)}");

            var result = ProcessUtil
                         .ExecuteAsync(new ExecuteRequest
            {
                FilePath         = OpenCoverExePath,
                Arguments        = string.Join(" ", opencoverSettings),
                WorkingDirectory = project.ProjectOutputFolder
            })
                         .GetAwaiter()
                         .GetResult();

            if (result.ExitCode != 0)
            {
                if (throwError)
                {
                    throw new Exception(result.Output);
                }

                Logger.Log($"{title} Error", result.Output);
                return(false);
            }

            Logger.Log(title, result.Output);
            return(true);
        }
        public static async Task <bool> RunCoverletAsync(CoverageProject project, bool throwError = false)
        {
            var title = $"Coverlet Run ({project.ProjectName})";

            var coverletSettings = new List <string>();

            coverletSettings.Add($@"""{project.TestDllFile}""");

            coverletSettings.Add($@"--format ""cobertura""");

            foreach (var value in (project.Settings.Exclude ?? new string[0]).Where(x => !string.IsNullOrWhiteSpace(x)))
            {
                coverletSettings.Add($@"--exclude ""{value.Replace("\"", "\\\"").Trim(' ', '\'')}""");
            }

            foreach (var referenceProjectWithExcludeAttribute in project.ReferencedProjects.Where(x => x.ExcludeFromCodeCoverage))
            {
                coverletSettings.Add($@"--exclude ""[{referenceProjectWithExcludeAttribute.AssemblyName}]*""");
            }

            foreach (var value in (project.Settings.Include ?? new string[0]).Where(x => !string.IsNullOrWhiteSpace(x)))
            {
                coverletSettings.Add($@"--include ""{value.Replace("\"", "\\\"").Trim(' ', '\'')}""");
            }

            foreach (var value in (project.Settings.ExcludeByFile ?? new string[0]).Where(x => !string.IsNullOrWhiteSpace(x)))
            {
                coverletSettings.Add($@"--exclude-by-file ""{value.Replace("\"", "\\\"").Trim(' ', '\'')}""");
            }

            foreach (var value in (project.Settings.ExcludeByAttribute ?? new string[0]).Where(x => !string.IsNullOrWhiteSpace(x)))
            {
                coverletSettings.Add($@"--exclude-by-attribute ""{value.Replace("\"", "\\\"").Trim(' ', '\'', '[', ']')}""");
            }

            if (project.Settings.IncludeTestAssembly)
            {
                coverletSettings.Add("--include-test-assembly");
            }

            coverletSettings.Add($@"--target ""dotnet""");

            coverletSettings.Add($@"--threshold-type line");

            coverletSettings.Add($@"--threshold-stat total");

            coverletSettings.Add($@"--threshold 0");

            coverletSettings.Add($@"--output ""{ project.CoverageOutputFile }""");

            var runSettings = !string.IsNullOrWhiteSpace(project.RunSettingsFile) ? $@"--settings """"{project.RunSettingsFile}""""" : default;

            coverletSettings.Add($@"--targetargs ""test  """"{project.TestDllFile}"""" --nologo --blame {runSettings} --results-directory """"{project.CoverageOutputFolder}"""" --diag """"{project.CoverageOutputFolder}/diagnostics.log""""  """);

            Logger.Log($"{title} Arguments {Environment.NewLine}{string.Join($"{Environment.NewLine}", coverletSettings)}");

            var result = await ProcessUtil
                         .ExecuteAsync(new ExecuteRequest
            {
                FilePath         = CoverletExePath,
                Arguments        = string.Join(" ", coverletSettings),
                WorkingDirectory = project.ProjectOutputFolder
            });


            if (result != null)
            {
                /*
                 * 0 - Success.
                 * 1 - If any test fails.
                 * 2 - Coverage percentage is below threshold.
                 * 3 - Test fails and also coverage percentage is below threshold.
                 */
                if (result.ExitCode > 3)
                {
                    if (throwError)
                    {
                        throw new Exception(result.Output);
                    }

                    Logger.Log($"{title} Error", result.Output);
                    return(false);
                }

                Logger.Log(title, result.Output);

                return(true);
            }
            return(false);
        }
        public static bool RunCoverlet(CoverageProject project, bool throwError = false)
        {
            var title = $"Coverlet Run ({project.ProjectName})";

            if (File.Exists(project.CoverToolOutputFile))
            {
                File.Delete(project.CoverToolOutputFile);
            }

            if (Directory.Exists(project.WorkOutputFolder))
            {
                Directory.Delete(project.WorkOutputFolder, true);
            }

            Directory.CreateDirectory(project.WorkOutputFolder);

            var coverletSettings = new List <string>();

            coverletSettings.Add($@"""{project.TestDllFileInWorkFolder}""");

            coverletSettings.Add($@"--format ""cobertura""");

            foreach (var value in (project.Settings.Exclude ?? new string[0]).Where(x => !string.IsNullOrWhiteSpace(x)))
            {
                coverletSettings.Add($@"--exclude ""{value.Replace("\"", "\\\"").Trim(' ', '\'')}""");
            }

            foreach (var value in (project.Settings.Include ?? new string[0]).Where(x => !string.IsNullOrWhiteSpace(x)))
            {
                coverletSettings.Add($@"--include ""{value.Replace("\"", "\\\"").Trim(' ', '\'')}""");
            }

            foreach (var value in (project.Settings.ExcludeByFile ?? new string[0]).Where(x => !string.IsNullOrWhiteSpace(x)))
            {
                coverletSettings.Add($@"--exclude-by-file ""{value.Replace("\"", "\\\"").Trim(' ', '\'')}""");
            }

            foreach (var value in (project.Settings.ExcludeByAttribute ?? new string[0]).Where(x => !string.IsNullOrWhiteSpace(x)))
            {
                coverletSettings.Add($@"--exclude-by-attribute ""{value.Replace("\"", "\\\"").Trim(' ', '\'', '[', ']')}""");
            }

            if (project.Settings.IncludeTestAssembly)
            {
                coverletSettings.Add("--include-test-assembly");
            }

            coverletSettings.Add($@"--target ""dotnet""");

            coverletSettings.Add($@"--threshold-type line");

            coverletSettings.Add($@"--threshold-stat total");

            coverletSettings.Add($@"--threshold 0");

            coverletSettings.Add($@"--output ""{ project.CoverToolOutputFile }""");

            coverletSettings.Add($@"--targetargs ""test  """"{project.TestDllFileInWorkFolder}"""" --nologo --blame --results-directory """"{project.WorkOutputFolder}"""" --diag """"{project.WorkOutputFolder}/diagnostics.log""""  """);

            Logger.Log($"{title} Arguments {Environment.NewLine}{string.Join($"{Environment.NewLine}", coverletSettings)}");

            var result = ProcessUtil
                         .ExecuteAsync(new ExecuteRequest
            {
                FilePath         = CoverletExePath,
                Arguments        = string.Join(" ", coverletSettings),
                WorkingDirectory = project.WorkFolder
            })
                         .GetAwaiter()
                         .GetResult();

            /*
             * 0 - Success.
             * 1 - If any test fails.
             * 2 - Coverage percentage is below threshold.
             * 3 - Test fails and also coverage percentage is below threshold.
             */
            if (result.ExitCode > 3)
            {
                if (throwError)
                {
                    throw new Exception(result.Output);
                }

                Logger.Log($"{title} Error", result.Output);
                return(false);
            }

            Logger.Log(title, result.Output);
            return(true);
        }
Example #8
0
        private static AppOptions GetSettings(CoverageProject project)
        {
            // get global settings

            var settings = AppOptions.Get();

            // override with test project settings

            XElement xproject;

            try
            {
                xproject = XElement.Parse(File.ReadAllText(project.ProjectFile));
            }
            catch (Exception ex)
            {
                Logger.Log("Failed to parse project file", ex);
                return(settings);
            }

            var xsettings = xproject.Descendants("PropertyGroup").FirstOrDefault(x =>
            {
                var label = x.Attribute("Label")?.Value?.Trim() ?? string.Empty;

                if (!Vsix.Code.Equals(label, StringComparison.OrdinalIgnoreCase))
                {
                    return(false);
                }

                return(true);
            });

            if (xsettings == null)
            {
                return(settings);
            }

            foreach (var property in settings.GetType().GetProperties())
            {
                try
                {
                    var xproperty = xsettings.Descendants().FirstOrDefault(x => x.Name.LocalName.Equals(property.Name, StringComparison.OrdinalIgnoreCase));

                    if (xproperty == null)
                    {
                        continue;
                    }

                    var strValue = xproperty.Value;

                    if (string.IsNullOrWhiteSpace(strValue))
                    {
                        continue;
                    }

                    var strValueArr = strValue.Split('\n', '\r').Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim()).ToArray();

                    if (!strValue.Any())
                    {
                        continue;
                    }

                    if (TypeMatch(property.PropertyType, typeof(string)))
                    {
                        property.SetValue(settings, strValueArr.FirstOrDefault());
                    }
                    else if (TypeMatch(property.PropertyType, typeof(string[])))
                    {
                        property.SetValue(settings, strValueArr);
                    }

                    else if (TypeMatch(property.PropertyType, typeof(bool), typeof(bool?)))
                    {
                        if (bool.TryParse(strValueArr.FirstOrDefault(), out bool value))
                        {
                            property.SetValue(settings, value);
                        }
                    }
                    else if (TypeMatch(property.PropertyType, typeof(bool[]), typeof(bool?[])))
                    {
                        var arr = strValueArr.Where(x => bool.TryParse(x, out var _)).Select(x => bool.Parse(x));
                        if (arr.Any())
                        {
                            property.SetValue(settings, arr);
                        }
                    }

                    else if (TypeMatch(property.PropertyType, typeof(int), typeof(int?)))
                    {
                        if (int.TryParse(strValueArr.FirstOrDefault(), out var value))
                        {
                            property.SetValue(settings, value);
                        }
                    }
                    else if (TypeMatch(property.PropertyType, typeof(int[]), typeof(int?[])))
                    {
                        var arr = strValueArr.Where(x => int.TryParse(x, out var _)).Select(x => int.Parse(x));
                        if (arr.Any())
                        {
                            property.SetValue(settings, arr);
                        }
                    }

                    else if (TypeMatch(property.PropertyType, typeof(short), typeof(short?)))
                    {
                        if (short.TryParse(strValueArr.FirstOrDefault(), out var vaue))
                        {
                            property.SetValue(settings, vaue);
                        }
                    }
                    else if (TypeMatch(property.PropertyType, typeof(short[]), typeof(short?[])))
                    {
                        var arr = strValueArr.Where(x => short.TryParse(x, out var _)).Select(x => short.Parse(x));
                        if (arr.Any())
                        {
                            property.SetValue(settings, arr);
                        }
                    }

                    else if (TypeMatch(property.PropertyType, typeof(long), typeof(long?)))
                    {
                        if (long.TryParse(strValueArr.FirstOrDefault(), out var value))
                        {
                            property.SetValue(settings, value);
                        }
                    }
                    else if (TypeMatch(property.PropertyType, typeof(long[]), typeof(long?[])))
                    {
                        var arr = strValueArr.Where(x => long.TryParse(x, out var _)).Select(x => long.Parse(x));
                        if (arr.Any())
                        {
                            property.SetValue(settings, arr);
                        }
                    }

                    else if (TypeMatch(property.PropertyType, typeof(decimal), typeof(decimal?)))
                    {
                        if (decimal.TryParse(strValueArr.FirstOrDefault(), out var value))
                        {
                            property.SetValue(settings, value);
                        }
                    }
                    else if (TypeMatch(property.PropertyType, typeof(decimal[]), typeof(decimal?[])))
                    {
                        var arr = strValueArr.Where(x => decimal.TryParse(x, out var _)).Select(x => decimal.Parse(x));
                        if (arr.Any())
                        {
                            property.SetValue(settings, arr);
                        }
                    }

                    else if (TypeMatch(property.PropertyType, typeof(double), typeof(double?)))
                    {
                        if (double.TryParse(strValueArr.FirstOrDefault(), out var value))
                        {
                            property.SetValue(settings, value);
                        }
                    }
                    else if (TypeMatch(property.PropertyType, typeof(double[]), typeof(double?[])))
                    {
                        var arr = strValueArr.Where(x => double.TryParse(x, out var _)).Select(x => double.Parse(x));
                        if (arr.Any())
                        {
                            property.SetValue(settings, arr);
                        }
                    }

                    else if (TypeMatch(property.PropertyType, typeof(float), typeof(float?)))
                    {
                        if (float.TryParse(strValueArr.FirstOrDefault(), out var value))
                        {
                            property.SetValue(settings, value);
                        }
                    }
                    else if (TypeMatch(property.PropertyType, typeof(float[]), typeof(float?[])))
                    {
                        var arr = strValueArr.Where(x => float.TryParse(x, out var _)).Select(x => float.Parse(x));
                        if (arr.Any())
                        {
                            property.SetValue(settings, arr);
                        }
                    }

                    else if (TypeMatch(property.PropertyType, typeof(char), typeof(char?)))
                    {
                        if (char.TryParse(strValueArr.FirstOrDefault(), out var value))
                        {
                            property.SetValue(settings, value);
                        }
                    }
                    else if (TypeMatch(property.PropertyType, typeof(char[]), typeof(char?[])))
                    {
                        var arr = strValueArr.Where(x => char.TryParse(x, out var _)).Select(x => char.Parse(x));
                        if (arr.Any())
                        {
                            property.SetValue(settings, arr);
                        }
                    }

                    else
                    {
                        throw new Exception($"Cannot handle '{property.PropertyType.Name}' yet");
                    }
                }
                catch (Exception exception)
                {
                    Logger.Log($"Failed to override '{property.Name}' setting", exception);
                }
            }

            // return

            return(settings);
        }