/// <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); } }
/// <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; } } } } } }