@@ -2808,6 +2808,119 @@ public void MultitargettingTargetsWithBuildProjectReferencesFalse()
28082808 }
28092809 }
28102810
2811+ [ Theory ]
2812+ // Built-in targets
2813+ [ InlineData ( new string [ 0 ] , new [ ] { "Project1Default" } , new [ ] { "Project2Default" } ) ]
2814+ [ InlineData ( new [ ] { "Build" } , new [ ] { "Project1Default" } , new [ ] { "Project2Default" } ) ]
2815+ [ InlineData ( new [ ] { "Rebuild" } , new [ ] { "Rebuild" } , new [ ] { "Rebuild" } ) ]
2816+ [ InlineData ( new [ ] { "Clean" } , new [ ] { "Clean" } , new [ ] { "Clean" } ) ]
2817+ [ InlineData ( new [ ] { "Publish" } , new [ ] { "Publish" } , new [ ] { "Publish" } ) ]
2818+ // Traversal targets
2819+ [ InlineData ( new [ ] { "Project1" } , new [ ] { "Project1Default" } , new string [ 0 ] ) ]
2820+ [ InlineData ( new [ ] { "Project2" } , new string [ 0 ] , new [ ] { "Project2Default" } ) ]
2821+ [ InlineData ( new [ ] { "Project1" , "Project2" } , new [ ] { "Project1Default" } , new [ ] { "Project2Default" } ) ]
2822+ [ InlineData ( new [ ] { "Project1:Rebuild" } , new [ ] { "Rebuild" } , new string [ 0 ] ) ]
2823+ [ InlineData ( new [ ] { "Project2:Rebuild" } , new string [ 0 ] , new [ ] { "Rebuild" } ) ]
2824+ [ InlineData ( new [ ] { "Project1:Rebuild" , "Project2:Clean" } , new [ ] { "Rebuild" } , new [ ] { "Clean" } ) ]
2825+ [ InlineData ( new [ ] { "CustomTarget" } , new [ ] { "CustomTarget" } , new [ ] { "CustomTarget" } ) ]
2826+ [ InlineData ( new [ ] { "Project1:CustomTarget" } , new [ ] { "CustomTarget" } , new string [ 0 ] ) ]
2827+ [ InlineData ( new [ ] { "Project2:CustomTarget" } , new string [ 0 ] , new [ ] { "CustomTarget" } ) ]
2828+ [ InlineData ( new [ ] { "Project1:CustomTarget" , "Project2:CustomTarget" } , new [ ] { "CustomTarget" } , new [ ] { "CustomTarget" } ) ]
2829+ public void GetTargetListsWithSolution ( string [ ] entryTargets , string [ ] expectedProject1Targets , string [ ] expectedProject2Targets )
2830+ {
2831+ using ( var env = TestEnvironment . Create ( ) )
2832+ {
2833+ const string ExtraContent = """
2834+ <Target Name="CustomTarget" />
2835+ """ ;
2836+ TransientTestFile project1File = CreateProjectFile ( env : env , projectNumber : 1 , defaultTargets : "Project1Default" , extraContent : ExtraContent ) ;
2837+ TransientTestFile project2File = CreateProjectFile ( env : env , projectNumber : 2 , defaultTargets : "Project2Default" , extraContent : ExtraContent ) ;
2838+
2839+ string solutionFileContents = $$ """
2840+ Microsoft Visual Studio Solution File, Format Version 12.00
2841+ # Visual Studio Version 17
2842+ VisualStudioVersion = 17.0.31903.59
2843+ MinimumVisualStudioVersion = 17.0.31903.59
2844+ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Project1", "{{ project1File . Path }} ", "{8761499A-7280-43C4-A32F-7F41C47CA6DF}"
2845+ EndProject
2846+ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Project2", "{{ project2File . Path }} ", "{2022C11A-1405-4983-BEC2-3A8B0233108F}"
2847+ EndProject
2848+ Global
2849+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
2850+ Debug|x64 = Debug|x64
2851+ Release|x64 = Release|x64
2852+ EndGlobalSection
2853+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
2854+ {8761499A-7280-43C4-A32F-7F41C47CA6DF}.Debug|x64.ActiveCfg = Debug|x64
2855+ {8761499A-7280-43C4-A32F-7F41C47CA6DF}.Debug|x64.Build.0 = Debug|x64
2856+ {8761499A-7280-43C4-A32F-7F41C47CA6DF}.Release|x64.ActiveCfg = Release|x64
2857+ {8761499A-7280-43C4-A32F-7F41C47CA6DF}.Release|x64.Build.0 = Release|x64
2858+ {2022C11A-1405-4983-BEC2-3A8B0233108F}.Debug|x64.ActiveCfg = Debug|x64
2859+ {2022C11A-1405-4983-BEC2-3A8B0233108F}.Debug|x64.Build.0 = Debug|x64
2860+ {2022C11A-1405-4983-BEC2-3A8B0233108F}.Release|x64.ActiveCfg = Release|x64
2861+ {2022C11A-1405-4983-BEC2-3A8B0233108F}.Release|x64.Build.0 = Release|x64
2862+ EndGlobalSection
2863+ GlobalSection(SolutionProperties) = preSolution
2864+ HideSolutionNode = FALSE
2865+ EndGlobalSection
2866+ EndGlobal
2867+ """ ;
2868+ TransientTestFile slnFile = env . CreateFile ( @"Solution.sln" , solutionFileContents ) ;
2869+ SolutionFile solutionFile = SolutionFile . Parse ( slnFile . Path ) ;
2870+
2871+ ProjectGraph projectGraph = new ( slnFile . Path ) ;
2872+ ProjectGraphNode project1Node = GetFirstNodeWithProjectNumber ( projectGraph , 1 ) ;
2873+ ProjectGraphNode project2Node = GetFirstNodeWithProjectNumber ( projectGraph , 2 ) ;
2874+
2875+ IReadOnlyDictionary < ProjectGraphNode , ImmutableList < string > > targetLists = projectGraph . GetTargetLists ( entryTargets ) ;
2876+ targetLists . Count . ShouldBe ( projectGraph . ProjectNodes . Count ) ;
2877+ targetLists [ project1Node ] . ShouldBe ( expectedProject1Targets ) ;
2878+ targetLists [ project2Node ] . ShouldBe ( expectedProject2Targets ) ;
2879+ }
2880+ }
2881+
2882+ [ Theory ]
2883+ [ InlineData ( "Project1:Build" ) ]
2884+ [ InlineData ( "Project1:" ) ]
2885+ public void GetTargetListsWithSolutionInvalidTargets ( string entryTarget )
2886+ {
2887+ using ( var env = TestEnvironment . Create ( ) )
2888+ {
2889+ TransientTestFile project1File = CreateProjectFile ( env : env , projectNumber : 1 ) ;
2890+ string solutionFileContents = $$ """
2891+ Microsoft Visual Studio Solution File, Format Version 12.00
2892+ # Visual Studio Version 17
2893+ VisualStudioVersion = 17.0.31903.59
2894+ MinimumVisualStudioVersion = 17.0.31903.59
2895+ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Project1", "{{ project1File . Path }} ", "{8761499A-7280-43C4-A32F-7F41C47CA6DF}"
2896+ EndProject
2897+ Global
2898+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
2899+ Debug|x64 = Debug|x64
2900+ Release|x64 = Release|x64
2901+ EndGlobalSection
2902+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
2903+ {8761499A-7280-43C4-A32F-7F41C47CA6DF}.Debug|x64.ActiveCfg = Debug|x64
2904+ {8761499A-7280-43C4-A32F-7F41C47CA6DF}.Debug|x64.Build.0 = Debug|x64
2905+ {8761499A-7280-43C4-A32F-7F41C47CA6DF}.Release|x64.ActiveCfg = Release|x64
2906+ {8761499A-7280-43C4-A32F-7F41C47CA6DF}.Release|x64.Build.0 = Release|x64
2907+ EndGlobalSection
2908+ GlobalSection(SolutionProperties) = preSolution
2909+ HideSolutionNode = FALSE
2910+ EndGlobalSection
2911+ EndGlobal
2912+ """ ;
2913+ TransientTestFile slnFile = env . CreateFile ( @"Solution.sln" , solutionFileContents ) ;
2914+ SolutionFile solutionFile = SolutionFile . Parse ( slnFile . Path ) ;
2915+
2916+ ProjectGraph projectGraph = new ( slnFile . Path ) ;
2917+
2918+ var getTargetListsFunc = ( ( ) => projectGraph . GetTargetLists ( [ entryTarget ] ) ) ;
2919+ InvalidProjectFileException exception = getTargetListsFunc . ShouldThrow < InvalidProjectFileException > ( ) ;
2920+ exception . Message . ShouldContain ( $ "The target \" { entryTarget } \" does not exist in the project.") ;
2921+ }
2922+ }
2923+
28112924 public void Dispose ( )
28122925 {
28132926 _env . Dispose ( ) ;
0 commit comments