@@ -61,7 +61,12 @@ public enum ProjectLoadSettings
61
61
/// <summary>
62
62
/// Throw an exception and stop the evaluation of a project if any circular imports are detected
63
63
/// </summary>
64
- RejectCircularImports = 4
64
+ RejectCircularImports = 4 ,
65
+
66
+ /// <summary>
67
+ /// Record the item elements that got evaluated
68
+ /// </summary>
69
+ RecordEvaluatedItemElements = 8
65
70
}
66
71
67
72
/// <summary>
@@ -1069,6 +1074,7 @@ public static string GetEvaluatedItemIncludeEscaped(ProjectItemDefinition item)
1069
1074
/// </returns>
1070
1075
public List < GlobResult > GetAllGlobs ( )
1071
1076
{
1077
+ ReevaluateForPostMortemAnalysisIfNecessary ( ) ;
1072
1078
return GetAllGlobs ( _data . EvaluatedItemElements ) ;
1073
1079
}
1074
1080
@@ -1082,6 +1088,8 @@ public List<GlobResult> GetAllGlobs(string itemType)
1082
1088
{
1083
1089
return new List < GlobResult > ( ) ;
1084
1090
}
1091
+
1092
+ ReevaluateForPostMortemAnalysisIfNecessary ( ) ;
1085
1093
return GetAllGlobs ( GetItemElementsByType ( _data . EvaluatedItemElements , itemType ) ) ;
1086
1094
}
1087
1095
@@ -1156,6 +1164,7 @@ private IEnumerable<GlobResult> GetAllGlobs(ProjectItemElement itemElement)
1156
1164
/// </returns>
1157
1165
public List < ProvenanceResult > GetItemProvenance ( string itemToMatch )
1158
1166
{
1167
+ ReevaluateForPostMortemAnalysisIfNecessary ( ) ;
1159
1168
return GetItemProvenance ( itemToMatch , _data . EvaluatedItemElements ) ;
1160
1169
}
1161
1170
@@ -1166,6 +1175,7 @@ public List<ProvenanceResult> GetItemProvenance(string itemToMatch)
1166
1175
/// <param name="itemType">The item type to constrain the search in</param>
1167
1176
public List < ProvenanceResult > GetItemProvenance ( string itemToMatch , string itemType )
1168
1177
{
1178
+ ReevaluateForPostMortemAnalysisIfNecessary ( ) ;
1169
1179
return GetItemProvenance ( itemToMatch , GetItemElementsByType ( _data . EvaluatedItemElements , itemType ) ) ;
1170
1180
}
1171
1181
@@ -1184,11 +1194,30 @@ public List<ProvenanceResult> GetItemProvenance(ProjectItem item)
1184
1194
return new List < ProvenanceResult > ( ) ;
1185
1195
}
1186
1196
1197
+ ReevaluateForPostMortemAnalysisIfNecessary ( ) ;
1187
1198
var itemElementsAbove = GetItemElementsThatMightAffectItem ( _data . EvaluatedItemElements , item ) ;
1188
1199
1189
1200
return GetItemProvenance ( item . EvaluatedInclude , itemElementsAbove ) ;
1190
1201
}
1191
1202
1203
+ /// <summary>
1204
+ /// Some project APIs need to do analysis that requires the Evaluator to record more data than usual as it evaluates.
1205
+ /// This method checks if the Evaluator was run with the extra required settings and if not, does a re-evaluation.
1206
+ /// If a re-evaluation was necessary, it saves this information so a next call does not re-evaluate.
1207
+ ///
1208
+ /// Using this method avoids storing extra data in memory when its not needed.
1209
+ /// </summary>
1210
+ private void ReevaluateForPostMortemAnalysisIfNecessary ( )
1211
+ {
1212
+ if ( _loadSettings . HasFlag ( ProjectLoadSettings . RecordEvaluatedItemElements ) )
1213
+ {
1214
+ return ;
1215
+ }
1216
+
1217
+ _loadSettings = _loadSettings | ProjectLoadSettings . RecordEvaluatedItemElements ;
1218
+ Reevaluate ( LoggingService , _loadSettings ) ;
1219
+ }
1220
+
1192
1221
private static IEnumerable < ProjectItemElement > GetItemElementsThatMightAffectItem ( List < ProjectItemElement > evaluatedItemElements , ProjectItem item )
1193
1222
{
1194
1223
return evaluatedItemElements
@@ -2392,34 +2421,22 @@ private ProjectInstance CreateProjectInstance(ILoggingService loggingServiceForE
2392
2421
/// Re-evaluates the project using the specified logging service.
2393
2422
/// </summary>
2394
2423
private void ReevaluateIfNecessary ( ILoggingService loggingServiceForEvaluation )
2424
+ {
2425
+ ReevaluateIfNecessary ( loggingServiceForEvaluation , _loadSettings ) ;
2426
+ }
2427
+
2428
+ /// <summary>
2429
+ /// Re-evaluates the project using the specified logging service and load settings.
2430
+ /// </summary>
2431
+ private void ReevaluateIfNecessary ( ILoggingService loggingServiceForEvaluation , ProjectLoadSettings loadSettings )
2395
2432
{
2396
2433
// We will skip the evaluation if the flag is set. This will give us better performance on scenarios
2397
2434
// that we know we don't have to reevaluate. One example is project conversion bulk addfiles and set attributes.
2398
2435
if ( ! SkipEvaluation && ! _projectCollection . SkipEvaluation && IsDirty )
2399
2436
{
2400
2437
try
2401
2438
{
2402
- Evaluator < ProjectProperty , ProjectItem , ProjectMetadata , ProjectItemDefinition > . Evaluate ( _data , _xml , _loadSettings , ProjectCollection . MaxNodeCount , ProjectCollection . EnvironmentProperties , loggingServiceForEvaluation , new ProjectItemFactory ( this ) , _projectCollection as IToolsetProvider , _projectCollection . ProjectRootElementCache , s_buildEventContext , null /* no project instance for debugging */ ) ;
2403
-
2404
- // We have to do this after evaluation, because evaluation might have changed
2405
- // the imports being pulled in.
2406
- int highestXmlVersion = Xml . Version ;
2407
-
2408
- if ( _data . ImportClosure != null )
2409
- {
2410
- foreach ( Triple < ProjectImportElement , ProjectRootElement , int > triple in _data . ImportClosure )
2411
- {
2412
- highestXmlVersion = ( highestXmlVersion < triple . Third ) ? triple . Third : highestXmlVersion ;
2413
- }
2414
- }
2415
-
2416
- _explicitlyMarkedDirty = false ;
2417
- _evaluatedVersion = highestXmlVersion ;
2418
- _evaluatedToolsetCollectionVersion = ProjectCollection . ToolsetsVersion ;
2419
- _evaluationCounter = GetNextEvaluationCounter ( ) ;
2420
- _data . HasUnsavedChanges = false ;
2421
-
2422
- ErrorUtilities . VerifyThrow ( ! IsDirty , "Should not be dirty now" ) ;
2439
+ Reevaluate ( loggingServiceForEvaluation , loadSettings ) ;
2423
2440
}
2424
2441
catch ( InvalidProjectFileException ex )
2425
2442
{
@@ -2429,6 +2446,31 @@ private void ReevaluateIfNecessary(ILoggingService loggingServiceForEvaluation)
2429
2446
}
2430
2447
}
2431
2448
2449
+ private void Reevaluate ( ILoggingService loggingServiceForEvaluation , ProjectLoadSettings loadSettings )
2450
+ {
2451
+ Evaluator < ProjectProperty , ProjectItem , ProjectMetadata , ProjectItemDefinition > . Evaluate ( _data , _xml , loadSettings , ProjectCollection . MaxNodeCount , ProjectCollection . EnvironmentProperties , loggingServiceForEvaluation , new ProjectItemFactory ( this ) , _projectCollection as IToolsetProvider , _projectCollection . ProjectRootElementCache , s_buildEventContext , null /* no project instance for debugging */ ) ;
2452
+
2453
+ // We have to do this after evaluation, because evaluation might have changed
2454
+ // the imports being pulled in.
2455
+ int highestXmlVersion = Xml . Version ;
2456
+
2457
+ if ( _data . ImportClosure != null )
2458
+ {
2459
+ foreach ( Triple < ProjectImportElement , ProjectRootElement , int > triple in _data . ImportClosure )
2460
+ {
2461
+ highestXmlVersion = ( highestXmlVersion < triple . Third ) ? triple . Third : highestXmlVersion ;
2462
+ }
2463
+ }
2464
+
2465
+ _explicitlyMarkedDirty = false ;
2466
+ _evaluatedVersion = highestXmlVersion ;
2467
+ _evaluatedToolsetCollectionVersion = ProjectCollection . ToolsetsVersion ;
2468
+ _evaluationCounter = GetNextEvaluationCounter ( ) ;
2469
+ _data . HasUnsavedChanges = false ;
2470
+
2471
+ ErrorUtilities . VerifyThrow ( ! IsDirty , "Should not be dirty now" ) ;
2472
+ }
2473
+
2432
2474
/// <summary>
2433
2475
/// Common code for the constructors.
2434
2476
/// Applies global properties that are on the collection.
0 commit comments