@@ -108,54 +108,66 @@ public override bool Execute()
108
108
109
109
var report = new XElement ( "AnnotatedUsages" ) ;
110
110
111
- foreach ( Usage usage in data . Usages . NullAsEmpty ( ) )
112
- {
113
- string id = usage . PackageIdentity . Id ;
114
- string version = usage . PackageIdentity . Version . OriginalVersion ;
111
+ var annotatedUsages = data . Usages . NullAsEmpty ( )
112
+ . Select ( usage =>
113
+ {
114
+ string id = usage . PackageIdentity . Id ;
115
+ string version = usage . PackageIdentity . Version . OriginalVersion ;
115
116
116
- string pvpIdent = WriteBuildOutputProps . GetPropertyName ( id ) ;
117
+ string pvpIdent = WriteBuildOutputProps . GetPropertyName ( id ) ;
117
118
118
- var sourceBuildCreator = new StringBuilder ( ) ;
119
- foreach ( RepoOutput output in sourceBuildRepoOutputs )
120
- {
121
- foreach ( PackageVersionPropsElement p in output . Built )
119
+ var sourceBuildCreator = new StringBuilder ( ) ;
120
+ foreach ( RepoOutput output in sourceBuildRepoOutputs )
122
121
{
123
- if ( p . Name . Equals ( pvpIdent , StringComparison . OrdinalIgnoreCase ) )
122
+ foreach ( PackageVersionPropsElement p in output . Built )
124
123
{
125
- if ( sourceBuildCreator . Length != 0 )
124
+ if ( p . Name . Equals ( pvpIdent , StringComparison . OrdinalIgnoreCase ) )
126
125
{
126
+ if ( sourceBuildCreator . Length != 0 )
127
+ {
128
+ sourceBuildCreator . Append ( " " ) ;
129
+ }
130
+ sourceBuildCreator . Append ( output . Repo ) ;
127
131
sourceBuildCreator . Append ( " " ) ;
132
+ sourceBuildCreator . Append ( p . Name ) ;
133
+ sourceBuildCreator . Append ( "/" ) ;
134
+ sourceBuildCreator . Append ( p . Version ) ;
128
135
}
129
- sourceBuildCreator . Append ( output . Repo ) ;
130
- sourceBuildCreator . Append ( " " ) ;
131
- sourceBuildCreator . Append ( p . Name ) ;
132
- sourceBuildCreator . Append ( "/" ) ;
133
- sourceBuildCreator . Append ( p . Version ) ;
134
136
}
135
137
}
136
- }
137
138
138
- prodConPackageOrigin . TryGetValue ( id , out string prodConCreator ) ;
139
+ prodConPackageOrigin . TryGetValue ( id , out string prodConCreator ) ;
139
140
140
- var annotated = new AnnotatedUsage
141
- {
142
- Usage = usage ,
141
+ return new AnnotatedUsage
142
+ {
143
+ Usage = usage ,
143
144
144
- Project = data . ProjectDirectories
145
- ? . FirstOrDefault ( p => usage . AssetsFile ? . StartsWith ( p ) ?? false ) ,
145
+ Project = data . ProjectDirectories
146
+ ? . FirstOrDefault ( p => usage . AssetsFile ? . StartsWith ( p ) ?? false ) ,
146
147
147
- SourceBuildPackageIdCreator = sourceBuildCreator . Length == 0
148
- ? null
149
- : sourceBuildCreator . ToString ( ) ,
148
+ SourceBuildPackageIdCreator = sourceBuildCreator . Length == 0
149
+ ? null
150
+ : sourceBuildCreator . ToString ( ) ,
150
151
151
- ProdConPackageIdCreator = prodConCreator ,
152
+ ProdConPackageIdCreator = prodConCreator ,
152
153
153
- EndsUpInOutput = poisonNupkgFilenames . Contains ( $ "{ id } .{ version } ")
154
- } ;
154
+ TestProjectByHeuristic = IsTestUsageByHeuristic ( usage ) ,
155
155
156
- report . Add ( annotated . ToXml ( ) ) ;
156
+ EndsUpInOutput = poisonNupkgFilenames . Contains ( $ "{ id } .{ version } ")
157
+ } ;
158
+ } )
159
+ . ToArray ( ) ;
160
+
161
+ foreach ( var onlyTestProjectUsage in annotatedUsages
162
+ . GroupBy ( u => u . Usage . PackageIdentity )
163
+ . Where ( g => g . All ( u => u . TestProjectByHeuristic ) )
164
+ . SelectMany ( g => g ) )
165
+ {
166
+ onlyTestProjectUsage . TestProjectOnlyByHeuristic = true ;
157
167
}
158
168
169
+ report . Add ( annotatedUsages . Select ( u => u . ToXml ( ) ) ) ;
170
+
159
171
Directory . CreateDirectory ( OutputDirectory ) ;
160
172
161
173
File . WriteAllText (
@@ -233,6 +245,29 @@ private void AddProdConPackage(
233
245
}
234
246
}
235
247
248
+ public static bool IsTestUsageByHeuristic ( Usage usage )
249
+ {
250
+ string [ ] assetsFileParts = usage . AssetsFile ? . Split ( '/' , '\\ ' ) ;
251
+
252
+ // If the dir name ends in Test(s), it's probably a test project.
253
+ // Ignore the first two segments to avoid classifying everything in "src/vstest".
254
+ // This also catches "test" dirs that contain many test projects.
255
+ if ( assetsFileParts ? . Skip ( 2 ) . Any ( p =>
256
+ p . EndsWith ( "Tests" , StringComparison . OrdinalIgnoreCase ) ||
257
+ p . EndsWith ( "Test" , StringComparison . OrdinalIgnoreCase ) ) == true )
258
+ {
259
+ return true ;
260
+ }
261
+
262
+ // CoreFX restores test dependencies during this sync project.
263
+ if ( assetsFileParts ? . Contains ( "XUnit.Runtime" ) == true )
264
+ {
265
+ return true ;
266
+ }
267
+
268
+ return false ;
269
+ }
270
+
236
271
private class RepoOutput
237
272
{
238
273
public string Repo { get ; set ; }
0 commit comments