dotnet / upgrade-assistant

A tool to assist developers in upgrading .NET Framework applications to .NET 6 and beyond
MIT License
1.1k stars 163 forks source link

Nullref in GetAllGlobalPackageReferences #1601

Open dfederm opened 6 days ago

dfederm commented 6 days ago

Does not exist

Describe the bug

I'm getting a NullReferenceException when trying to run the tool on a project.

To Reproduce

upgrade-assistant upgrade "<path>" --operation feature.sdkstyle

Exceptions (if any)

System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.UpgradeAssistant.ProjectRootElementExtensions.GetAllGlobalPackageReferences(ProjectRootElement projectRoot) in
D:\a\_work\1\s\src\msbuild\Extensions\ProjectRootElementExtensions.cs:line 32
   at Microsoft.UpgradeAssistant.Msbuild.Services.Project.ProjectDependenciesSetBuilder.<>c__DisplayClass12_0.<<GetPackages>g__GetPackageReferenceDefinitions|3>d.MoveNext() in
D:\a\_work\1\s\src\msbuild\Services\Project\ProjectDependenciesSetBuilder.cs:line 232
   at System.Linq.Enumerable.<Any>g__WithEnumerator|36_0[TSource](IEnumerable`1 source)
   at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source)
   at Microsoft.UpgradeAssistant.Msbuild.Services.Project.ProjectDependenciesSetBuilder.<>c__DisplayClass12_0.<GetPackages>g__CreatePackage|1(ProjectItem packageReference) in
D:\a\_work\1\s\src\msbuild\Services\Project\ProjectDependenciesSetBuilder.cs:line 198
   at Microsoft.UpgradeAssistant.Msbuild.Services.Project.ProjectDependenciesSetBuilder.GetPackages(Project msbuildProject, IEnumerable`1 imports, String rootFolder, CancellationToken
cancellationToken)+MoveNext() in D:\a\_work\1\s\src\msbuild\Services\Project\ProjectDependenciesSetBuilder.cs:line 159
   at Microsoft.UpgradeAssistant.Services.DependenciesSet.Add(IEnumerable`1 dependencies) in D:\a\_work\1\s\src\engine\Services\Project\Dependencies\DependenciesSet.cs:line 62
   at Microsoft.UpgradeAssistant.Msbuild.Services.Project.ProjectDependenciesSetBuilder.GetDependenciesAsync(Project msbuildProject, String rootPath, CancellationToken cancellationToken) in
D:\a\_work\1\s\src\msbuild\Services\Project\ProjectDependenciesSetBuilder.cs:line 57
   at Microsoft.UpgradeAssistant.Msbuild.Services.Project.ProjectDependenciesSetBuilder.<>c__DisplayClass8_0.<<GetDependenciesAsync>b__0>d.MoveNext() in
D:\a\_work\1\s\src\msbuild\Services\Project\ProjectDependenciesSetBuilder.cs:line 39
--- End of stack trace from previous location ---
   at Microsoft.UpgradeAssistant.Services.DefaultMsbuildProjectAccess.RunAsync[T](Func`3 projectAction) in D:\a\_work\1\s\src\msbuild\Services\Msbuild\DefaultMsbuildProjectAccess.cs:line 46
   at Microsoft.UpgradeAssistant.Msbuild.Services.Project.ProjectDependenciesSetBuilder.GetDependenciesAsync(String projectPath, String rootPath, CancellationToken cancellationToken) in
D:\a\_work\1\s\src\msbuild\Services\Project\ProjectDependenciesSetBuilder.cs:line 37
   at Microsoft.UpgradeAssistant.Cli.Slices.Services.Project.ProjectService.GetDependenciesAsync(ISolution solution, String projectPath, CancellationToken cancellationToken) in
D:\a\_work\1\s\src\cli\Slices\Services\Project\ProjectService.cs:line 362
   at Microsoft.UpgradeAssistant.Cli.Slices.Services.Project.ProjectService.CreateProjectAsync(ISolution solution, String projectPath, CancellationToken cancellationToken) in
