From f9296099217a739a840696c6bd0103463dafb0f0 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 18 May 2018 14:32:26 -0700 Subject: [PATCH] Fix bug when multi-TFM project reference is outside OmniSharp's target path When OmniSharp loads a project reference outside the OmniSharp path, it does not attempt to do a full design-time build of the project. Instead, it just uses the MSBuild project evaluation. However, an important code path was being skipped where a target framework is selected in the case that the project has multiple target frameworks. Later, this causes an exception to be thrown because several properties did not evaluate properly. This change ensures that a target framework is selected in this case. --- build.json | 3 +- src/OmniSharp.MSBuild/ProjectLoader.cs | 11 +++-- .../ProjectWithMultiTFMLib/App/App.csproj | 12 +++++ .../ProjectWithMultiTFMLib/App/Program.cs | 12 +++++ .../ProjectWithMultiTFMLib/Lib/Class1.cs | 8 ++++ .../ProjectWithMultiTFMLib/Lib/Lib.csproj | 7 +++ .../ProjectWithMultiTFMLib.sln | 48 +++++++++++++++++++ .../WorkspaceInformationTests.cs | 21 ++++++++ 8 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 test-assets/test-projects/ProjectWithMultiTFMLib/App/App.csproj create mode 100644 test-assets/test-projects/ProjectWithMultiTFMLib/App/Program.cs create mode 100644 test-assets/test-projects/ProjectWithMultiTFMLib/Lib/Class1.cs create mode 100644 test-assets/test-projects/ProjectWithMultiTFMLib/Lib/Lib.csproj create mode 100644 test-assets/test-projects/ProjectWithMultiTFMLib/ProjectWithMultiTFMLib.sln diff --git a/build.json b/build.json index fc36a01308..07d8fc86d0 100644 --- a/build.json +++ b/build.json @@ -37,7 +37,8 @@ "TwoProjectsWithSolution", "ProjectWithGeneratedFile", "CSharpAndFSharp", - "ProjectWithMismatchedFileName" + "ProjectWithMismatchedFileName", + "ProjectWithMultiTFMLib" ], "LegacyTestAssets": [ "LegacyNUnitTestProject", diff --git a/src/OmniSharp.MSBuild/ProjectLoader.cs b/src/OmniSharp.MSBuild/ProjectLoader.cs index 907da5db9c..7857890064 100644 --- a/src/OmniSharp.MSBuild/ProjectLoader.cs +++ b/src/OmniSharp.MSBuild/ProjectLoader.cs @@ -110,7 +110,11 @@ private MSB.Evaluation.Project EvaluateProjectFileCore(string filePath) toolsVersion = GetLegalToolsetVersion(toolsVersion, projectCollection.Toolsets); - return projectCollection.LoadProject(filePath, toolsVersion); + var project = projectCollection.LoadProject(filePath, toolsVersion); + + SetTargetFrameworkIfNeeded(project); + + return project; } private static void SetTargetFrameworkIfNeeded(MSB.Evaluation.Project evaluatedProject) @@ -127,10 +131,7 @@ private static void SetTargetFrameworkIfNeeded(MSB.Evaluation.Project evaluatedP // do better and potentially allow OmniSharp hosts to select a target framework. targetFramework = targetFrameworks[0]; evaluatedProject.SetProperty(PropertyNames.TargetFramework, targetFramework); - } - else if (!string.IsNullOrWhiteSpace(targetFramework) && targetFrameworks.Length == 0) - { - targetFrameworks = ImmutableArray.Create(targetFramework); + evaluatedProject.ReevaluateIfNecessary(); } } diff --git a/test-assets/test-projects/ProjectWithMultiTFMLib/App/App.csproj b/test-assets/test-projects/ProjectWithMultiTFMLib/App/App.csproj new file mode 100644 index 0000000000..5588202a85 --- /dev/null +++ b/test-assets/test-projects/ProjectWithMultiTFMLib/App/App.csproj @@ -0,0 +1,12 @@ + + + + + + + + Exe + netcoreapp1.1 + + + diff --git a/test-assets/test-projects/ProjectWithMultiTFMLib/App/Program.cs b/test-assets/test-projects/ProjectWithMultiTFMLib/App/Program.cs new file mode 100644 index 0000000000..be4278310c --- /dev/null +++ b/test-assets/test-projects/ProjectWithMultiTFMLib/App/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace App +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/test-assets/test-projects/ProjectWithMultiTFMLib/Lib/Class1.cs b/test-assets/test-projects/ProjectWithMultiTFMLib/Lib/Class1.cs new file mode 100644 index 0000000000..44e7c59c4d --- /dev/null +++ b/test-assets/test-projects/ProjectWithMultiTFMLib/Lib/Class1.cs @@ -0,0 +1,8 @@ +using System; + +namespace Lib +{ + public class Class1 + { + } +} diff --git a/test-assets/test-projects/ProjectWithMultiTFMLib/Lib/Lib.csproj b/test-assets/test-projects/ProjectWithMultiTFMLib/Lib/Lib.csproj new file mode 100644 index 0000000000..895941aa5f --- /dev/null +++ b/test-assets/test-projects/ProjectWithMultiTFMLib/Lib/Lib.csproj @@ -0,0 +1,7 @@ + + + + netstandard1.3;netstandard2.0 + + + diff --git a/test-assets/test-projects/ProjectWithMultiTFMLib/ProjectWithMultiTFMLib.sln b/test-assets/test-projects/ProjectWithMultiTFMLib/ProjectWithMultiTFMLib.sln new file mode 100644 index 0000000000..e72e6e9e3b --- /dev/null +++ b/test-assets/test-projects/ProjectWithMultiTFMLib/ProjectWithMultiTFMLib.sln @@ -0,0 +1,48 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "App", "App\App.csproj", "{632DFE45-B56E-4158-8F27-45E2BA0BAFCF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lib", "Lib\Lib.csproj", "{CE41561B-5D13-4688-8686-EEFF744BE8B5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {632DFE45-B56E-4158-8F27-45E2BA0BAFCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {632DFE45-B56E-4158-8F27-45E2BA0BAFCF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {632DFE45-B56E-4158-8F27-45E2BA0BAFCF}.Debug|x64.ActiveCfg = Debug|x64 + {632DFE45-B56E-4158-8F27-45E2BA0BAFCF}.Debug|x64.Build.0 = Debug|x64 + {632DFE45-B56E-4158-8F27-45E2BA0BAFCF}.Debug|x86.ActiveCfg = Debug|x86 + {632DFE45-B56E-4158-8F27-45E2BA0BAFCF}.Debug|x86.Build.0 = Debug|x86 + {632DFE45-B56E-4158-8F27-45E2BA0BAFCF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {632DFE45-B56E-4158-8F27-45E2BA0BAFCF}.Release|Any CPU.Build.0 = Release|Any CPU + {632DFE45-B56E-4158-8F27-45E2BA0BAFCF}.Release|x64.ActiveCfg = Release|x64 + {632DFE45-B56E-4158-8F27-45E2BA0BAFCF}.Release|x64.Build.0 = Release|x64 + {632DFE45-B56E-4158-8F27-45E2BA0BAFCF}.Release|x86.ActiveCfg = Release|x86 + {632DFE45-B56E-4158-8F27-45E2BA0BAFCF}.Release|x86.Build.0 = Release|x86 + {CE41561B-5D13-4688-8686-EEFF744BE8B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE41561B-5D13-4688-8686-EEFF744BE8B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE41561B-5D13-4688-8686-EEFF744BE8B5}.Debug|x64.ActiveCfg = Debug|x64 + {CE41561B-5D13-4688-8686-EEFF744BE8B5}.Debug|x64.Build.0 = Debug|x64 + {CE41561B-5D13-4688-8686-EEFF744BE8B5}.Debug|x86.ActiveCfg = Debug|x86 + {CE41561B-5D13-4688-8686-EEFF744BE8B5}.Debug|x86.Build.0 = Debug|x86 + {CE41561B-5D13-4688-8686-EEFF744BE8B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CE41561B-5D13-4688-8686-EEFF744BE8B5}.Release|Any CPU.Build.0 = Release|Any CPU + {CE41561B-5D13-4688-8686-EEFF744BE8B5}.Release|x64.ActiveCfg = Release|x64 + {CE41561B-5D13-4688-8686-EEFF744BE8B5}.Release|x64.Build.0 = Release|x64 + {CE41561B-5D13-4688-8686-EEFF744BE8B5}.Release|x86.ActiveCfg = Release|x86 + {CE41561B-5D13-4688-8686-EEFF744BE8B5}.Release|x86.Build.0 = Release|x86 + EndGlobalSection +EndGlobal diff --git a/tests/OmniSharp.MSBuild.Tests/WorkspaceInformationTests.cs b/tests/OmniSharp.MSBuild.Tests/WorkspaceInformationTests.cs index 9aea40b238..500f9138cd 100644 --- a/tests/OmniSharp.MSBuild.Tests/WorkspaceInformationTests.cs +++ b/tests/OmniSharp.MSBuild.Tests/WorkspaceInformationTests.cs @@ -141,6 +141,27 @@ public async Task TestProjectWithReferencedProjectOutsideOfOmniSharp() } } + [Fact] + public async Task TestProjectWithMultiTFMReferencedProjectOutsideOfOmniSharp() + { + using (var testProject = await TestAssets.Instance.GetTestProjectAsync("ProjectWithMultiTFMLib")) + using (var host = CreateOmniSharpHost(Path.Combine(testProject.Directory, "App"))) + { + var workspaceInfo = await GetWorkspaceInfoAsync(host); + + Assert.NotNull(workspaceInfo.Projects); + Assert.Equal(2, workspaceInfo.Projects.Count); + + var project1 = workspaceInfo.Projects[0]; + Assert.Equal("App.csproj", Path.GetFileName(project1.Path)); + + var project2 = workspaceInfo.Projects[1]; + Assert.Equal("Lib.csproj", Path.GetFileName(project2.Path)); + Assert.Equal(".NETStandard,Version=v1.3", project2.TargetFramework); + Assert.Equal(2, project2.TargetFrameworks.Count); + } + } + [ConditionalFact(typeof(WindowsOnly))] public async Task AntlrGeneratedFiles() {