@@ -1973,6 +1973,90 @@ public void InnerBuildsFromNonRootOuterBuildInheritEdgesToOuterBuild()
19731973 }
19741974 }
19751975
1976+ [ Theory ]
1977+ [ InlineData ( null , null ) ]
1978+ [ InlineData ( "OuterTarget" , null ) ]
1979+ [ InlineData ( null , "ExplicitTarget" ) ]
1980+ [ InlineData ( "OuterTarget" , "ExplicitTarget" ) ]
1981+ public void DirectInnerBuildReferenceIsPreservedWhenOuterBuildGeneratesTheSameEdge (
1982+ string outerTargets ,
1983+ string explicitTargets )
1984+ {
1985+ string outerTargetsMetadata = outerTargets is null ? string . Empty : $ " Targets=\" { outerTargets } \" ";
1986+ string explicitTargetsMetadata = explicitTargets is null ? string . Empty : $ " Targets=\" { explicitTargets } \" ";
1987+ string expectedOuterTarget = outerTargets ?? "ChildDefault" ;
1988+ string expectedExplicitTarget = explicitTargets ?? "ChildDefault" ;
1989+ string expectedMergedTargets = outerTargets is null && explicitTargets is null
1990+ ? string . Empty
1991+ : $ "{ expectedExplicitTarget } ;{ expectedOuterTarget } ";
1992+
1993+ TransientTestFile child = _env . CreateFile ( "child.proj" , """
1994+ <Project DefaultTargets="ChildDefault">
1995+ <PropertyGroup>
1996+ <InnerBuildProperty>TargetFramework</InnerBuildProperty>
1997+ <InnerBuildPropertyValues>TargetFrameworks</InnerBuildPropertyValues>
1998+ <TargetFrameworks>net8.0;net9.0</TargetFrameworks>
1999+ </PropertyGroup>
2000+ <Target Name="ChildDefault" />
2001+ <Target Name="OuterTarget" />
2002+ <Target Name="ExplicitTarget" />
2003+ </Project>
2004+ """ ) ;
2005+
2006+ TransientTestFile root = _env . CreateFile ( "root.proj" , $ """
2007+ <Project DefaultTargets="Build">
2008+ <ItemGroup>
2009+ <ProjectReference Include="{ child . Path } "{ outerTargetsMetadata } />
2010+ <ProjectReference Include="{ child . Path } "
2011+ SetTargetFramework="TargetFramework=net8.0"{ explicitTargetsMetadata } />
2012+ <ProjectReferenceTargets Include="Build"
2013+ Targets="{ MSBuildConstants . ProjectReferenceTargetsOrDefaultTargetsMarker } "
2014+ OuterBuild="true" />
2015+ <ProjectReferenceTargets Include="Build"
2016+ Targets="{ MSBuildConstants . ProjectReferenceTargetsOrDefaultTargetsMarker } " />
2017+ </ItemGroup>
2018+ <Target Name="Build" />
2019+ </Project>
2020+ """ ) ;
2021+
2022+ var graph = new ProjectGraph ( root . Path ) ;
2023+
2024+ ProjectGraphNode rootNode = graph . EntryPointNodes . ShouldHaveSingleItem ( ) ;
2025+ ProjectGraphNode outerBuild = graph . ProjectNodes . Single (
2026+ node => node . ProjectInstance . FullPath == child . Path &&
2027+ ! node . ProjectInstance . GlobalProperties . ContainsKey ( "TargetFramework" ) ) ;
2028+ ProjectGraphNode net8Build = graph . ProjectNodes . Single (
2029+ node => node . ProjectInstance . FullPath == child . Path &&
2030+ node . ProjectInstance . GlobalProperties . TryGetValue ( "TargetFramework" , out string targetFramework ) &&
2031+ targetFramework == "net8.0" ) ;
2032+ ProjectGraphNode net9Build = graph . ProjectNodes . Single (
2033+ node => node . ProjectInstance . FullPath == child . Path &&
2034+ node . ProjectInstance . GlobalProperties . TryGetValue ( "TargetFramework" , out string targetFramework ) &&
2035+ targetFramework == "net9.0" ) ;
2036+
2037+ graph . ProjectNodes . Count . ShouldBe ( 4 ) ;
2038+ rootNode . ProjectReferences . Count . ShouldBe ( 3 ) ;
2039+ outerBuild . ProjectReferences . ShouldBe ( [ net8Build , net9Build ] , ignoreOrder : true ) ;
2040+
2041+ ProjectItemInstance edgeToOuterBuild = graph . TestOnly_Edges [ ( rootNode , outerBuild ) ] ;
2042+ ProjectItemInstance edgeToNet8Build = graph . TestOnly_Edges [ ( rootNode , net8Build ) ] ;
2043+ ProjectItemInstance edgeToNet9Build = graph . TestOnly_Edges [ ( rootNode , net9Build ) ] ;
2044+
2045+ edgeToNet8Build . ItemType . ShouldBe ( ItemTypeNames . ProjectReference ) ;
2046+ edgeToNet8Build . GetMetadataValue ( "SetTargetFramework" ) . ShouldBe ( "TargetFramework=net8.0" ) ;
2047+ edgeToNet8Build . GetMetadataValue ( "Targets" ) . ShouldBe ( expectedMergedTargets ) ;
2048+ edgeToNet9Build . ShouldBeSameAs ( edgeToOuterBuild ) ;
2049+
2050+ IReadOnlyDictionary < ProjectGraphNode , ImmutableList < string > > targetLists = graph . GetTargetLists ( [ "Build" ] ) ;
2051+ targetLists [ rootNode ] . ShouldBe ( [ "Build" ] ) ;
2052+ targetLists [ outerBuild ] . ShouldBe ( [ expectedOuterTarget ] ) ;
2053+ targetLists [ net8Build ] . ShouldBe (
2054+ outerTargets is null && explicitTargets is null
2055+ ? [ "ChildDefault" ]
2056+ : [ expectedExplicitTarget , expectedOuterTarget ] ) ;
2057+ targetLists [ net9Build ] . ShouldBe ( [ expectedOuterTarget ] ) ;
2058+ }
2059+
19762060 [ Fact ]
19772061 public void DuplicatedInnerBuildMonikersShouldGetDeduplicated ( )
19782062 {
0 commit comments