D:\a\_work\1\s\src\cli\Slices\Services\Project\ProjectService.cs:line 455
   at Microsoft.UpgradeAssistant.Cli.Slices.Services.Project.ProjectService.GetProjectAsync(ISolution solution, String projectPath, CancellationToken cancellationToken) in
D:\a\_work\1\s\src\cli\Slices\Services\Project\ProjectService.cs:line 432
   at Microsoft.UpgradeAssistant.Cli.Slices.Services.Project.ProjectService.GetProjectByPathAsync(ISolution solution, String projectPath, CancellationToken cancellationToken) in
D:\a\_work\1\s\src\cli\Slices\Services\Project\ProjectService.cs:line 246
   at Microsoft.UpgradeAssistant.Cli.UpgradeHost.GetTraitsAsync(String projectPath, CancellationToken cancellationToken) in D:\a\_work\1\s\src\cli\UpgradeHost.cs:line 120
   at Microsoft.UpgradeAssistant.Cli.Flow.FlowContextExtensions.GetOriginalTraitsAsync(IFlowContext context, String projectPath, IUpgradeHost host, CancellationToken cancellationToken) in
D:\a\_work\1\s\src\cli\Flow\FlowContext.Extensions.cs:line 24
   at Microsoft.UpgradeAssistant.Cli.Flow.Steps.Upgrade.SelectControllerFlowStep.<>c__DisplayClass8_0.<<ValidateUserInputAsync>b__0>d.MoveNext() in
D:\a\_work\1\s\src\cli\Flow\Steps\Upgrade\SelectControllerFlowStep .cs:line 48
--- End of stack trace from previous location ---
   at Spectre.Console.Status.<>c__DisplayClass17_0`1.<<StartAsync>b__0>d.MoveNext() in /_/src/Spectre.Console/Live/Status/Status.cs:line 120
--- End of stack trace from previous location ---
   at Spectre.Console.Progress.<>c__DisplayClass28_0`1.<<StartAsync>b__0>d.MoveNext() in /_/src/Spectre.Console/Live/Progress/Progress.cs:line 133
--- End of stack trace from previous location ---
   at Spectre.Console.Internal.DefaultExclusivityMode.RunAsync[T](Func`1 func) in /_/src/Spectre.Console/Internal/DefaultExclusivityMode.cs:line 40
   at Spectre.Console.Progress.StartAsync[T](Func`2 action) in /_/src/Spectre.Console/Live/Progress/Progress.cs:line 116
   at Spectre.Console.Status.StartAsync[T](String status, Func`2 func) in /_/src/Spectre.Console/Live/Status/Status.cs:line 117
   at Microsoft.UpgradeAssistant.Cli.Flow.Steps.Upgrade.SelectControllerFlowStep.ValidateUserInputAsync(IFlowContext context, CancellationToken cancellationToken) in
D:\a\_work\1\s\src\cli\Flow\Steps\Upgrade\SelectControllerFlowStep .cs:line 42
   at Spectre.Console.Flow.FlowRunner.RunAsync(CancellationToken cancellationToken) in D:\a\_work\1\s\src\spectre.flow\Flow\FlowRunner.cs:line 83
dfederm commented 6 days ago

Upon inspection, the nullref is when looking for the CPM file. It's look for it as a "local" import, but the root path is the dir the project is in, not the repo root. Thus it's not finding the CPM file under that root and a null flows downstream and throws.

dfederm commented 6 days ago

Looks like it's picking up that root path because there happens to be a sln there. So there's a bad assumption here that the sln file is at the repo root.

dfederm commented 6 days ago

Workaround: Delete all slns in the repo and if required generate a new one at the repo root which contains all projects.

Would be great if the filtering could use what MSBuild actually uses for CPM ("look up the parent directory until I find one") instead of assuming some specific solution structure.