/// <summary>
        /// Handles a generic BuildMessage event and assigns it to the appropriate logging node.
        /// </summary>
        /// <param name="args">The <see cref="BuildMessageEventArgs"/> instance containing the event data.</param>
        public void AddMessage(LazyFormattedBuildEventArgs args, string message)
        {
            TreeNode parent       = null;
            BaseNode nodeToAdd    = null;
            bool     lowRelevance = false;

            var buildEventContext = args.BuildEventContext;

            if (buildEventContext.TaskId > 0)
            {
                parent = GetTask(args);
                if (parent is Task task)
                {
                    if (task is ResolveAssemblyReferenceTask rar)
                    {
                        if (ProcessRAR(rar, ref parent, message))
                        {
                            return;
                        }
                    }
                    else if (string.Equals(task.Name, "MSBuild", StringComparison.OrdinalIgnoreCase))
                    {
                        if (ProcessMSBuildTask(task, ref parent, ref nodeToAdd, message))
                        {
                            return;
                        }
                    }
                    else if (string.Equals(task.Name, "RestoreTask", StringComparison.OrdinalIgnoreCase))
                    {
                        if (ProcessRestoreTask(task, ref parent, message))
                        {
                            return;
                        }
                    }
                    else if (string.Equals(task.Name, "Mmp", StringComparison.OrdinalIgnoreCase))
                    {
                        if (ProcessMmp(task, ref parent, message))
                        {
                            return;
                        }
                    }
                }
            }
            else if (buildEventContext.TargetId > 0)
            {
                parent = GetTarget(args);

                if (Strings.TaskSkippedFalseConditionRegex.IsMatch(message))
                {
                    lowRelevance = true;
                }
            }
            else if (buildEventContext.ProjectContextId > 0)
            {
                var project = construction.GetOrAddProject(buildEventContext.ProjectContextId);
                parent = project;

                if (message.Equals("Building with tools version \"Current\".", StringComparison.Ordinal))
                {
                    // this is useless so just drop it on the floor
                    return;
                }

                var targetSkipReason = Strings.GetTargetSkipReason(message);
                if (targetSkipReason != TargetSkipReason.None)
                {
                    // Target skipped was a simple message before this PR:
                    // https://github.com/dotnet/msbuild/pull/6402
                    var targetName = Intern(TextUtilities.ParseQuotedSubstring(message));
                    if (targetName != null)
                    {
                        var args2 = new TargetSkippedEventArgs2(message);
                        args2.TargetName          = targetName;
                        args2.BuildEventContext   = args.BuildEventContext;
                        args2.SkipReason          = targetSkipReason;
                        args2.OriginallySucceeded = targetSkipReason != TargetSkipReason.PreviouslyBuiltUnsuccessfully;
                        typeof(BuildEventArgs)
                        .GetField("timestamp", BindingFlags.Instance | BindingFlags.NonPublic)
                        .SetValue(args2, args.Timestamp);
                        construction.TargetSkipped(args2);
                        return;
                    }
                }
            }
            else if (buildEventContext.EvaluationId != -1)
            {
                parent = construction.EvaluationFolder;

                var evaluationId = buildEventContext.EvaluationId;
                var evaluation   = construction.Build.FindEvaluation(evaluationId);
                if (evaluation != null)
                {
                    parent = evaluation;
                }

                if (args is PropertyReassignmentEventArgs || Strings.PropertyReassignmentRegex.IsMatch(message))
                {
                    TimedNode properties;
                    if (evaluation != null)
                    {
                        properties = evaluation.PropertyReassignmentFolder;
                    }
                    else
                    {
                        properties = parent.GetOrCreateNodeWithName <TimedNode>(Strings.PropertyReassignmentFolder, addAtBeginning: true);
                    }

                    var propertyName = Strings.GetPropertyName(message);
                    parent = properties.GetOrCreateNodeWithName <Folder>(propertyName);
                }
                else if (parent == evaluation && parent.FindChild <Message>(message) != null)
                {
                    // avoid duplicate messages
                    return;
                }
            }

            if (parent == null)
            {
                parent = construction.Build;

                if (construction.Build.FileFormatVersion < 9 && Strings.IsEvaluationMessage(message))
                {
                    if (!evaluationMessagesAlreadySeen.Add(message))
                    {
                        return;
                    }

                    parent = construction.EvaluationFolder;
                }
                else if (construction.Build.FileFormatVersion < 9 && Strings.PropertyReassignmentRegex.IsMatch(message))
                {
                    if (!evaluationMessagesAlreadySeen.Add(message))
                    {
                        return;
                    }

                    var properties = construction.EvaluationFolder.GetOrCreateNodeWithName <Folder>(Strings.PropertyReassignmentFolder);
                    parent = properties.GetOrCreateNodeWithName <Folder>(Strings.GetPropertyName(message));
                }
                else if (Strings.IsTargetDoesNotExistAndWillBeSkipped(message))
                {
                    var folder = construction.EvaluationFolder;
                    parent       = folder;
                    lowRelevance = true;
                }
                else if (
                    buildEventContext.NodeId == 0 &&
                    buildEventContext.ProjectContextId == 0 &&
                    buildEventContext.ProjectInstanceId == 0 &&
                    buildEventContext.TargetId == 0 &&
                    buildEventContext.TaskId == 0)
                {
                    // must be Detailed Build Summary
                    // https://github.com/Microsoft/msbuild/blob/master/src/XMakeBuildEngine/BackEnd/Components/Scheduler/Scheduler.cs#L509
                    DetailedSummary.AppendLine(message);
                    return;
                }
                else if (
                    buildEventContext.NodeId == -2 &&
                    buildEventContext.ProjectContextId == -2 &&
                    buildEventContext.ProjectInstanceId == -1)
                {
                    if (message.StartsWith(Strings.MSBuildVersionPrefix))
                    {
                        var version = message.Substring(Strings.MSBuildVersionPrefix.Length);
                        construction.Build.MSBuildVersion = version;
                    }
                }
            }

            if (nodeToAdd == null)
            {
                message   = Intern(message);
                nodeToAdd = new Message
                {
                    Text           = message,
                    Timestamp      = args.Timestamp,
                    IsLowRelevance = lowRelevance
                };
            }

            parent.AddChild(nodeToAdd);
        }
        public void TargetSkipped(TargetSkippedEventArgs2 args)
        {
            string targetName  = Intern(args.TargetName);
            string messageText = args.Message;

            var originalBuildEventContext = args.OriginalBuildEventContext;
            var skipReason = args.SkipReason;

            if ((skipReason == TargetSkipReason.PreviouslyBuiltSuccessfully ||
                 skipReason == TargetSkipReason.PreviouslyBuiltUnsuccessfully) && originalBuildEventContext != null)
            {
                var prefix = "Target \"" + targetName + "\" "; // trim the Target Name text since the node will already display that
                if (messageText.StartsWith(prefix, StringComparison.Ordinal))
                {
                    messageText = messageText.Substring(prefix.Length);
                }
            }

            messageText = Intern(messageText);

            var target = AddTargetCore(
                args,
                targetName,
                Intern(args.ParentTarget),
                Intern(args.TargetFile),
                args.BuildReason);

            if (originalBuildEventContext != null && originalBuildEventContext.ProjectContextId != BuildEventContext.InvalidProjectContextId)
            {
                var originalProject = GetProject(originalBuildEventContext.ProjectContextId);
                if (originalProject != null)
                {
                    target.ParentTarget = messageText;
                    if (originalBuildEventContext.TargetId != -1 &&
                        originalProject.GetTargetById(originalBuildEventContext.TargetId) is Target originalTarget)
                    {
                        target.OriginalNode = originalTarget;
                    }
                    else
                    {
                        // the original target was skipped because of false condition, so its target id == -1
                        // Need to look it up by name, if unambiguous
                        var candidates = originalProject
                                         .Children
                                         .OfType <Target>()
                                         .Where(t => t.Name == targetName)
                                         .ToArray();
                        if (candidates.Length == 1)
                        {
                            originalTarget = candidates[0];
                        }
                        else
                        {
                            originalTarget = null;
                        }

                        target.OriginalNode = (TimedNode)originalTarget ?? originalProject;
                    }
                }
            }
            else
            {
                var messageNode = new Message {
                    Text = messageText
                };
                target.AddChild(messageNode);
            }
        }
