@@ -144,9 +144,6 @@ public static IEnumerable<object[]> ProjectData
144144 new object [ ] { "dotnet.new" , "1.0.0" , null , "dotnet.new.resources" , null , dotnetNewSatelliteAssemblies , null , null , null } ,
145145 new object [ ] { "simple.dependencies" , "1.0.0" , null , "simple.dependencies" , null , null , null , null , resolvedNuGetFiles } ,
146146 } ;
147-
148-
149-
150147 }
151148 }
152149
@@ -190,11 +187,16 @@ public void ItDoesntCreateReferenceAssembliesWhenNoCompilationOptions()
190187 . RuntimeLibraries
191188 . SelectMany ( l => l . Dependencies )
192189 . Should ( )
193- . NotBeEmpty ( )
194- . And
195- . NotContain ( d => d . Name == "System.NotConflicting" )
196- . And
197- . NotContain ( d => d . Name == "System.Collections.NonGeneric.Reference" ) ;
190+ . BeEmpty ( ) ;
191+ }
192+
193+ [ Fact ]
194+ public void ItDoesntCreateKeepUnneededRuntimeReferences ( )
195+ {
196+ DependencyContext dependencyContext = BuildDependencyContextWithReferenceAssemblies ( useCompilationOptions : false ) ;
197+
198+ dependencyContext . RuntimeLibraries . Count . Should ( ) . Be ( 1 ) ;
199+ dependencyContext . RuntimeLibraries [ 0 ] . Name . Should ( ) . Be ( "simple.dependencies" ) ; // This is the entrypoint
198200 }
199201
200202 [ Fact ]
@@ -213,6 +215,188 @@ public void ItHandlesReferenceAndPackageReferenceNameCollisions()
213215 . Contain ( c => c . Name == "System.Collections.NonGeneric.Reference.Reference" && c . Type == "referenceassembly" ) ;
214216 }
215217
218+ // If an assembly is in withResources, it has to be a key in dependencies, even with an empty list.
219+ private static DependencyContext BuildDependencyContextFromDependenciesWithResources ( Dictionary < string , List < string > > dependencies , List < string > withResources , List < string > references , bool dllReference )
220+ {
221+ string mainProjectName = "simpleApp" ;
222+ LockFile lockFile = TestLockFiles . GetLockFile ( mainProjectName ) ;
223+
224+ SingleProjectInfo mainProject = SingleProjectInfo . Create (
225+ "/usr/Path" ,
226+ mainProjectName ,
227+ ".dll" ,
228+ "1.0.0" ,
229+ [ ] ) ;
230+ string mainProjectDirectory = Path . GetDirectoryName ( mainProject . ProjectPath ) ;
231+
232+
233+ ITaskItem [ ] referencePaths = dllReference ? references . Select ( reference =>
234+ new MockTaskItem ( $ "/usr/Path/{ reference } .dll", new Dictionary < string , string > {
235+ { "CopyLocal" , "false" } ,
236+ { "FusionName" , $ "{ reference } , Version=4.0.0.0, Culture=neutral, PublicKeyToken=null" } ,
237+ { "Version" , "" } ,
238+ } ) ) . ToArray ( ) : [ ] ;
239+
240+ ProjectContext projectContext = lockFile . CreateProjectContext (
241+ FrameworkConstants . CommonFrameworks . Net10_0 . GetShortFolderName ( ) ,
242+ runtime : null ,
243+ platformLibraryName : Constants . DefaultPlatformLibrary ,
244+ runtimeFrameworks : null ,
245+ isSelfContained : false ) ;
246+
247+ if ( ! dllReference )
248+ {
249+ projectContext . LockFile . ProjectFileDependencyGroups . Add ( new ProjectFileDependencyGroup ( string . Empty , references ) ) ;
250+ }
251+
252+ Dictionary < string , SingleProjectInfo > referenceProjectInfos = new ( ) ;
253+
254+ foreach ( KeyValuePair < string , List < string > > kvp in dependencies )
255+ {
256+ projectContext . LockFileTarget . Libraries = projectContext . LockFileTarget . Libraries . Concat ( [
257+ new LockFileTargetLibrary ( )
258+ {
259+ Name = kvp . Key ,
260+ Version = new NuGetVersion ( 4 , 0 , 0 ) ,
261+ Type = withResources . Contains ( kvp . Key ) ? "project" : "unrealType" ,
262+ Dependencies = kvp . Value . Select ( n => new PackageDependency ( n ) ) . ToList ( )
263+ } ] ) . ToList ( ) ;
264+
265+ if ( withResources . Contains ( kvp . Key ) )
266+ {
267+ var fullPath = Path . GetFullPath ( Path . Combine ( mainProjectDirectory , kvp . Key ) ) ;
268+ lockFile . Libraries = lockFile . Libraries . Concat ( [ new LockFileLibrary ( )
269+ {
270+ Name = kvp . Key ,
271+ Version = new NuGetVersion ( 4 , 0 , 0 ) ,
272+ Type = "project" ,
273+ MSBuildProject = fullPath
274+ } ] ) . ToList ( ) ;
275+
276+ referenceProjectInfos . Add ( fullPath , SingleProjectInfo . Create ( kvp . Key , kvp . Key , ".dll" , "4.0.0" ,
277+ [ new MockTaskItem ( $ "{ kvp . Key } .resource", new Dictionary < string , string > ( ) {
278+ { "Culture" , "en-us" } ,
279+ { "TargetPath" , $ "{ kvp . Key } .resource" }
280+ } ) ] ) ) ;
281+ }
282+ }
283+
284+ CompilationOptions compilationOptions = CreateCompilationOptions ( ) ;
285+
286+ return new DependencyContextBuilder ( mainProject , includeRuntimeFileVersions : false , runtimeGraph : null , projectContext : projectContext , libraryLookup : new LockFileLookup ( lockFile ) )
287+ . WithReferenceAssemblies ( ReferenceInfo . CreateReferenceInfos ( referencePaths ) )
288+ . WithCompilationOptions ( compilationOptions )
289+ . WithReferenceProjectInfos ( referenceProjectInfos )
290+ . Build ( ) ;
291+ }
292+
293+ [ Theory ]
294+ [ InlineData ( true ) ]
295+ [ InlineData ( false ) ]
296+ public void DirectReferenceToPackageWithNoAssets ( bool dllReference )
297+ {
298+ DependencyContext dependencyContext = BuildDependencyContextFromDependenciesWithResources ( [ ] , [ ] , [ "System.A" ] , dllReference ) ;
299+ Save ( dependencyContext ) ;
300+ dependencyContext . RuntimeLibraries . Count . Should ( ) . Be ( 1 ) ;
301+ }
302+
303+ [ Theory ]
304+ [ InlineData ( true ) ]
305+ [ InlineData ( false ) ]
306+ public void IndirectReferenceToPackageWithNoAssets ( bool dllReference )
307+ {
308+ DependencyContext dependencyContext = BuildDependencyContextFromDependenciesWithResources ( new Dictionary < string , List < string > > ( ) {
309+ { "System.A" , [ "System.B" ] }
310+ } , [ "System.A" ] , [ "System.A" ] , dllReference ) ;
311+ Save ( dependencyContext ) ;
312+ dependencyContext . RuntimeLibraries . Count . Should ( ) . Be ( 2 ) ;
313+ dependencyContext . RuntimeLibraries . Should ( ) . Contain ( x => x . Name . Equals ( "System.A" ) ) ;
314+ }
315+
316+ [ Theory ]
317+ [ InlineData ( true ) ]
318+ [ InlineData ( false ) ]
319+ public void PackageWithNoAssetsReferencesPackageWithNoAssets ( bool dllReference )
320+ {
321+ DependencyContext dependencyContext = BuildDependencyContextFromDependenciesWithResources ( new Dictionary < string , List < string > > ( ) {
322+ { "System.A" , [ "System.B" ] } ,
323+ { "System.B" , [ ] }
324+ } , [ ] , [ "System.A" ] , dllReference ) ;
325+ Save ( dependencyContext ) ;
326+ dependencyContext . RuntimeLibraries . Count . Should ( ) . Be ( 1 ) ;
327+ }
328+
329+ [ Theory ]
330+ [ InlineData ( true ) ]
331+ [ InlineData ( false ) ]
332+ public void PackageWithNoAssetsReferencesPackageWithAssets ( bool dllReference )
333+ {
334+ DependencyContext dependencyContext = BuildDependencyContextFromDependenciesWithResources ( new Dictionary < string , List < string > > ( ) {
335+ { "System.A" , [ "System.B" ] } ,
336+ { "System.B" , [ ] }
337+ } , [ "System.B" ] , [ "System.A" ] , dllReference ) ;
338+ Save ( dependencyContext ) ;
339+ dependencyContext . RuntimeLibraries . Count . Should ( ) . Be ( 3 ) ;
340+ dependencyContext . RuntimeLibraries . Should ( ) . Contain ( x => x . Name . Equals ( "System.A" ) ) ;
341+ dependencyContext . RuntimeLibraries . Should ( ) . Contain ( x => x . Name . Equals ( "System.B" ) ) ;
342+ }
343+
344+ [ Theory ]
345+ [ InlineData ( true ) ]
346+ [ InlineData ( false ) ]
347+ public void PackageWithNoAssetsReferencesPackageReferencesByOtherPackage ( bool dllReference )
348+ {
349+ DependencyContext dependencyContext = BuildDependencyContextFromDependenciesWithResources ( new Dictionary < string , List < string > > ( )
350+ {
351+ { "System.A" , [ "System.B" ] } ,
352+ { "System.B" , [ ] } ,
353+ } , [ "System.B" ] , [ "System.A" , "System.B" ] , dllReference ) ;
354+ Save ( dependencyContext ) ;
355+ dependencyContext . RuntimeLibraries . Count . Should ( ) . Be ( 2 ) ;
356+ dependencyContext . RuntimeLibraries . Should ( ) . Contain ( x => x . Name . Equals ( "System.B" ) ) ;
357+ }
358+
359+ [ Theory ]
360+ [ InlineData ( true ) ]
361+ [ InlineData ( false ) ]
362+ public void PackageWithNoAssetsReferencesPackageWithAssetsWithOtherReferencer ( bool dllReference )
363+ {
364+ DependencyContext dependencyContext = BuildDependencyContextFromDependenciesWithResources ( new Dictionary < string , List < string > > ( )
365+ {
366+ { "System.A" , [ "System.B" ] } ,
367+ { "System.B" , [ ] } ,
368+ { "System.C" , [ "System.B" ] }
369+ } , [ "System.B" , "System.C" ] , [ "System.A" , "System.C" ] , dllReference ) ;
370+ Save ( dependencyContext ) ;
371+ dependencyContext . RuntimeLibraries . Count . Should ( ) . Be ( 3 ) ;
372+ dependencyContext . RuntimeLibraries . Should ( ) . Contain ( x => x . Name . Equals ( "System.C" ) ) ;
373+ dependencyContext . RuntimeLibraries . Should ( ) . Contain ( x => x . Name . Equals ( "System.B" ) ) ;
374+ }
375+
376+ [ Theory ]
377+ [ InlineData ( true ) ]
378+ [ InlineData ( false ) ]
379+ public void TwoPackagesWithNoAssetsReferencePackageWithAssets ( bool dllReference )
380+ {
381+ DependencyContext dependencyContext = BuildDependencyContextFromDependenciesWithResources ( new Dictionary < string , List < string > > ( )
382+ {
383+ { "System.A" , [ "System.B" ] } ,
384+ { "System.C" , [ "System.B" ] } ,
385+ { "System.B" , [ ] }
386+ } , [ "System.B" ] , [ "System.A" , "System.C" ] , dllReference ) ;
387+ Save ( dependencyContext ) ;
388+ dependencyContext . RuntimeLibraries . Count . Should ( ) . Be ( 3 ) ;
389+ dependencyContext . RuntimeLibraries . Should ( ) . Contain ( x => x . Name . Equals ( "System.B" ) ) ;
390+ if ( dependencyContext . RuntimeLibraries . Any ( x => x . Name . Equals ( "System.A" ) ) )
391+ {
392+ dependencyContext . RuntimeLibraries . Should ( ) . NotContain ( x => x . Name . Equals ( "System.C" ) ) ;
393+ }
394+ else
395+ {
396+ dependencyContext . RuntimeLibraries . Should ( ) . Contain ( x => x . Name . Equals ( "System.C" ) ) ;
397+ }
398+ }
399+
216400 private DependencyContext BuildDependencyContextWithReferenceAssemblies ( bool useCompilationOptions )
217401 {
218402 string mainProjectName = "simple.dependencies" ;
0 commit comments