@@ -162,6 +162,30 @@ public sealed class ResolvePackageAssets : TaskBase
162
162
/// </summary>
163
163
public bool DesignTimeBuild { get ; set ; }
164
164
165
+ /// <summary>
166
+ /// Eg: "Microsoft.NETCore.App;NETStandard.Library"
167
+ /// </summary>
168
+ [ Required ]
169
+ public string DefaultImplicitPackages { get ; set ; }
170
+
171
+ /// <summary>
172
+ /// Items with metadata "ParentTarget" and "ParentPackage", which allows determining the hierarchy of package references.
173
+ /// </summary>
174
+ [ Required ]
175
+ public ITaskItem [ ] InputPackageDependencies { get ; set ; }
176
+
177
+ /// <summary>
178
+ /// Information about each package in the project, with metadata:
179
+ /// - Name = "MetadataExtractor"
180
+ /// - Path = "metadataextractor/1.0.0"
181
+ /// - ResolvedPath = "C:\Users\drnoakes\.nuget\packages\metadataextractor\1.0.0"
182
+ /// - Type = "package"
183
+ /// - Version = "2.3.0"
184
+ /// - DiagnosticLevel = ""
185
+ /// </summary>
186
+ [ Required ]
187
+ public ITaskItem [ ] PackageDefinitions { get ; set ; }
188
+
165
189
#endregion
166
190
167
191
#region Output Items
@@ -238,6 +262,17 @@ public sealed class ResolvePackageAssets : TaskBase
238
262
[ Output ]
239
263
public ITaskItem [ ] PackageDependencies { get ; private set ; }
240
264
265
+ /// <summary>
266
+ /// Filters and projects items produced by <see cref="ResolvePackageDependencies"/> for consumption by
267
+ /// the dependencies tree, via design-time builds.
268
+ /// </summary>
269
+ /// <remarks>
270
+ /// Changes to the implementation of output must be coordinated with <c>PackageRuleHandler</c>
271
+ /// in the dotnet/project-system repo.
272
+ /// </remarks>
273
+ [ Output ]
274
+ public ITaskItem [ ] PackageDependenciesDesignTime { get ; private set ; }
275
+
241
276
/// <summary>
242
277
/// List of symbol files (.pdb) related to NuGet packages.
243
278
/// </summary>
@@ -311,7 +346,7 @@ public sealed class ResolvePackageAssets : TaskBase
311
346
////////////////////////////////////////////////////////////////////////////////////////////////////
312
347
313
348
private const int CacheFormatSignature = ( 'P' << 0 ) | ( 'K' << 8 ) | ( 'G' << 16 ) | ( 'A' << 24 ) ;
314
- private const int CacheFormatVersion = 11 ;
349
+ private const int CacheFormatVersion = 12 ;
315
350
private static readonly Encoding TextEncoding = Encoding . UTF8 ;
316
351
private const int SettingsHashLength = 256 / 8 ;
317
352
private HashAlgorithm CreateSettingsHash ( ) => SHA256 . Create ( ) ;
@@ -343,6 +378,7 @@ private void ReadItemGroups()
343
378
FrameworkReferences = reader . ReadItemGroup ( ) ;
344
379
NativeLibraries = reader . ReadItemGroup ( ) ;
345
380
PackageDependencies = reader . ReadItemGroup ( ) ;
381
+ PackageDependenciesDesignTime = reader . ReadItemGroup ( ) ;
346
382
PackageFolders = reader . ReadItemGroup ( ) ;
347
383
ReferenceDocumentationFiles = reader . ReadItemGroup ( ) ;
348
384
ResourceAssemblies = reader . ReadItemGroup ( ) ;
@@ -660,6 +696,7 @@ private ITaskItem ReadItem()
660
696
internal sealed class CacheWriter : IDisposable
661
697
{
662
698
private const int InitialStringTableCapacity = 32 ;
699
+ private const string ResolvedMetadata = "Resolved" ;
663
700
664
701
private ResolvePackageAssets _task ;
665
702
private BinaryWriter _writer ;
@@ -814,6 +851,7 @@ private void WriteItemGroups()
814
851
WriteItemGroup ( WriteFrameworkReferences ) ;
815
852
WriteItemGroup ( WriteNativeLibraries ) ;
816
853
WriteItemGroup ( WritePackageDependencies ) ;
854
+ WriteItemGroup ( WritePackageDependenciesDesignTime ) ;
817
855
WriteItemGroup ( WritePackageFolders ) ;
818
856
WriteItemGroup ( WriteReferenceDocumentationFiles ) ;
819
857
WriteItemGroup ( WriteResourceAssemblies ) ;
@@ -1408,6 +1446,111 @@ private void WritePackageDependencies()
1408
1446
}
1409
1447
}
1410
1448
1449
+ private void WritePackageDependenciesDesignTime ( )
1450
+ {
1451
+ var implicitPackageReferences = GetImplicitPackageReferences ( _task . DefaultImplicitPackages ) ;
1452
+
1453
+ // We have two types of data:
1454
+ //
1455
+ // 1) "PackageDependencies" which place a package in a given target/hierarchy
1456
+ // 2) "PackageDefinitions" which provide general metadata about a package
1457
+ //
1458
+ // First, we scan PackageDependencies to build the set of packages in our target.
1459
+
1460
+ var allowItemSpecs = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) ;
1461
+
1462
+ foreach ( var dependency in _task . InputPackageDependencies )
1463
+ {
1464
+ if ( dependency . HasMetadataValue ( MetadataKeys . ParentPackage ) )
1465
+ {
1466
+ // ignore non-top-level packages (those with ParentPackage)
1467
+ continue ;
1468
+ }
1469
+
1470
+ var target = dependency . GetMetadata ( MetadataKeys . ParentTarget ) ;
1471
+
1472
+ if ( ! StringComparer . OrdinalIgnoreCase . Equals ( target , _task . TargetFramework ) )
1473
+ {
1474
+ // skip dependencies for other targets
1475
+ continue ;
1476
+ }
1477
+
1478
+ allowItemSpecs . Add ( dependency . ItemSpec ) ;
1479
+ }
1480
+
1481
+ // Second, find PackageDefinitions that match our allowed item specs
1482
+
1483
+ var outputItems = new List < ITaskItem > ( allowItemSpecs . Count ) ;
1484
+
1485
+ foreach ( var packageDef in _task . PackageDefinitions )
1486
+ {
1487
+ if ( ! allowItemSpecs . Contains ( packageDef . ItemSpec ) )
1488
+ {
1489
+ // We are not interested in this definition (not top-level, or wrong target)
1490
+ continue ;
1491
+ }
1492
+
1493
+ var dependencyType = GetDependencyType ( packageDef . GetMetadata ( MetadataKeys . Type ) ) ;
1494
+
1495
+ if ( dependencyType == DependencyType . Package ||
1496
+ dependencyType == DependencyType . Unresolved )
1497
+ {
1498
+ var name = packageDef . GetMetadata ( MetadataKeys . Name ) ;
1499
+
1500
+ if ( string . IsNullOrEmpty ( name ) )
1501
+ {
1502
+ // Name is required
1503
+ continue ;
1504
+ }
1505
+
1506
+ var version = packageDef . GetMetadata ( MetadataKeys . Version ) ?? string . Empty ;
1507
+ var resolvedPath = packageDef . GetMetadata ( MetadataKeys . ResolvedPath ) ;
1508
+ var resolved = ! string . IsNullOrEmpty ( resolvedPath ) ;
1509
+ var path = ( resolved
1510
+ ? resolvedPath
1511
+ : packageDef . GetMetadata ( MetadataKeys . Path ) ) ?? string . Empty ;
1512
+ var isImplicitlyDefined = implicitPackageReferences . Contains ( name ) ;
1513
+ var diagnosticLevel = packageDef . GetMetadata ( MetadataKeys . DiagnosticLevel ) ?? string . Empty ;
1514
+
1515
+ WriteItem ( packageDef . ItemSpec ) ;
1516
+ WriteMetadata ( MetadataKeys . Name , name ) ;
1517
+ WriteMetadata ( MetadataKeys . Version , version ) ;
1518
+ WriteMetadata ( MetadataKeys . Path , path ) ;
1519
+ WriteMetadata ( MetadataKeys . IsImplicitlyDefined , isImplicitlyDefined . ToString ( ) ) ;
1520
+ WriteMetadata ( MetadataKeys . DiagnosticLevel , diagnosticLevel ) ;
1521
+ WriteMetadata ( ResolvedMetadata , resolved . ToString ( ) ) ;
1522
+ }
1523
+ }
1524
+
1525
+ static HashSet < string > GetImplicitPackageReferences ( string defaultImplicitPackages )
1526
+ {
1527
+ var implicitPackageReferences = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) ;
1528
+ if ( string . IsNullOrEmpty ( defaultImplicitPackages ) )
1529
+ {
1530
+ return implicitPackageReferences ;
1531
+ }
1532
+
1533
+ var packageNames = defaultImplicitPackages . Split ( new [ ] { ';' } , StringSplitOptions . RemoveEmptyEntries ) ;
1534
+ if ( packageNames . Length == 0 )
1535
+ {
1536
+ return implicitPackageReferences ;
1537
+ }
1538
+
1539
+ foreach ( var packageReference in packageNames )
1540
+ {
1541
+ implicitPackageReferences . Add ( packageReference ) ;
1542
+ }
1543
+
1544
+ return implicitPackageReferences ;
1545
+ }
1546
+
1547
+ static DependencyType GetDependencyType ( string dependencyTypeString )
1548
+ {
1549
+ Enum . TryParse ( dependencyTypeString , ignoreCase : true , out DependencyType dependencyType ) ;
1550
+ return dependencyType ;
1551
+ }
1552
+ }
1553
+
1411
1554
private void WriteResourceAssemblies ( )
1412
1555
{
1413
1556
WriteItems (
0 commit comments