diff --git a/eng/build.ps1 b/eng/build.ps1 index fae5fbd127fd0b61983bd3f38a1ea01c07f1482d..7e87fb4177eca74decb1525dfb97f837f7184752 100644 --- a/eng/build.ps1 +++ b/eng/build.ps1 @@ -331,6 +331,9 @@ function SetVisualStudioBootstrapperBuildArgs() { # Core function for running our unit / integration tests tests function TestUsingOptimizedRunner() { + # Capture the Path so we can revert it for integration tests + $originalPath = $env:PATH + # Tests need to locate .NET Core SDK $dotnet = InitializeDotNetCli @@ -417,9 +420,26 @@ function TestUsingOptimizedRunner() { $args += " $dll" } + if ($testVsi) { + # Capture the Environment variables altered by `InitializeDotNetCli` so we can revert to them + $alteredDotNetMultiLevelLookup = $env:DOTNET_MULTILEVEL_LOOKUP + $alteredPath = $env:PATH + + # Resolve runtime, shared framework, or SDK from other locations for integration tests + $env:DOTNET_MULTILEVEL_LOOKUP = $null + $env:PATH = $originalPath + } + try { Exec-Console $runTests $args - } finally { + } + finally { + if ($testVsi) { + # Revert the environment variables to the state `InitializeDotNetCli` left them in + $env:DOTNET_MULTILEVEL_LOOKUP = $alteredDotNetMultiLevelLookup + $env:PATH = $alteredPath + } + Get-Process "xunit*" -ErrorAction SilentlyContinue | Stop-Process if ($testIOperation) { Remove-Item env:\ROSLYN_TEST_IOPERATION diff --git a/src/Features/Core/Portable/AddImport/AbstractAddImportCodeFixProvider.cs b/src/Features/Core/Portable/AddImport/AbstractAddImportCodeFixProvider.cs index 817d1b0efdf15fcb9800f754e25b0f2e869b12b7..f6c358c03d6f111d61cfa56f2417f557f5bce29a 100644 --- a/src/Features/Core/Portable/AddImport/AbstractAddImportCodeFixProvider.cs +++ b/src/Features/Core/Portable/AddImport/AbstractAddImportCodeFixProvider.cs @@ -54,7 +54,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) : null; var installerService = GetPackageInstallerService(document); - var packageSources = searchNuGetPackages && symbolSearchService != null && installerService != null + var packageSources = searchNuGetPackages && symbolSearchService != null && installerService?.IsEnabled(document.Project.Id) == true ? installerService.GetPackageSources() : ImmutableArray.Empty; diff --git a/src/VisualStudio/CSharp/Test/ProjectSystemShim/CPS/AdditionalPropertiesTests.cs b/src/VisualStudio/CSharp/Test/ProjectSystemShim/CPS/AdditionalPropertiesTests.cs index 336189477825d52ad5ec82a5ccb1ee16a99c81dd..7797b9c57e99e2f05d9fc219a89cd52379363be4 100644 --- a/src/VisualStudio/CSharp/Test/ProjectSystemShim/CPS/AdditionalPropertiesTests.cs +++ b/src/VisualStudio/CSharp/Test/ProjectSystemShim/CPS/AdditionalPropertiesTests.cs @@ -40,7 +40,8 @@ static string DefaultNamespaceOfSingleProject(TestEnvironment environment) [InlineData(LanguageVersion.Latest)] [InlineData(LanguageVersion.LatestMajor)] [InlineData(LanguageVersion.Preview)] - public void SetProperty_MaxSupportedLangVersion_CPS(LanguageVersion maxSupportedLangVersion) + [InlineData(null)] + public void SetProperty_MaxSupportedLangVersion_CPS(LanguageVersion? maxSupportedLangVersion) { var catalog = TestEnvironment.s_exportCatalog.Value .WithParts( @@ -56,14 +57,47 @@ public void SetProperty_MaxSupportedLangVersion_CPS(LanguageVersion maxSupported var project = environment.Workspace.CurrentSolution.Projects.Single(); var oldParseOptions = (CSharpParseOptions)project.ParseOptions; - cpsProject.SetProperty(AdditionalPropertyNames.MaxSupportedLangVersion, maxSupportedLangVersion.ToDisplayString()); + cpsProject.SetProperty(AdditionalPropertyNames.MaxSupportedLangVersion, maxSupportedLangVersion?.ToDisplayString()); var canApply = environment.Workspace.CanApplyParseOptionChange( oldParseOptions, oldParseOptions.WithLanguageVersion(attemptedVersion), project); - Assert.Equal(attemptedVersion <= maxSupportedLangVersion, canApply); + if (maxSupportedLangVersion.HasValue) + { + Assert.Equal(attemptedVersion <= maxSupportedLangVersion.Value, canApply); + } + else + { + Assert.True(canApply); + } + } + } + + [WpfFact] + public void SetProperty_MaxSupportedLangVersion_CPS_NotSet() + { + var catalog = TestEnvironment.s_exportCatalog.Value + .WithParts( + typeof(CSharpParseOptionsChangingService)); + + const LanguageVersion attemptedVersion = LanguageVersion.CSharp8; + + var factory = ExportProviderCache.GetOrCreateExportProviderFactory(catalog); + + using (var environment = new TestEnvironment(exportProviderFactory: factory)) + using (var cpsProject = CSharpHelpers.CreateCSharpCPSProject(environment, "Test")) + { + var project = environment.Workspace.CurrentSolution.Projects.Single(); + var oldParseOptions = (CSharpParseOptions)project.ParseOptions; + + var canApply = environment.Workspace.CanApplyParseOptionChange( + oldParseOptions, + oldParseOptions.WithLanguageVersion(attemptedVersion), + project); + + Assert.True(canApply); } } } diff --git a/src/VisualStudio/CSharp/Test/ProjectSystemShim/LegacyProject/CSharpCompilerOptionsTests.cs b/src/VisualStudio/CSharp/Test/ProjectSystemShim/LegacyProject/CSharpCompilerOptionsTests.cs index 6e884ebec16992253ea22b00757979ad82fdf705..2f1f3dcd9ca1cd22b4f26e9935252e487c372990 100644 --- a/src/VisualStudio/CSharp/Test/ProjectSystemShim/LegacyProject/CSharpCompilerOptionsTests.cs +++ b/src/VisualStudio/CSharp/Test/ProjectSystemShim/LegacyProject/CSharpCompilerOptionsTests.cs @@ -4,10 +4,13 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.VisualStudio; using Microsoft.VisualStudio.LanguageServices.CSharp.ProjectSystemShim.Interop; +using Microsoft.VisualStudio.LanguageServices.CSharp.Utilities; using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem; using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.Interop; using Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim.Framework; +using Microsoft.VisualStudio.Shell.Interop; using Roslyn.Test.Utilities; using Xunit; @@ -167,5 +170,80 @@ public void ProjectCompilationOutputsChange() outputs = (CompilationOutputFilesWithImplicitPdbPath)environment.Workspace.GetCompilationOutputs(project.Test_VisualStudioProject.Id); Assert.Equal(@"C:\a\3.dll", outputs.AssemblyFilePath); } + + [WpfTheory] + [InlineData(LanguageVersion.CSharp7_3)] + [InlineData(LanguageVersion.CSharp8)] + [InlineData(LanguageVersion.Latest)] + [InlineData(LanguageVersion.LatestMajor)] + [InlineData(LanguageVersion.Preview)] + [InlineData(null)] + public void SetProperty_MaxSupportedLangVersion(LanguageVersion? maxSupportedLangVersion) + { + var catalog = TestEnvironment.s_exportCatalog.Value + .WithParts( + typeof(CSharpParseOptionsChangingService)); + + var factory = ExportProviderCache.GetOrCreateExportProviderFactory(catalog); + using var environment = new TestEnvironment(exportProviderFactory: factory); + + var hierarchy = environment.CreateHierarchy("CSharpProject", "Bin", projectRefPath: null, projectCapabilities: "CSharp"); + var storage = Assert.IsAssignableFrom(hierarchy); + + Assert.True(ErrorHandler.Succeeded( + storage.SetPropertyValue( + "MaxSupportedLangVersion", null, (uint)_PersistStorageType.PST_PROJECT_FILE, maxSupportedLangVersion?.ToDisplayString()))); + + _ = CSharpHelpers.CreateCSharpProject(environment, "Test", hierarchy); + + var project = environment.Workspace.CurrentSolution.Projects.Single(); + + var oldParseOptions = (CSharpParseOptions)project.ParseOptions; + + const LanguageVersion attemptedVersion = LanguageVersion.CSharp8; + + var canApply = environment.Workspace.CanApplyParseOptionChange( + oldParseOptions, + oldParseOptions.WithLanguageVersion(attemptedVersion), + project); + + if (maxSupportedLangVersion.HasValue) + { + Assert.Equal(attemptedVersion <= maxSupportedLangVersion.Value, canApply); + } + else + { + Assert.True(canApply); + } + } + + [WpfFact] + public void SetProperty_MaxSupportedLangVersion_NotSet() + { + var catalog = TestEnvironment.s_exportCatalog.Value + .WithParts( + typeof(CSharpParseOptionsChangingService)); + + var factory = ExportProviderCache.GetOrCreateExportProviderFactory(catalog); + using var environment = new TestEnvironment(exportProviderFactory: factory); + + var hierarchy = environment.CreateHierarchy("CSharpProject", "Bin", projectRefPath: null, projectCapabilities: "CSharp"); + var storage = Assert.IsAssignableFrom(hierarchy); + + _ = CSharpHelpers.CreateCSharpProject(environment, "Test", hierarchy); + + var project = environment.Workspace.CurrentSolution.Projects.Single(); + + var oldParseOptions = (CSharpParseOptions)project.ParseOptions; + + const LanguageVersion attemptedVersion = LanguageVersion.CSharp8; + + var canApply = environment.Workspace.CanApplyParseOptionChange( + oldParseOptions, + oldParseOptions.WithLanguageVersion(attemptedVersion), + project); + + Assert.True(canApply); + } } } diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/Legacy/AbstractLegacyProject.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/Legacy/AbstractLegacyProject.cs index cb3dcb206137ff56e4de93b0c31f04ba61d0539c..6674c131c9648702e0c9ed82c5b80fd9bda0f09b 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/Legacy/AbstractLegacyProject.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/Legacy/AbstractLegacyProject.cs @@ -101,6 +101,11 @@ internal abstract partial class AbstractLegacyProject : ForegroundThreadAffiniti // (e.g. through a msbuild property) VisualStudioProject.DefaultNamespace = GetRootNamespacePropertyValue(hierarchy); + if (TryGetMaxLangVersionPropertyValue(hierarchy, out var maxLangVer)) + { + VisualStudioProject.MaxLangVersion = maxLangVer; + } + Hierarchy = hierarchy; ConnectHierarchyEvents(); RefreshBinOutputPath(); @@ -391,5 +396,16 @@ private static string GetRootNamespacePropertyValue(IVsHierarchy hierarchy) return null; } + + private static bool TryGetMaxLangVersionPropertyValue(IVsHierarchy hierarchy, out string maxLangVer) + { + if (!(hierarchy is IVsBuildPropertyStorage storage)) + { + maxLangVer = null; + return false; + } + + return ErrorHandler.Succeeded(storage.GetPropertyValue("MaxSupportedLangVersion", null, (uint)_PersistStorageType.PST_PROJECT_FILE, out maxLangVer)); + } } } diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs index 74742fd600764b47bb1258e0d46b924c4ba7d930..e8f9b66560c014509afde808407e21760a7cc711 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs @@ -18,16 +18,16 @@ public CSharpUpgradeProject(VisualStudioInstanceFactory instanceFactory, ITestOu { } - private void InvokeFix() + private void InvokeFix(string version = "latest") { - VisualStudio.Editor.SetText(@" -#error version:latest + VisualStudio.Editor.SetText(@$" +#error version:{version} "); VisualStudio.Editor.Activate(); - VisualStudio.Editor.PlaceCaret("version:latest"); + VisualStudio.Editor.PlaceCaret($"version:{version}"); VisualStudio.Editor.InvokeCodeActionList(); - VisualStudio.Editor.Verify.CodeAction("Upgrade this project to C# language version 'latest'", applyFix: true); + VisualStudio.Editor.Verify.CodeAction($"Upgrade this project to C# language version '{version}'", applyFix: true); } [WpfFact(Skip = "https://github.com/dotnet/roslyn/issues/38301"), Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] @@ -49,10 +49,43 @@ public void LegacyProject_AllConfigurationsUpdated() var project = new ProjectUtils.Project(ProjectName); VisualStudio.SolutionExplorer.CreateSolution(SolutionName); - VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.ClassLibrary, LanguageNames.CSharp); + VisualStudio.SolutionExplorer.AddCustomProject(project, ".csproj", $@" + + + + Debug + x64 + {{F4233BA4-A4CB-498B-BBC1-65A42206B1BA}} + Library + {ProjectName} + {ProjectName} + v4.5 + 7.0 + + + bin\x86\Debug\ + x86 + + + bin\x86\Release\ + x86 + + + bin\x64\Debug\ + x64 + + + bin\x64\Release\ + x64 + + + + +"); + VisualStudio.SolutionExplorer.AddFile(project, "C.cs", open: true); - InvokeFix(); - VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "LangVersion", "latest"); + InvokeFix(version: "7.3"); + VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "LangVersion", "7.3"); } [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] @@ -77,6 +110,7 @@ public void LegacyProject_MultiplePlatforms_AllConfigurationsUpdated() bin\x86\Debug\ x86 + 7.2 bin\x86\Release\ @@ -91,6 +125,7 @@ public void LegacyProject_MultiplePlatforms_AllConfigurationsUpdated() bin\x64\Release\ x64 + 7.1 @@ -99,8 +134,8 @@ public void LegacyProject_MultiplePlatforms_AllConfigurationsUpdated() VisualStudio.SolutionExplorer.AddFile(project, "C.cs", open: true); - InvokeFix(); - VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "LangVersion", "latest"); + InvokeFix(version: "7.3"); + VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "LangVersion", "7.3"); } } } diff --git a/src/VisualStudio/TestUtilities2/ProjectSystemShim/Framework/MockHierarchy.vb b/src/VisualStudio/TestUtilities2/ProjectSystemShim/Framework/MockHierarchy.vb index c78255a4ff477793fc611960d3208ff067295368..9859a1781c7cdd5ae4c13e8f6bb54a7d7a0f0455 100644 --- a/src/VisualStudio/TestUtilities2/ProjectSystemShim/Framework/MockHierarchy.vb +++ b/src/VisualStudio/TestUtilities2/ProjectSystemShim/Framework/MockHierarchy.vb @@ -19,6 +19,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim.Fr Private _projectName As String Private _projectBinPath As String + Private _maxSupportedLangVer As String Private ReadOnly _projectRefPath As String Private ReadOnly _projectCapabilities As String Private ReadOnly _projectMock As Mock(Of EnvDTE.Project) = New Mock(Of EnvDTE.Project)(MockBehavior.Strict) @@ -330,6 +331,9 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim.Fr ElseIf pszPropName = "TargetRefPath" Then pbstrPropValue = _projectRefPath Return VSConstants.S_OK + ElseIf pszPropName = "MaxSupportedLangVersion" Then + pbstrPropValue = _maxSupportedLangVer + Return VSConstants.S_OK End If Throw New NotSupportedException($"{NameOf(MockHierarchy)}.{NameOf(GetPropertyValue)} does not support reading {pszPropName}.") @@ -342,6 +346,9 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim.Fr ElseIf pszPropName = "TargetFileName" Then _projectName = PathUtilities.GetFileName(pszPropValue, includeExtension:=False) Return VSConstants.S_OK + ElseIf pszPropName = "MaxSupportedLangVersion" Then + _maxSupportedLangVer = pszPropValue + Return VSConstants.S_OK End If Throw New NotImplementedException()