<commit_before>﻿using System;
using System.Linq;

namespace Microsoft.Build.Logging.StructuredLogger
{
    public class ImportTreeAnalyzer
    {
        public static void Analyze(Folder evaluation, StringCache stringTable)
        {
            evaluation.VisitAllChildren<Message>(m => VisitMessage(m, stringTable), takeChildrenSnapshot: true);
        }

        private static void VisitMessage(Message message, StringCache stringTable)
        {
            var match = Strings.ImportingProjectRegex.Match(message.Text);
            if (match.Success && match.Groups.Count == 5)
            {
                var project = match.Groups["File"].Value;
                var importedProject = match.Groups["ImportedProject"].Value;
                var line = int.Parse(match.Groups["Line"].Value);
                var column = int.Parse(match.Groups["Column"].Value);

                project = stringTable.Intern(project);
                importedProject = stringTable.Intern(importedProject);

                AddImport(
                    message,
                    project,
                    importedProject,
                    line,
                    column,
                    imported: true);
                return;
            }

            match = Strings.ProjectWasNotImportedRegex.Match(message.Text);
            if (match.Success && match.Groups.Count == 6)
            {
                var project = match.Groups["File"].Value;
                var importedProject = match.Groups["ImportedProject"].Value;
                var line = int.Parse(match.Groups["Line"].Value);
                var column = int.Parse(match.Groups["Column"].Value);
                var reason = match.Groups["Reason"].Value;

                project = stringTable.Intern(project);
                importedProject = stringTable.Intern(importedProject);
                reason = stringTable.Intern("Not imported due to " + reason);

                AddImport(
                    message,
                    project,
                    importedProject,
                    line,
                    column,
                    imported: false,
                    reason: reason);
                return;
            }
        }

        private static void AddImport(
            Message message,
            string project,
            string importedProject,
            int line,
            int column,
            bool imported,
            string reason = null)
        {
            var rootProjectNode = (Project)message.Parent as Project;
            if (rootProjectNode.Children.First() is Folder importsFolder && importsFolder.Name == Strings.Imports)
            {
            }
            else
            {
                importsFolder = new Folder()
                {
                    Name = Strings.Imports
                };
                rootProjectNode.AddChildAtBeginning(importsFolder);
            }

            TextNode import;
            if (imported)
            {
                import = new Import(project, importedProject, line, column);
            }
            else
            {
                import = new NoImport(project, importedProject, line, column, reason);
            }
            
            NamedNode parent = importsFolder;

            if (project != rootProjectNode.ProjectFile)
            {
                parent = rootProjectNode.FindFirstDescendant<Import>(i => string.Equals(i.ImportedProjectFilePath, project, StringComparison.OrdinalIgnoreCase));
                if (parent == null)
                {
                    parent = new Import(rootProjectNode.Name, project, 0, 0);
                    importsFolder.AddChild(parent);
                }
            }

            parent.AddChild(import);

            message.Parent.Children.Remove(message);
        }
    }
}
<commit_msg>Fix an invalid cast when reading localized logs.<commit_after>﻿using System;
using System.Linq;

namespace Microsoft.Build.Logging.StructuredLogger
{
    public class ImportTreeAnalyzer
    {
        public static void Analyze(Folder evaluation, StringCache stringTable)
        {
            evaluation.VisitAllChildren<Message>(m => VisitMessage(m, stringTable), takeChildrenSnapshot: true);
        }

        private static void VisitMessage(Message message, StringCache stringTable)
        {
            var match = Strings.ImportingProjectRegex.Match(message.Text);
            if (match.Success && match.Groups.Count == 5)
            {
                var project = match.Groups["File"].Value;
                var importedProject = match.Groups["ImportedProject"].Value;
                var line = int.Parse(match.Groups["Line"].Value);
                var column = int.Parse(match.Groups["Column"].Value);

                project = stringTable.Intern(project);
                importedProject = stringTable.Intern(importedProject);

                AddImport(
                    message,
                    project,
                    importedProject,
                    line,
                    column,
                    imported: true);
                return;
            }

            match = Strings.ProjectWasNotImportedRegex.Match(message.Text);
            if (match.Success && match.Groups.Count == 6)
            {
                var project = match.Groups["File"].Value;
                var importedProject = match.Groups["ImportedProject"].Value;
                var line = int.Parse(match.Groups["Line"].Value);
                var column = int.Parse(match.Groups["Column"].Value);
                var reason = match.Groups["Reason"].Value;

                project = stringTable.Intern(project);
                importedProject = stringTable.Intern(importedProject);
                reason = stringTable.Intern("Not imported due to " + reason);

                AddImport(
                    message,
                    project,
                    importedProject,
                    line,
                    column,
                    imported: false,
                    reason: reason);
                return;
            }
        }

        private static void AddImport(
            Message message,
            string project,
            string importedProject,
            int line,
            int column,
            bool imported,
            string reason = null)
        {
            var rootProjectNode = message.Parent as Project;
            if (rootProjectNode == null)
            {
                // possible with localized logs
                return;
            }

            if (rootProjectNode.Children.First() is Folder importsFolder && importsFolder.Name == Strings.Imports)
            {
            }
            else
            {
                importsFolder = new Folder()
                {
                    Name = Strings.Imports
                };
                rootProjectNode.AddChildAtBeginning(importsFolder);
            }

            TextNode import;
            if (imported)
            {
                import = new Import(project, importedProject, line, column);
            }
            else
            {
                import = new NoImport(project, importedProject, line, column, reason);
            }
            
            NamedNode parent = importsFolder;

            if (project != rootProjectNode.ProjectFile)
            {
                parent = rootProjectNode.FindFirstDescendant<Import>(i => string.Equals(i.ImportedProjectFilePath, project, StringComparison.OrdinalIgnoreCase));
                if (parent == null)
                {
                    parent = new Import(rootProjectNode.Name, project, 0, 0);
                    importsFolder.AddChild(parent);
                }
            }

            parent.AddChild(import);

            message.Parent.Children.Remove(message);
        }
    }
}

{'fraction_non_alphanumeric': 0.08144126357354393, 'fraction_numerical': 0.0009871668311944718, 'mean_word_length': 1.281813063063063, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, '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': '5710809', 'n_tokens_mistral': 1867, 'n_tokens_neox': 1726, 'n_words': 377}