private IDictionary Evaluate()

in src/Build/Evaluation/Evaluator.cs [724:941]


        private IDictionary<string, object> Evaluate()
        {
#if FEATURE_MSBUILD_DEBUGGER
            InitializeForDebugging();
#endif

            // Pass0: load initial properties
            // Follow the order of precedence so that Global properties overwrite Environment properties
            ICollection<P> builtInProperties = AddBuiltInProperties();
            ICollection<P> environmentProperties = AddEnvironmentProperties();
            ICollection<P> toolsetProperties = AddToolsetProperties();
            ICollection<P> subToolsetProperties = AddSubToolsetProperties();
            ICollection<P> globalProperties = AddGlobalProperties();

#if FEATURE_MSBUILD_DEBUGGER
            // Create a state for the root project node to show initial properties
            if (DebuggerManager.DebuggingEnabled)
            {
                _initialLocals = new Dictionary<string, object>();
                _initialLocals.Add(new KeyValuePair<string, object>(s_initialLocalsTypes[(int)LocalsTypes.Project].Name, _projectInstanceIfAnyForDebuggerOnly));
                _initialLocals.Add(new KeyValuePair<string, object>(s_initialLocalsTypes[(int)LocalsTypes.BuiltIn].Name, builtInProperties));
                _initialLocals.Add(new KeyValuePair<string, object>(s_initialLocalsTypes[(int)LocalsTypes.Environment].Name, environmentProperties));
                _initialLocals.Add(new KeyValuePair<string, object>(s_initialLocalsTypes[(int)LocalsTypes.Toolset].Name, toolsetProperties));
                _initialLocals.Add(new KeyValuePair<string, object>(s_initialLocalsTypes[(int)LocalsTypes.SubToolset].Name, subToolsetProperties));
                _initialLocals.Add(new KeyValuePair<string, object>(s_initialLocalsTypes[(int)LocalsTypes.Global].Name, globalProperties));

                DebuggerManager.DefineState(_projectRootElement.Location, _projectRootElement.ElementName, s_initialLocalsTypes);

                DebuggerManager.BakeStates(Path.GetFileNameWithoutExtension(_projectRootElement.FullPath));

                DebuggerManager.PulseState(_projectRootElement.Location, _initialLocals);

                _propertyPassLocals = new Dictionary<string, object>(_initialLocals);
                _propertyPassLocals.Add(new KeyValuePair<string, object>(s_propertyPassLocalsTypes[(int)LocalsTypes.EvaluateExpression].Name, (ExpandExpression)_data.ExpandString));
                _propertyPassLocals.Add(new KeyValuePair<string, object>(s_propertyPassLocalsTypes[(int)LocalsTypes.EvaluateCondition].Name, (EvaluateConditionalExpression)_data.EvaluateCondition));
                _propertyPassLocals.Add(new KeyValuePair<string, object>(s_propertyPassLocalsTypes[(int)LocalsTypes.ToolsVersion].Name, _data.Toolset.ToolsVersion));
                _propertyPassLocals.Add(new KeyValuePair<string, object>(s_propertyPassLocalsTypes[(int)LocalsTypes.Properties].Name, _data.Properties));

                _itemDefinitionPassLocals = new Dictionary<string, object>(_propertyPassLocals);
                _itemDefinitionPassLocals.Add(new KeyValuePair<string, object>(s_itemDefinitionPassLocalsTypes[(int)LocalsTypes.ItemDefinitions].Name, _data.ItemDefinitionsEnumerable));

                _itemPassLocals = new Dictionary<string, object>(_itemDefinitionPassLocals);
                _itemPassLocals.Add(new KeyValuePair<string, object>(s_itemPassLocalsTypes[(int)LocalsTypes.Items].Name, _data.Items));

                // This is currently only needed when debugging
                _importRelationships = new Dictionary<ProjectRootElement, ProjectRootElement>();

                // This is passed back to the build, so locals are visible during the build
                _projectLevelLocalsForBuild = _itemPassLocals;
            }
#endif
#if (!STANDALONEBUILD)
            CodeMarkers.Instance.CodeMarker(CodeMarkerEvent.perfMSBuildProjectEvaluatePass0End);
#endif
            string projectFile = String.IsNullOrEmpty(_projectRootElement.ProjectFileLocation.File) ? "(null)" : _projectRootElement.ProjectFileLocation.File;

            _loggingService.LogComment(_buildEventContext, MessageImportance.Low, "EvaluationStarted", projectFile);

#if MSBUILDENABLEVSPROFILING 
            string endPass0 = String.Format(CultureInfo.CurrentCulture, "Evaluate Project {0} - End Pass 0 (Initial properties)", projectFile);
            DataCollection.CommentMarkProfile(8816, endPass0);
#endif

            // Pass1: evaluate properties, load imports, and gather everything else
            PerformDepthFirstPass(_projectRootElement);

            List<string> initialTargets = new List<string>(_initialTargetsList.Count);
            for (int i = 0; i < _initialTargetsList.Count; i++)
            {
                initialTargets.Add(EscapingUtilities.UnescapeAll(_initialTargetsList[i].Trim()));
            }

            _data.InitialTargets = initialTargets;
#if (!STANDALONEBUILD)
            CodeMarkers.Instance.CodeMarker(CodeMarkerEvent.perfMSBuildProjectEvaluatePass1End);
#endif
#if MSBUILDENABLEVSPROFILING 
            string endPass1 = String.Format(CultureInfo.CurrentCulture, "Evaluate Project {0} - End Pass 1 (Properties and Imports)", projectFile);
            DataCollection.CommentMarkProfile(8817, endPass1);
#endif
            // Pass2: evaluate item definitions
            foreach (ProjectItemDefinitionGroupElement itemDefinitionGroupElement in _itemDefinitionGroupElements)
            {
                EvaluateItemDefinitionGroupElement(itemDefinitionGroupElement);
            }
#if (!STANDALONEBUILD)
            CodeMarkers.Instance.CodeMarker(CodeMarkerEvent.perfMSBuildProjectEvaluatePass2End);
#endif
#if MSBUILDENABLEVSPROFILING 
            string endPass2 = String.Format(CultureInfo.CurrentCulture, "Evaluate Project {0} - End Pass 2 (Item Definitions)", projectFile);
            DataCollection.CommentMarkProfile(8818, endPass2);
#endif
            LazyItemEvaluator<P, I, M, D> lazyEvaluator = null;

            // comment next line to turn off lazy Evaluation
            lazyEvaluator = new LazyItemEvaluator<P, I, M, D>(_data, _itemFactory, _buildEventContext, _loggingService);

            // Pass3: evaluate project items
            foreach (ProjectItemGroupElement itemGroupElement in _itemGroupElements)
            {
                EvaluateItemGroupElement(itemGroupElement, lazyEvaluator);
            }

            if (lazyEvaluator != null)
            {

                // Tell the lazy evaluator to compute the items and add them to _data
                IList<LazyItemEvaluator<P, I, M, D>.ItemData> items = lazyEvaluator.GetAllItems();
                foreach (var itemData in items)
                {
                    if (itemData.ConditionResult)
                    {
                        _data.AddItem(itemData.Item);

                        if (_data.ShouldEvaluateForDesignTime)
                        {
                            _data.AddToAllEvaluatedItemsList(itemData.Item);
                        }
                    }

                    if (_data.ShouldEvaluateForDesignTime)
                    {
                        _data.AddItemIgnoringCondition(itemData.Item);
                    }
                }

                // lazy evaluator can be collected now, the rest of evaluation does not need it anymore
                lazyEvaluator = null;
            }

#if (!STANDALONEBUILD)
            CodeMarkers.Instance.CodeMarker(CodeMarkerEvent.perfMSBuildProjectEvaluatePass3End);
#endif
#if MSBUILDENABLEVSPROFILING 
            string endPass3 = String.Format(CultureInfo.CurrentCulture, "Evaluate Project {0} - End Pass 3 (Items)", projectFile);
            DataCollection.CommentMarkProfile(8819, endPass3);
#endif
            // Pass4: evaluate using-tasks
            foreach (Pair<string, ProjectUsingTaskElement> entry in _usingTaskElements)
            {
                EvaluateUsingTaskElement(entry.Key, entry.Value);
            }

            // If there was no DefaultTargets attribute found in the depth first pass, 
            // use the name of the first target. If there isn't any target, don't error until build time.
            if (_data.DefaultTargets == null || _data.DefaultTargets.Count == 0)
            {
                List<string> defaultTargets = new List<string>(_targetElements.Count);
                if (_targetElements.Count > 0)
                {
                    defaultTargets.Add(_targetElements[0].Name);
                }

                _data.DefaultTargets = defaultTargets;
            }

            Dictionary<string, List<TargetSpecification>> targetsWhichRunBeforeByTarget = new Dictionary<string, List<TargetSpecification>>(StringComparer.OrdinalIgnoreCase);
            Dictionary<string, List<TargetSpecification>> targetsWhichRunAfterByTarget = new Dictionary<string, List<TargetSpecification>>(StringComparer.OrdinalIgnoreCase);
            LinkedList<ProjectTargetElement> activeTargetsByEvaluationOrder = new LinkedList<ProjectTargetElement>();
            Dictionary<string, LinkedListNode<ProjectTargetElement>> activeTargets = new Dictionary<string, LinkedListNode<ProjectTargetElement>>(StringComparer.OrdinalIgnoreCase);
#if (!STANDALONEBUILD)
            CodeMarkers.Instance.CodeMarker(CodeMarkerEvent.perfMSBuildProjectEvaluatePass4End);
#endif
#if MSBUILDENABLEVSPROFILING 
            string endPass4 = String.Format(CultureInfo.CurrentCulture, "Evaluate Project {0} - End Pass 4 (UsingTasks)", projectFile);
            DataCollection.CommentMarkProfile(8820, endPass4);
#endif

            // Pass5: read targets (but don't evaluate them: that happens during build)
            foreach (ProjectTargetElement targetElement in _targetElements)
            {
                ReadTargetElement(targetElement, activeTargetsByEvaluationOrder, activeTargets);
            }

            foreach (ProjectTargetElement target in activeTargetsByEvaluationOrder)
            {
                AddBeforeAndAfterTargetMappings(target, activeTargets, targetsWhichRunBeforeByTarget, targetsWhichRunAfterByTarget);
            }

            _data.BeforeTargets = targetsWhichRunBeforeByTarget;
            _data.AfterTargets = targetsWhichRunAfterByTarget;

            if (s_debugEvaluation)
            {
                // This is so important for VS performance it's worth always tracing; accidentally having 
                // inconsistent sets of global properties will cause reevaluations, which are wasteful and incorrect
                if (_projectRootElement.Count > 0) // VB/C# will new up empty projects; they aren't worth recording
                {
                    ProjectPropertyInstance configurationData = _data.GlobalPropertiesDictionary["currentsolutionconfigurationcontents"];
                    int hash = (configurationData != null) ? configurationData.EvaluatedValue.GetHashCode() : 0;
                    string propertyDump = null;

                    foreach (var entry in _data.GlobalPropertiesDictionary)
                    {
                        if (!String.Equals(entry.Name, "currentsolutionconfigurationcontents", StringComparison.OrdinalIgnoreCase))
                        {
                            propertyDump += entry.Name + "=" + entry.EvaluatedValue + "\n";
                        }
                    }

                    string line = new string('#', 100) + "\n";

                    string output = String.Format(CultureInfo.CurrentUICulture, "###: MSBUILD: Evaluating or reevaluating project {0} with {1} global properties and {2} tools version, child count {3}, CurrentSolutionConfigurationContents hash {4} other properties:\n{5}", _projectRootElement.FullPath, globalProperties.Count, _data.Toolset.ToolsVersion, _projectRootElement.Count, hash, propertyDump);

                    Trace.WriteLine(line + output + line);
                }
            }

            _data.FinishEvaluation();

            _loggingService.LogComment(_buildEventContext, MessageImportance.Low, "EvaluationFinished", projectFile);

#if FEATURE_MSBUILD_DEBUGGER
            return _projectLevelLocalsForBuild;
#else
            return null;
#endif
        }