Example #3
0
        private void TargetSkipped(TargetSkippedEventArgs2 args)
        {
            var project = GetProject(args.BuildEventContext.ProjectContextId);

            string targetName  = Intern(args.TargetName);
            string targetFile  = Intern(args.TargetFile);
            string messageText = args.Message;

            var    skipReason = args.SkipReason;
            Target target;

            if (skipReason == TargetSkipReason.ConditionWasFalse ||
                skipReason == TargetSkipReason.OutputsUpToDate ||
                skipReason == TargetSkipReason.None // file format version < 14
                )
            {
                messageText = Intern(messageText);
                target      = AddTargetCore(
                    args,
                    targetName,
                    Intern(args.ParentTarget),
                    targetFile,
                    args.BuildReason);
                var messageNode = new Message {
                    Text = messageText
                };
                if (target != null)
                {
                    target.AddChild(messageNode);
                }
                else
                {
                    project.AddChild(messageNode);
                }

                return;
            }

            var prefix = "Target \"" + targetName + "\" "; // trim the Target Name text since the node will already display that

            if (messageText.StartsWith(prefix, StringComparison.Ordinal))
            {
                messageText = messageText.Substring(prefix.Length);
            }

            messageText = Intern(messageText);

            target = new Target()
            {
                Name      = targetName,
                Id        = -1,
                StartTime = args.Timestamp,
                EndTime   = args.Timestamp
            };

            target.NodeId         = args.BuildEventContext.NodeId;
            target.SourceFilePath = targetFile;

            project.TryAddTarget(target);

            if (args.OriginalBuildEventContext is { } buildEventContext&& buildEventContext.ProjectContextId != BuildEventContext.InvalidProjectContextId)
            {
                var originalProject = GetProject(buildEventContext.ProjectContextId);
                if (originalProject != null)
                {
                    target.ParentTarget = messageText;
                    var originalTarget = originalProject.GetTargetById(buildEventContext.TargetId);
                    if (originalTarget != null)
                    {
                        target.OriginalNode = originalTarget;
                    }
                    else
                    {
                        target.OriginalNode = originalProject;
                    }
                }
            }
        }