/// <inheritdoc />
        public void PredictInputsAndOutputs(
            ProjectInstance projectInstance,
            ProjectPredictionReporter predictionReporter)
        {
            // Determine the active Targets in this Project.
            var activeTargets = new Dictionary <string, ProjectTargetInstance>(StringComparer.OrdinalIgnoreCase);

            // Start with the default targets, initial targets and all of their parent targets, the closure of its dependencies.
            foreach (string target in projectInstance.DefaultTargets)
            {
                projectInstance.AddToActiveTargets(target, activeTargets);
            }

            foreach (string target in projectInstance.InitialTargets)
            {
                projectInstance.AddToActiveTargets(target, activeTargets);
            }

            // Aside from InitialTargets and DefaultTargets, for completeness of inputs/outputs detection,
            // include custom targets defined directly in this Project.
            // Note that this misses targets defined in any custom targets files.
            foreach (ProjectTargetInstance target in projectInstance.Targets.Values
                     .Where(t => string.Equals(t.Location.File, projectInstance.ProjectFileLocation.File, PathComparer.Comparison)))
            {
                projectInstance.AddToActiveTargets(target.Name, activeTargets);
            }

            projectInstance.AddBeforeAndAfterTargets(activeTargets);

            // Then parse copy tasks for these targets.
            foreach (KeyValuePair <string, ProjectTargetInstance> target in activeTargets)
            {
                ParseCopyTask(target.Value, projectInstance, predictionReporter);
            }
        }
示例#2
0
        /// <summary>
        /// Expand (recursively) set of active targets to include targets which reference any
        /// of the active targets with BeforeTarget or AfterTarget.
        /// </summary>
        /// <param name="projectInstance">An MSBuild Project instance to use for context.</param>
        /// <param name="activeTargets">
        /// Set of active targets. Will be modified in place to add targets that reference this
        /// graph with BeforeTarget or AfterTarget.
        /// </param>
        public static void AddBeforeAndAfterTargets(this ProjectInstance projectInstance, Dictionary <string, ProjectTargetInstance> activeTargets)
        {
            var newTargetsToConsider = true;

            while (newTargetsToConsider)
            {
                newTargetsToConsider = false;

                foreach (KeyValuePair <string, ProjectTargetInstance> pair in projectInstance.Targets)
                {
                    string targetName = pair.Key;
                    ProjectTargetInstance targetInstance = pair.Value;

                    // If the target is not already in our list of active targets ...
                    if (!activeTargets.ContainsKey(targetName))
                    {
                        IEnumerable <string> hookedTargets = projectInstance.EvaluateValue(targetInstance.AfterTargets)
                                                             .Concat(projectInstance.EvaluateValue(targetInstance.BeforeTargets));
                        foreach (string hookedTarget in hookedTargets)
                        {
                            // ... and it hooks a running target with BeforeTargets/AfterTargets ...
                            if (activeTargets.ContainsKey(hookedTarget))
                            {
                                // ... then add it to the list of running targets ...
                                projectInstance.AddToActiveTargets(targetName, activeTargets);

                                // ... and make a note to run again, since activeTargets has changed.
                                newTargetsToConsider = true;
                            }
                        }
                    }
                }
            }
        }