private void PerformDepthFirstPass()

in src/Build/Evaluation/Evaluator.cs [948:1196]


        private void PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
        {
            // We accumulate InitialTargets from the project and each import
            IList<string> initialTargets = _expander.ExpandIntoStringListLeaveEscaped(currentProjectOrImport.InitialTargets, ExpanderOptions.ExpandProperties, currentProjectOrImport.InitialTargetsLocation);
            _initialTargetsList.AddRange(initialTargets);

            if (!s_ignoreTreatAsLocalProperty)
            {
                IList<string> globalPropertiesToTreatAsLocals = _expander.ExpandIntoStringListLeaveEscaped(currentProjectOrImport.TreatAsLocalProperty, ExpanderOptions.ExpandProperties, currentProjectOrImport.TreatAsLocalPropertyLocation);

                foreach (string propertyName in globalPropertiesToTreatAsLocals)
                {
                    XmlUtilities.VerifyThrowProjectValidElementName(propertyName, currentProjectOrImport.Location);
                    _data.GlobalPropertiesToTreatAsLocal.Add(propertyName);
                }
            }

            UpdateDefaultTargets(currentProjectOrImport);

#if FEATURE_MSBUILD_DEBUGGER
            if (DebuggerManager.DebuggingEnabled)
            {
                // Create a state for every element processed during the properties pass
                foreach (ProjectElement element in currentProjectOrImport.AllChildren)
                {
                    if (
                        element is ProjectPropertyGroupElement ||
                        element is ProjectPropertyElement ||
                        element is ProjectImportGroupElement ||
                        element is ProjectImportElement ||
                        element is ProjectChooseElement ||
                        element is ProjectWhenElement || // although Whens are encountered again during the item pass, the condition is only evaluated on the first pass, hence, property locals only
                        element is ProjectOtherwiseElement
                        )
                    {
                        // Skip any that are somewhere below targets; those will be defined later
                        if (!(element is ProjectTargetElement) &&
                            element.AllParents.FirstOrDefault(delegate (ProjectElementContainer current) { return (current != null && current is ProjectTargetElement); }) == null)
                        {
                            DebuggerManager.DefineState(element.Location, element.Location.LocationString, s_propertyPassLocalsTypes);
                        }
                    }
                }

                // Bake the property pass states so we can enter them
                DebuggerManager.BakeStates(Path.GetFileNameWithoutExtension(currentProjectOrImport.FullPath));
            }
#endif
            IList<ProjectImportElement> implicitImports = new List<ProjectImportElement>();

            if (!String.IsNullOrWhiteSpace(currentProjectOrImport.Sdk))
            {
                // SDK imports are added implicitly where they are evaluated at the top and bottom as if they are in the XML
                //
                foreach (string sdk in currentProjectOrImport.Sdk.Split(';').Select(i => i.Trim()))
                {
                    if (String.IsNullOrWhiteSpace(sdk))
                    {
                        ProjectErrorUtilities.ThrowInvalidProject(currentProjectOrImport.SdkLocation, "InvalidSdkFormat", currentProjectOrImport.Sdk);
                    }

                    int slashIndex = sdk.LastIndexOf("/", StringComparison.Ordinal);
                    string sdkName = slashIndex > 0 ? sdk.Substring(0, slashIndex) : sdk;

                    // TODO: do something other than just ignore the version

                    if (sdkName.Contains("/"))
                    {
                        ProjectErrorUtilities.ThrowInvalidProject(currentProjectOrImport.SdkLocation, "InvalidSdkFormat", currentProjectOrImport.Sdk);
                    }

                    implicitImports.Add(ProjectImportElement.CreateImplicit("Sdk.props", currentProjectOrImport, ImplicitImportLocation.Top, sdkName));

                    implicitImports.Add(ProjectImportElement.CreateImplicit("Sdk.targets", currentProjectOrImport, ImplicitImportLocation.Bottom, sdkName));
                }
            }

            foreach (var import in implicitImports.Where(i => i.ImplicitImportLocation == ImplicitImportLocation.Top))
            {
                EvaluateImportElement(currentProjectOrImport.DirectoryPath, import);
            }

            foreach (ProjectElement element in currentProjectOrImport.Children)
            {
                ProjectPropertyGroupElement propertyGroup = element as ProjectPropertyGroupElement;

                if (propertyGroup != null)
                {
                    EvaluatePropertyGroupElement(propertyGroup);
                    continue;
                }

                ProjectItemGroupElement itemGroup = element as ProjectItemGroupElement;

                if (itemGroup != null)
                {
                    _itemGroupElements.Add(itemGroup);

#if FEATURE_MSBUILD_DEBUGGER
                    if (DebuggerManager.DebuggingEnabled)
                    {
                        DebuggerManager.DefineState(element.Location, element.Location.LocationString, s_itemPassLocalsTypes);

                        foreach (ProjectItemElement item in itemGroup.Items)
                        {
                            DebuggerManager.DefineState(item.Location, item.Location.LocationString, s_itemPassLocalsTypes);

                            foreach (ProjectMetadataElement metadatum in item.Metadata)
                            {
                                DebuggerManager.DefineState(metadatum.Location, metadatum.Location.LocationString, s_itemPassLocalsTypes);
                            }
                        }
                    }
#endif

                    continue;
                }

                ProjectItemDefinitionGroupElement itemDefinitionGroup = element as ProjectItemDefinitionGroupElement;

                if (itemDefinitionGroup != null)
                {
                    _itemDefinitionGroupElements.Add(itemDefinitionGroup);

#if FEATURE_MSBUILD_DEBUGGER
                    if (DebuggerManager.DebuggingEnabled)
                    {
                        DebuggerManager.DefineState(element.Location, element.Location.LocationString, s_itemDefinitionPassLocalsTypes);

                        foreach (ProjectItemDefinitionElement itemDefinition in itemDefinitionGroup.ItemDefinitions)
                        {
                            DebuggerManager.DefineState(itemDefinition.Location, itemDefinition.Location.LocationString, s_itemDefinitionPassLocalsTypes);

                            foreach (ProjectMetadataElement metadatum in itemDefinition.Metadata)
                            {
                                DebuggerManager.DefineState(metadatum.Location, metadatum.Location.LocationString, s_itemDefinitionPassLocalsTypes);
                            }
                        }
                    }
#endif

                    continue;
                }

                ProjectTargetElement target = element as ProjectTargetElement;

                if (target != null)
                {
#if FEATURE_MSBUILD_DEBUGGER
                    if (DebuggerManager.DebuggingEnabled)
                    {
                        DebuggerManager.DefineState(element.Location, element.Location.LocationString, s_itemPassLocalsTypes);

                        foreach (ProjectElement child in (target.AllChildren))
                        {
                            DebuggerManager.DefineState(child.Location, child.Location.LocationString, s_itemPassLocalsTypes);
                        }
                    }
#endif

                    if (_projectSupportsReturnsAttribute.ContainsKey(currentProjectOrImport))
                    {
                        _projectSupportsReturnsAttribute[currentProjectOrImport] |= (target.Returns != null);
                    }
                    else
                    {
                        _projectSupportsReturnsAttribute[currentProjectOrImport] = (target.Returns != null);
                    }

                    _targetElements.Add(target);

                    continue;
                }

                ProjectImportElement import = element as ProjectImportElement;
                if (import != null)
                {
                    EvaluateImportElement(currentProjectOrImport.DirectoryPath, import);
                    continue;
                }

                ProjectImportGroupElement importGroup = element as ProjectImportGroupElement;

                if (importGroup != null)
                {
                    EvaluateImportGroupElement(currentProjectOrImport.DirectoryPath, importGroup);
                    continue;
                }

                ProjectUsingTaskElement usingTask = element as ProjectUsingTaskElement;

                if (usingTask != null)
                {
#if FEATURE_MSBUILD_DEBUGGER
                    if (DebuggerManager.DebuggingEnabled)
                    {
                        DebuggerManager.DefineState(element.Location, element.Location.LocationString, s_itemPassLocalsTypes);
                    }
#endif

                    _usingTaskElements.Add(new Pair<string, ProjectUsingTaskElement>(currentProjectOrImport.DirectoryPath, usingTask));
                    continue;
                }

                ProjectChooseElement choose = element as ProjectChooseElement;

                if (choose != null)
                {
#if FEATURE_MSBUILD_DEBUGGER
                    if (DebuggerManager.DebuggingEnabled)
                    {
                        // Already defined states for all choose children that were relevant to the
                        // property pass; now the ones relevant to the item pass, which get the item pass locals
                        foreach (ProjectElement child in choose.AllChildren)
                        {
                            if (child is ProjectItemGroupElement ||
                                child is ProjectItemElement ||
                                child is ProjectMetadataElement)
                            {
                                DebuggerManager.DefineState(child.Location, child.Location.LocationString, s_itemPassLocalsTypes);
                            }
                        }
                    }
#endif

                    EvaluateChooseElement(choose);
                    continue;
                }

                if (element is ProjectExtensionsElement)
                {
                    continue;
                }

                ErrorUtilities.ThrowInternalError("Unexpected child type");
            }

            foreach (var import in implicitImports.Where(i => i.ImplicitImportLocation == ImplicitImportLocation.Bottom))
            {
                EvaluateImportElement(currentProjectOrImport.DirectoryPath, import);
            }

#if FEATURE_MSBUILD_DEBUGGER
            if (DebuggerManager.DebuggingEnabled)
            {
                DebuggerManager.BakeStates(Path.GetFileNameWithoutExtension(currentProjectOrImport.FullPath));
            }
#endif
        }