From 8c35eafd73045bb9f0210afe05903ab03005d04a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 1 Apr 2018 16:40:54 +0200 Subject: [PATCH 01/45] Allowing ChangeCompilationOptions in VisualStudioWorkspace --- .../VisualStudioWorkspaceImpl.cs | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs index 8b9636cb13acb..a8b7c7017ecb4 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs @@ -9,6 +9,7 @@ using System.Threading; using EnvDTE; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Host; @@ -241,6 +242,7 @@ public override bool CanApplyChange(ApplyChangesKind feature) case ApplyChangesKind.AddAdditionalDocument: case ApplyChangesKind.RemoveAdditionalDocument: case ApplyChangesKind.ChangeAdditionalDocument: + case ApplyChangesKind.ChangeCompilationOptions: case ApplyChangesKind.ChangeParseOptions: return true; @@ -302,6 +304,36 @@ private string GetAnalyzerPath(AnalyzerReference analyzerReference) return analyzerReference.FullPath; } + protected override void ApplyCompilationOptionsChanged(ProjectId projectId, CompilationOptions options) + { + if (projectId == null) + { + throw new ArgumentNullException(nameof(projectId)); + } + + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + + GetProjectData(projectId, out var hostProject, out var hierarchy, out var project); + foreach (string configurationName in (object[])project.ConfigurationManager.ConfigurationRowNames) + { + switch (hostProject.Language) + { + case LanguageNames.CSharp: + var csharpProperties = (VSLangProj80.CSharpProjectConfigurationProperties3)project.ConfigurationManager + .ConfigurationRow(configurationName).Item(1).Object; + + csharpProperties.AllowUnsafeBlocks = ((CSharpCompilationOptions)options).AllowUnsafe; + break; + + case LanguageNames.VisualBasic: + throw new InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_parse_options); + } + } + } + protected override void ApplyParseOptionsChanged(ProjectId projectId, ParseOptions options) { if (projectId == null) @@ -316,7 +348,7 @@ protected override void ApplyParseOptionsChanged(ProjectId projectId, ParseOptio var parseOptionsService = CurrentSolution.GetProject(projectId).LanguageServices.GetService(); Contract.ThrowIfNull(parseOptionsService, nameof(parseOptionsService)); - + string newVersion = parseOptionsService.GetLanguageVersion(options); GetProjectData(projectId, out var hostProject, out var hierarchy, out var project); From 5f8c43d4f6cae723ef66e83e360640947b43f8d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 1 Apr 2018 16:52:46 +0200 Subject: [PATCH 02/45] This_workspace_does_not_support_updating_Visual_Basic_compilation_options --- .../ProjectSystem/VisualStudioWorkspaceImpl.cs | 2 +- .../Core/Def/ServicesVSResources.Designer.cs | 9 +++++++++ src/VisualStudio/Core/Def/ServicesVSResources.resx | 3 +++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf | 5 +++++ .../Core/Def/xlf/ServicesVSResources.pt-BR.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf | 5 +++++ .../Core/Def/xlf/ServicesVSResources.zh-Hans.xlf | 5 +++++ .../Core/Def/xlf/ServicesVSResources.zh-Hant.xlf | 5 +++++ 16 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs index a8b7c7017ecb4..d508ce51d9ac6 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs @@ -329,7 +329,7 @@ protected override void ApplyCompilationOptionsChanged(ProjectId projectId, Comp break; case LanguageNames.VisualBasic: - throw new InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_parse_options); + throw new InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_compilation_options); } } } diff --git a/src/VisualStudio/Core/Def/ServicesVSResources.Designer.cs b/src/VisualStudio/Core/Def/ServicesVSResources.Designer.cs index 21c15fe2aee4e..bfc49077a5dc6 100644 --- a/src/VisualStudio/Core/Def/ServicesVSResources.Designer.cs +++ b/src/VisualStudio/Core/Def/ServicesVSResources.Designer.cs @@ -2423,6 +2423,15 @@ internal static string This_item_cannot_be_deleted_because_it_is_used_by_an_exis } } + /// + /// Looks up a localized string similar to This workspace does not support updating Visual Basic compilation options.. + /// + internal static string This_workspace_does_not_support_updating_Visual_Basic_compilation_options { + get { + return ResourceManager.GetString("This_workspace_does_not_support_updating_Visual_Basic_compilation_options", resourceCulture); + } + } + /// /// Looks up a localized string similar to This workspace does not support updating Visual Basic parse options.. /// diff --git a/src/VisualStudio/Core/Def/ServicesVSResources.resx b/src/VisualStudio/Core/Def/ServicesVSResources.resx index b2b4fb2893558..f8978145cda53 100644 --- a/src/VisualStudio/Core/Def/ServicesVSResources.resx +++ b/src/VisualStudio/Core/Def/ServicesVSResources.resx @@ -504,6 +504,9 @@ Use the dropdown to view and switch to other projects this file may belong to. This workspace only supports opening documents on the UI thread. + + This workspace does not support updating Visual Basic compilation options. + This workspace does not support updating Visual Basic parse options. diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf index 2e4b92354aa1e..95768a9d710bb 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf @@ -1528,6 +1528,11 @@ Souhlasím se všemi výše uvedenými podmínkami: Live code analysis + + This workspace does not support updating Visual Basic compilation options. + This workspace does not support updating Visual Basic compilation options. + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf index ea54e4c736db9..dbd2a5a5cd1dd 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf @@ -1528,6 +1528,11 @@ Ich stimme allen vorstehenden Bedingungen zu: Live code analysis + + This workspace does not support updating Visual Basic compilation options. + This workspace does not support updating Visual Basic compilation options. + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf index 18a458a63bbbc..84737671692e3 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf @@ -1528,6 +1528,11 @@ Estoy de acuerdo con todo lo anterior: Live code analysis + + This workspace does not support updating Visual Basic compilation options. + This workspace does not support updating Visual Basic compilation options. + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf index 30ec28635560c..8d63a7c65f9df 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf @@ -1528,6 +1528,11 @@ Je suis d'accord avec tout ce qui précède : Live code analysis + + This workspace does not support updating Visual Basic compilation options. + This workspace does not support updating Visual Basic compilation options. + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf index ca0135c82e060..62fda58b33f99 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf @@ -1528,6 +1528,11 @@ L'utente accetta le condizioni sopra riportate: Live code analysis + + This workspace does not support updating Visual Basic compilation options. + This workspace does not support updating Visual Basic compilation options. + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf index 473797fe1fa6f..52bf174260044 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf @@ -1528,6 +1528,11 @@ I agree to all of the foregoing: Live code analysis + + This workspace does not support updating Visual Basic compilation options. + This workspace does not support updating Visual Basic compilation options. + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf index 094930c1d3655..b7f4884198ce6 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf @@ -1528,6 +1528,11 @@ I agree to all of the foregoing: Live code analysis + + This workspace does not support updating Visual Basic compilation options. + This workspace does not support updating Visual Basic compilation options. + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf index eb5b4ea265fa1..4c987f8499dec 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf @@ -1528,6 +1528,11 @@ Wyrażam zgodę na wszystkie następujące postanowienia: Live code analysis + + This workspace does not support updating Visual Basic compilation options. + This workspace does not support updating Visual Basic compilation options. + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf index b831bd18c074f..0bbdac7c84de7 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf @@ -1528,6 +1528,11 @@ Eu concordo com todo o conteúdo supracitado: Live code analysis + + This workspace does not support updating Visual Basic compilation options. + This workspace does not support updating Visual Basic compilation options. + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf index be852a5d97428..cc4ef2435d789 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf @@ -1528,6 +1528,11 @@ I agree to all of the foregoing: Live code analysis + + This workspace does not support updating Visual Basic compilation options. + This workspace does not support updating Visual Basic compilation options. + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf index 6cabbf969344f..88befb0bff47e 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf @@ -1528,6 +1528,11 @@ Aşağıdakilerin tümünü onaylıyorum: Live code analysis + + This workspace does not support updating Visual Basic compilation options. + This workspace does not support updating Visual Basic compilation options. + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf index 23ce2eae415b0..501c277576bac 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf @@ -1528,6 +1528,11 @@ I agree to all of the foregoing: Live code analysis + + This workspace does not support updating Visual Basic compilation options. + This workspace does not support updating Visual Basic compilation options. + + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf index 48d6cb7f7bc44..f2808af1672f8 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf @@ -1528,6 +1528,11 @@ I agree to all of the foregoing: Live code analysis + + This workspace does not support updating Visual Basic compilation options. + This workspace does not support updating Visual Basic compilation options. + + \ No newline at end of file From 6db55aa9c4b755ba783477083352beb508dd18db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 1 Apr 2018 18:55:45 +0200 Subject: [PATCH 03/45] CanApplyCompilationOptionChange --- .../ProjectSystem/VisualStudioWorkspaceImpl.cs | 11 +++++++++++ src/Workspaces/Core/Portable/PublicAPI.Unshipped.txt | 1 + src/Workspaces/Core/Portable/Workspace/Workspace.cs | 7 ++++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs index d508ce51d9ac6..1c89da585e907 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs @@ -206,6 +206,17 @@ internal bool IsCPSProject(CodeAnalysis.Project project) return false; } + protected override bool CanApplyCompilationOptionChange(CompilationOptions oldOptions, CompilationOptions newOptions, CodeAnalysis.Project project) + { + if (!(oldOptions is CSharpCompilationOptions oldCSharpOptions)) + { + return false; + } + + // Currently, only changes to AllowUnsafe of C# compilation options are supported. + return oldCSharpOptions.WithAllowUnsafe(((CSharpCompilationOptions)newOptions).AllowUnsafe) == newOptions; + } + protected override bool CanApplyParseOptionChange(ParseOptions oldOptions, ParseOptions newOptions, CodeAnalysis.Project project) { var parseOptionsService = project.LanguageServices.GetService(); diff --git a/src/Workspaces/Core/Portable/PublicAPI.Unshipped.txt b/src/Workspaces/Core/Portable/PublicAPI.Unshipped.txt index 523b172ac0b21..7577223867e08 100644 --- a/src/Workspaces/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Workspaces/Core/Portable/PublicAPI.Unshipped.txt @@ -17,3 +17,4 @@ const Microsoft.CodeAnalysis.Classification.ClassificationTypeNames.ParameterNam const Microsoft.CodeAnalysis.Classification.ClassificationTypeNames.PropertyName = "property name" -> string static Microsoft.CodeAnalysis.ProjectInfo.Create(Microsoft.CodeAnalysis.ProjectId id, Microsoft.CodeAnalysis.VersionStamp version, string name, string assemblyName, string language, string filePath = null, string outputFilePath = null, Microsoft.CodeAnalysis.CompilationOptions compilationOptions = null, Microsoft.CodeAnalysis.ParseOptions parseOptions = null, System.Collections.Generic.IEnumerable documents = null, System.Collections.Generic.IEnumerable projectReferences = null, System.Collections.Generic.IEnumerable metadataReferences = null, System.Collections.Generic.IEnumerable analyzerReferences = null, System.Collections.Generic.IEnumerable additionalDocuments = null, bool isSubmission = false, System.Type hostObjectType = null, string outputRefFilePath = null) -> Microsoft.CodeAnalysis.ProjectInfo static Microsoft.CodeAnalysis.ProjectInfo.Create(Microsoft.CodeAnalysis.ProjectId id, Microsoft.CodeAnalysis.VersionStamp version, string name, string assemblyName, string language, string filePath, string outputFilePath, Microsoft.CodeAnalysis.CompilationOptions compilationOptions, Microsoft.CodeAnalysis.ParseOptions parseOptions, System.Collections.Generic.IEnumerable documents, System.Collections.Generic.IEnumerable projectReferences, System.Collections.Generic.IEnumerable metadataReferences, System.Collections.Generic.IEnumerable analyzerReferences, System.Collections.Generic.IEnumerable additionalDocuments, bool isSubmission, System.Type hostObjectType) -> Microsoft.CodeAnalysis.ProjectInfo +virtual Microsoft.CodeAnalysis.Workspace.CanApplyCompilationOptionChange(Microsoft.CodeAnalysis.CompilationOptions oldOptions, Microsoft.CodeAnalysis.CompilationOptions newOptions, Microsoft.CodeAnalysis.Project project) -> bool diff --git a/src/Workspaces/Core/Portable/Workspace/Workspace.cs b/src/Workspaces/Core/Portable/Workspace/Workspace.cs index c9e15aea99529..a43d2feb1c311 100644 --- a/src/Workspaces/Core/Portable/Workspace/Workspace.cs +++ b/src/Workspaces/Core/Portable/Workspace/Workspace.cs @@ -1181,7 +1181,9 @@ private void CheckAllowedSolutionChanges(SolutionChanges solutionChanges) private void CheckAllowedProjectChanges(ProjectChanges projectChanges) { if (projectChanges.OldProject.CompilationOptions != projectChanges.NewProject.CompilationOptions - && !this.CanApplyChange(ApplyChangesKind.ChangeCompilationOptions)) + && !this.CanApplyChange(ApplyChangesKind.ChangeCompilationOptions) + && !this.CanApplyCompilationOptionChange( + projectChanges.OldProject.CompilationOptions, projectChanges.NewProject.CompilationOptions, projectChanges.NewProject)) { throw new NotSupportedException(WorkspacesResources.Changing_compilation_options_is_not_supported); } @@ -1262,6 +1264,9 @@ private void CheckAllowedProjectChanges(ProjectChanges projectChanges) } } + protected virtual bool CanApplyCompilationOptionChange(CompilationOptions oldOptions, CompilationOptions newOptions, Project project) + => false; + protected virtual bool CanApplyParseOptionChange(ParseOptions oldOptions, ParseOptions newOptions, Project project) => false; From ad483315058678ad509499c483987f0ce8d79499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 1 Apr 2018 21:37:16 +0200 Subject: [PATCH 04/45] Adding AllowUnsafe option to TestWorkspace --- .../Workspaces/TestWorkspace_Create.cs | 1 + .../Workspaces/TestWorkspace_XmlConsumption.cs | 14 +++++++++++++- .../Workspaces/TestWorkspace_XmlCreation.cs | 7 ++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_Create.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_Create.cs index 61f7c08292750..740937cda19ec 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_Create.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_Create.cs @@ -59,6 +59,7 @@ public partial class TestWorkspace private const string AliasAttributeName = "Alias"; private const string ProjectNameAttribute = "Name"; private const string CheckOverflowAttributeName = "CheckOverflow"; + private const string AllowUnsafeAttributeName = "AllowUnsafe"; /// /// Creates a single buffer in a workspace. diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs index f9d9f44ad2cb6..31ed16d4237db 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs @@ -466,6 +466,7 @@ private static CompilationOptions CreateCompilationOptions(TestWorkspace workspa var strongNameProvider = default(StrongNameProvider); var delaySign = default(bool?); var checkOverflow = false; + bool allowUnsafe = false; if (compilationOptionsElement != null) { @@ -483,6 +484,12 @@ private static CompilationOptions CreateCompilationOptions(TestWorkspace workspa checkOverflow = (bool)checkOverflowAttribute; } + var allowUnsafeAttribute = compilationOptionsElement.Attribute(AllowUnsafeAttributeName); + if (allowUnsafeAttribute != null) + { + allowUnsafe = (bool)allowUnsafeAttribute; + } + var reportDiagnosticAttribute = compilationOptionsElement.Attribute(ReportDiagnosticAttributeName); if (reportDiagnosticAttribute != null) { @@ -529,7 +536,7 @@ private static CompilationOptions CreateCompilationOptions(TestWorkspace workspa // VB needs Compilation.ParseOptions set (we do the same at the VS layer) return language == LanguageNames.CSharp - ? (CompilationOptions)new CSharpCompilationOptions(OutputKind.WindowsRuntimeMetadata) + ? (CompilationOptions)new CSharpCompilationOptions(OutputKind.WindowsRuntimeMetadata, allowUnsafe: allowUnsafe) : new VisualBasicCompilationOptions(OutputKind.WindowsRuntimeMetadata).WithGlobalImports(globalImports).WithRootNamespace(rootNamespace) .WithParseOptions((VisualBasicParseOptions)parseOptions ?? VisualBasicParseOptions.Default); } @@ -557,6 +564,11 @@ private static CompilationOptions CreateCompilationOptions(TestWorkspace workspa .WithDelaySign(delaySign) .WithOverflowChecks(checkOverflow); + if (language == LanguageNames.CSharp) + { + compilationOptions = ((CSharpCompilationOptions)compilationOptions).WithAllowUnsafe(allowUnsafe); + } + if (language == LanguageNames.VisualBasic) { // VB needs Compilation.ParseOptions set (we do the same at the VS layer) diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs index 2d4a69bfb5260..fc558611a74a7 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs @@ -77,7 +77,12 @@ private static XAttribute CreateDocumentationModeAttribute(ParseOptions parseOpt private static XElement CreateCompilationOptionsElement(CompilationOptions options) { XElement element = null; - if (options is Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilationOptions vbOptions) + if (options is Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions csOptions) + { + element = new XElement(CompilationOptionsElementName); + element.SetAttributeValue(AllowUnsafeAttributeName, csOptions.AllowUnsafe); + } + else if (options is Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilationOptions vbOptions) { element = new XElement(CompilationOptionsElementName, vbOptions.GlobalImports.AsEnumerable().Select(i => new XElement(GlobalImportElementName, i.Name))); From 8cdfeda98afb7576c06c38784c8f39cdaaa71246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 1 Apr 2018 21:41:58 +0200 Subject: [PATCH 05/45] Simplifying CreateCompilationOptionsElement --- .../Workspaces/TestWorkspace_XmlCreation.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs index fc558611a74a7..8b2994041b90b 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs @@ -76,16 +76,15 @@ private static XAttribute CreateDocumentationModeAttribute(ParseOptions parseOpt private static XElement CreateCompilationOptionsElement(CompilationOptions options) { - XElement element = null; - if (options is Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions csOptions) + var element = new XElement(CompilationOptionsElementName); + + if (options is CodeAnalysis.CSharp.CSharpCompilationOptions csOptions) { - element = new XElement(CompilationOptionsElementName); element.SetAttributeValue(AllowUnsafeAttributeName, csOptions.AllowUnsafe); } - else if (options is Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilationOptions vbOptions) + else if (options is CodeAnalysis.VisualBasic.VisualBasicCompilationOptions vbOptions) { - element = new XElement(CompilationOptionsElementName, - vbOptions.GlobalImports.AsEnumerable().Select(i => new XElement(GlobalImportElementName, i.Name))); + element.Add(vbOptions.GlobalImports.AsEnumerable().Select(i => new XElement(GlobalImportElementName, i.Name))); if (vbOptions.RootNamespace != null) { @@ -95,7 +94,6 @@ private static XElement CreateCompilationOptionsElement(CompilationOptions optio if (options.CheckOverflow) { - element = element ?? new XElement(CompilationOptionsElementName); element.SetAttributeValue(CheckOverflowAttributeName, true); } From dbfbdbee9c3ebfe0c8a20be065c9c6f0d422f91a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 1 Apr 2018 21:59:05 +0200 Subject: [PATCH 06/45] Adding tests + implementation --- .../UnsafeProject/UnsafeProjectTests.cs | 111 ++++++++++++++++++ .../CSharpUnsafeProjectCodeFixProvider.cs | 34 ++++++ src/Test/Utilities/Portable/Traits/Traits.cs | 1 + 3 files changed, 146 insertions(+) create mode 100644 src/EditorFeatures/CSharpTest/Diagnostics/UnsafeProject/UnsafeProjectTests.cs create mode 100644 src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/UnsafeProject/UnsafeProjectTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/UnsafeProject/UnsafeProjectTests.cs new file mode 100644 index 0000000000000..ee45c35c951e5 --- /dev/null +++ b/src/EditorFeatures/CSharpTest/Diagnostics/UnsafeProject/UnsafeProjectTests.cs @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Linq; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.UnsafeProject; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.UnsafeProject +{ + [Trait(Traits.Feature, Traits.Features.CodeActionsUnsafeProject)] + public class UnsafeProjectTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest + { + internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace) + => (null, new CSharpUnsafeProjectCodeFixProvider()); + + private async Task TestAllowUnsafeEnabledIfDisabledAsync(string initialMarkup) + { + var parameters = new TestParameters(); + using (var workspace = CreateWorkspaceFromOptions(initialMarkup, parameters)) + { + var actions = await GetCodeActionsAsync(workspace, parameters); + var operations = await VerifyInputsAndGetOperationsAsync(0, actions, priority: null); + + var appliedChanges = ApplyOperationsAndGetSolution(workspace, operations); + var oldSolution = appliedChanges.Item1; + var newSolution = appliedChanges.Item2; + Assert.True(((CSharpCompilationOptions)newSolution.Projects.Single().CompilationOptions).AllowUnsafe); + } + + // no action offered if unsafe was already enabled + await TestMissingAsync(initialMarkup, new TestParameters(compilationOptions: + new CSharpCompilationOptions(outputKind: default, allowUnsafe: true))); + } + + [Fact] + public async Task OnUnsafeClass() + { + await TestAllowUnsafeEnabledIfDisabledAsync( +@" +unsafe class [|C|] // The compiler reports this on the name, not the 'unsafe' keyword. +{ +}"); + } + + [Fact] + public async Task OnUnsafeMethod() + { + await TestAllowUnsafeEnabledIfDisabledAsync( +@" +class C +{ + unsafe void [|M|]() + { + } +}"); + } + + [Fact] + public async Task OnUnsafeLocalFunction() + { + await TestAllowUnsafeEnabledIfDisabledAsync( +@" +class C +{ + void M() + { + unsafe void [|Function|]() + { + } + } +}"); + } + + [Fact] + public async Task OnUnsafeBlock() + { + await TestAllowUnsafeEnabledIfDisabledAsync( +@" +class C +{ + void M() + { + [|unsafe|] + { + } + } +}"); + } + + [Fact] + public async Task NotInsideUnsafeBlock() + { + await TestMissingAsync( +@" +class C +{ + void M() + { + unsafe + { + [|int * p;|] + } + } +}"); + } + } +} diff --git a/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs b/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs new file mode 100644 index 0000000000000..6afaad0a5e3dd --- /dev/null +++ b/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using System.Composition; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.UpgradeProject; + +namespace Microsoft.CodeAnalysis.CSharp.UnsafeProject +{ + [ExportCodeFixProvider(LanguageNames.CSharp), Shared] + internal class CSharpUnsafeProjectCodeFixProvider : CodeFixProvider + { + private const string CS0227 = nameof(CS0227); // error CS0227: Unsafe code may only appear if compiling with /unsafe + + public override ImmutableArray FixableDiagnosticIds { get; } = + ImmutableArray.Create(CS0227); + + private string UnsafeThisProjectResource => "Allow unsafe code in this project"; + + public override Task RegisterCodeFixesAsync(CodeFixContext context) + { + context.RegisterCodeFix(new ParseOptionsChangeAction(UnsafeThisProjectResource, _ => + Task.FromResult(AllowUnsafeOnProject(context.Document.Project))), context.Diagnostics); + return Task.CompletedTask; + } + + private static Solution AllowUnsafeOnProject(Project project) + { + var compilationOptions = (CSharpCompilationOptions)project.CompilationOptions; + return project.Solution.WithProjectCompilationOptions(project.Id, compilationOptions.WithAllowUnsafe(true)); + } + } +} diff --git a/src/Test/Utilities/Portable/Traits/Traits.cs b/src/Test/Utilities/Portable/Traits/Traits.cs index e11b659c1ab56..1a36667fa3668 100644 --- a/src/Test/Utilities/Portable/Traits/Traits.cs +++ b/src/Test/Utilities/Portable/Traits/Traits.cs @@ -33,6 +33,7 @@ public static class Features public const string CodeActionsAddConstructorParametersFromMembers = "CodeActions.AddConstructorParametersFromMembers"; public const string CodeActionsAddDocCommentNodes = "CodeActions.AddDocCommentParamNodes"; public const string CodeActionsAddAwait = "CodeActions.AddAwait"; + public const string CodeActionsUnsafeProject = "CodeActions.UnsafeProject"; public const string CodeActionsUpgradeProject = "CodeActions.UpgradeProject"; public const string CodeActionsAddAccessibilityModifiers = "CodeActions.AddAccessibilityModifiers"; public const string CodeActionsAddBraces = "CodeActions.AddBraces"; From 61001fb1ef731c2821e58acdcae5c5a648e6f247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 1 Apr 2018 23:39:38 +0200 Subject: [PATCH 07/45] Renaming ParseOptionsChangeAction --- .../UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs | 2 +- .../AbstractUpgradeProjectCodeFixProvider.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs b/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs index 6afaad0a5e3dd..f5945e2501b2e 100644 --- a/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs @@ -20,7 +20,7 @@ internal class CSharpUnsafeProjectCodeFixProvider : CodeFixProvider public override Task RegisterCodeFixesAsync(CodeFixContext context) { - context.RegisterCodeFix(new ParseOptionsChangeAction(UnsafeThisProjectResource, _ => + context.RegisterCodeFix(new ProjectOptionsChangeAction(UnsafeThisProjectResource, _ => Task.FromResult(AllowUnsafeOnProject(context.Document.Project))), context.Diagnostics); return Task.CompletedTask; } diff --git a/src/Features/Core/Portable/UpgradeProject/AbstractUpgradeProjectCodeFixProvider.cs b/src/Features/Core/Portable/UpgradeProject/AbstractUpgradeProjectCodeFixProvider.cs index 76dd84b9e8166..6ee531f71f4cd 100644 --- a/src/Features/Core/Portable/UpgradeProject/AbstractUpgradeProjectCodeFixProvider.cs +++ b/src/Features/Core/Portable/UpgradeProject/AbstractUpgradeProjectCodeFixProvider.cs @@ -43,7 +43,7 @@ protected ImmutableArray GetUpgradeProjectCodeActionsAsync(CodeFixCo var language = project.Language; var fixOneProjectTitle = string.Format(UpgradeThisProjectResource, newVersion); - var fixOneProject = new ParseOptionsChangeAction(fixOneProjectTitle, + var fixOneProject = new ProjectOptionsChangeAction(fixOneProjectTitle, _ => Task.FromResult(UpgradeProject(project, newVersion))); result.Add(fixOneProject); @@ -51,7 +51,7 @@ protected ImmutableArray GetUpgradeProjectCodeActionsAsync(CodeFixCo { var fixAllProjectsTitle = string.Format(UpgradeAllProjectsResource, newVersion); - var fixAllProjects = new ParseOptionsChangeAction(fixAllProjectsTitle, + var fixAllProjects = new ProjectOptionsChangeAction(fixAllProjectsTitle, ct => Task.FromResult(UpgradeAllProjects(solution, language, newVersion, ct))); result.Add(fixAllProjects); @@ -83,9 +83,9 @@ private bool CanUpgrade(Project project, string language, string version) } } - internal class ParseOptionsChangeAction : SolutionChangeAction + internal class ProjectOptionsChangeAction : SolutionChangeAction { - public ParseOptionsChangeAction(string title, Func> createChangedSolution) + public ProjectOptionsChangeAction(string title, Func> createChangedSolution) : base(title, createChangedSolution, equivalenceKey: null) { } From cbd1e91fece88806a0b6c3ca0a8e9bb07e329697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 1 Apr 2018 23:58:05 +0200 Subject: [PATCH 08/45] Localization --- .../CSharpFeaturesResources.Designer.cs | 20 ++++++++++++++++++- .../Portable/CSharpFeaturesResources.resx | 3 +++ .../CSharpUnsafeProjectCodeFixProvider.cs | 6 ++---- .../xlf/CSharpFeaturesResources.cs.xlf | 5 +++++ .../xlf/CSharpFeaturesResources.de.xlf | 5 +++++ .../xlf/CSharpFeaturesResources.es.xlf | 5 +++++ .../xlf/CSharpFeaturesResources.fr.xlf | 5 +++++ .../xlf/CSharpFeaturesResources.it.xlf | 5 +++++ .../xlf/CSharpFeaturesResources.ja.xlf | 5 +++++ .../xlf/CSharpFeaturesResources.ko.xlf | 5 +++++ .../xlf/CSharpFeaturesResources.pl.xlf | 5 +++++ .../xlf/CSharpFeaturesResources.pt-BR.xlf | 5 +++++ .../xlf/CSharpFeaturesResources.ru.xlf | 5 +++++ .../xlf/CSharpFeaturesResources.tr.xlf | 5 +++++ .../xlf/CSharpFeaturesResources.zh-Hans.xlf | 5 +++++ .../xlf/CSharpFeaturesResources.zh-Hant.xlf | 5 +++++ 16 files changed, 89 insertions(+), 5 deletions(-) diff --git a/src/Features/CSharp/Portable/CSharpFeaturesResources.Designer.cs b/src/Features/CSharp/Portable/CSharpFeaturesResources.Designer.cs index 9b76552edcf1f..4a16682c7d23c 100644 --- a/src/Features/CSharp/Portable/CSharpFeaturesResources.Designer.cs +++ b/src/Features/CSharp/Portable/CSharpFeaturesResources.Designer.cs @@ -88,6 +88,15 @@ internal static string Add_this { } } + /// + /// Looks up a localized string similar to Allow unsafe code in this project. + /// + internal static string Allow_unsafe_code_in_this_project { + get { + return ResourceManager.GetString("Allow_unsafe_code_in_this_project", resourceCulture); + } + } + /// /// Looks up a localized string similar to anonymous method. /// @@ -548,7 +557,16 @@ internal static string Invalid_selection { } } - /// + /// + /// Looks up a localized string similar to Invert if statement. + /// + internal static string Invert_if_statement { + get { + return ResourceManager.GetString("Invert_if_statement", resourceCulture); + } + } + + /// /// Looks up a localized string similar to is pattern. /// internal static string is_pattern { diff --git a/src/Features/CSharp/Portable/CSharpFeaturesResources.resx b/src/Features/CSharp/Portable/CSharpFeaturesResources.resx index 33729d573f118..74971f5f76f6c 100644 --- a/src/Features/CSharp/Portable/CSharpFeaturesResources.resx +++ b/src/Features/CSharp/Portable/CSharpFeaturesResources.resx @@ -524,4 +524,7 @@ Convert 'for' to 'foreach' + + Allow unsafe code in this project + \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs b/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs index f5945e2501b2e..af4573c76ce38 100644 --- a/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs @@ -16,12 +16,10 @@ internal class CSharpUnsafeProjectCodeFixProvider : CodeFixProvider public override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(CS0227); - private string UnsafeThisProjectResource => "Allow unsafe code in this project"; - public override Task RegisterCodeFixesAsync(CodeFixContext context) { - context.RegisterCodeFix(new ProjectOptionsChangeAction(UnsafeThisProjectResource, _ => - Task.FromResult(AllowUnsafeOnProject(context.Document.Project))), context.Diagnostics); + context.RegisterCodeFix(new ProjectOptionsChangeAction(CSharpFeaturesResources.Allow_unsafe_code_in_this_project, + _ => Task.FromResult(AllowUnsafeOnProject(context.Document.Project))), context.Diagnostics); return Task.CompletedTask; } diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf index 1bd06a1edf3ae..ffca106719fcc 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf @@ -637,6 +637,11 @@ Convert 'for' to 'foreach' + + Allow unsafe code in this project + Allow unsafe code in this project + + \ No newline at end of file diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf index 40097ece0728d..4e1358d27104c 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf @@ -637,6 +637,11 @@ Convert 'for' to 'foreach' + + Allow unsafe code in this project + Allow unsafe code in this project + + \ No newline at end of file diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf index 7e32776cfaac4..78897a8555569 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf @@ -637,6 +637,11 @@ Convert 'for' to 'foreach' + + Allow unsafe code in this project + Allow unsafe code in this project + + \ No newline at end of file diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf index cc200a5d5491f..f3193fdca770c 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf @@ -637,6 +637,11 @@ Convert 'for' to 'foreach' + + Allow unsafe code in this project + Allow unsafe code in this project + + \ No newline at end of file diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf index 4972959fe5c76..a250ceb9f1006 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf @@ -637,6 +637,11 @@ Convert 'for' to 'foreach' + + Allow unsafe code in this project + Allow unsafe code in this project + + \ No newline at end of file diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf index 8fafb335468d5..fb641a58f2f2b 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf @@ -637,6 +637,11 @@ Convert 'for' to 'foreach' + + Allow unsafe code in this project + Allow unsafe code in this project + + \ No newline at end of file diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf index 4ee71f75c339e..b272bd8bc41a9 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf @@ -637,6 +637,11 @@ Convert 'for' to 'foreach' + + Allow unsafe code in this project + Allow unsafe code in this project + + \ No newline at end of file diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf index e2b5d1b93fa92..f061f5becc2c1 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf @@ -637,6 +637,11 @@ Convert 'for' to 'foreach' + + Allow unsafe code in this project + Allow unsafe code in this project + + \ No newline at end of file diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf index 4aaadb65a887d..afe6f3145ab7d 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf @@ -637,6 +637,11 @@ Convert 'for' to 'foreach' + + Allow unsafe code in this project + Allow unsafe code in this project + + \ No newline at end of file diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf index cd96923d9f55c..718c694f102be 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf @@ -637,6 +637,11 @@ Convert 'for' to 'foreach' + + Allow unsafe code in this project + Allow unsafe code in this project + + \ No newline at end of file diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf index 91847b34d5139..5d322a25b3f71 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf @@ -637,6 +637,11 @@ Convert 'for' to 'foreach' + + Allow unsafe code in this project + Allow unsafe code in this project + + \ No newline at end of file diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf index 12bfb8b9c438e..a1ac630346239 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf @@ -637,6 +637,11 @@ Convert 'for' to 'foreach' + + Allow unsafe code in this project + Allow unsafe code in this project + + \ No newline at end of file diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf index f2ec2b3b74bc8..aff10def3603c 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf @@ -637,6 +637,11 @@ Convert 'for' to 'foreach' + + Allow unsafe code in this project + Allow unsafe code in this project + + \ No newline at end of file From f162695a95d6777ce11caeb042162cb1d2956fc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Mon, 2 Apr 2018 00:44:13 +0200 Subject: [PATCH 09/45] Adding comment for missing fix all --- .../CSharpUnsafeProjectCodeFixProvider.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs b/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs index af4573c76ce38..685545473fb18 100644 --- a/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs @@ -16,6 +16,18 @@ internal class CSharpUnsafeProjectCodeFixProvider : CodeFixProvider public override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(CS0227); + public override FixAllProvider GetFixAllProvider() + { + // Fix all could be implemented, but doesn't seem as important because for this to be useful, + // the user would have to have erroneous unsafe blocks in several projects, which sounds really unlikely. + // And after all, unsafe code itself is and should be an edge case - do we want to make it easier + // to convert to it on a larger scale? + // If we do this, we should create a custom FixAllProvider that only supports FixAllScope.Solution + // since Document and Project don't really make sense - the action would always be the same as for fix one + // and having these extra options would only be confusing. + return null; + } + public override Task RegisterCodeFixesAsync(CodeFixContext context) { context.RegisterCodeFix(new ProjectOptionsChangeAction(CSharpFeaturesResources.Allow_unsafe_code_in_this_project, From 7b511a811fff495412762a70ae99542da7d2ea01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Mon, 2 Apr 2018 13:00:59 +0200 Subject: [PATCH 10/45] Simplifying enumeration of ConfigurationManager --- .../ProjectSystem/VisualStudioWorkspaceImpl.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs index 1c89da585e907..9bf2644b18637 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs @@ -328,13 +328,12 @@ protected override void ApplyCompilationOptionsChanged(ProjectId projectId, Comp } GetProjectData(projectId, out var hostProject, out var hierarchy, out var project); - foreach (string configurationName in (object[])project.ConfigurationManager.ConfigurationRowNames) + foreach (Configuration configuration in project.ConfigurationManager) { switch (hostProject.Language) { case LanguageNames.CSharp: - var csharpProperties = (VSLangProj80.CSharpProjectConfigurationProperties3)project.ConfigurationManager - .ConfigurationRow(configurationName).Item(1).Object; + var csharpProperties = (VSLangProj80.CSharpProjectConfigurationProperties3)configuration.Object; csharpProperties.AllowUnsafeBlocks = ((CSharpCompilationOptions)options).AllowUnsafe; break; @@ -359,17 +358,16 @@ protected override void ApplyParseOptionsChanged(ProjectId projectId, ParseOptio var parseOptionsService = CurrentSolution.GetProject(projectId).LanguageServices.GetService(); Contract.ThrowIfNull(parseOptionsService, nameof(parseOptionsService)); - + string newVersion = parseOptionsService.GetLanguageVersion(options); GetProjectData(projectId, out var hostProject, out var hierarchy, out var project); - foreach (string configurationName in (object[])project.ConfigurationManager.ConfigurationRowNames) + foreach (Configuration configuration in project.ConfigurationManager) { switch (hostProject.Language) { case LanguageNames.CSharp: - var csharpProperties = (VSLangProj80.CSharpProjectConfigurationProperties3)project.ConfigurationManager - .ConfigurationRow(configurationName).Item(1).Object; + var csharpProperties = (VSLangProj80.CSharpProjectConfigurationProperties3)configuration.Object; if (newVersion != csharpProperties.LanguageVersion) { From a934f22b9f0271a338221fde6c84f5d49d1ca85b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Tue, 3 Apr 2018 00:11:29 +0200 Subject: [PATCH 11/45] Renaming --- .../UpdateProjectToAllowUnsafeTests.cs} | 6 +++--- .../CSharpUpdateProjectToAllowUnsafeCodeFixProvider.cs} | 2 +- src/Test/Utilities/Portable/Traits/Traits.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/EditorFeatures/CSharpTest/Diagnostics/{UnsafeProject/UnsafeProjectTests.cs => UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs} (91%) rename src/Features/CSharp/Portable/{UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs => UpdateProjectToAllowUnsafe/CSharpUpdateProjectToAllowUnsafeCodeFixProvider.cs} (96%) diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/UnsafeProject/UnsafeProjectTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs similarity index 91% rename from src/EditorFeatures/CSharpTest/Diagnostics/UnsafeProject/UnsafeProjectTests.cs rename to src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs index ee45c35c951e5..f6e4e1297bbf5 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/UnsafeProject/UnsafeProjectTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs @@ -11,11 +11,11 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.UnsafeProject { - [Trait(Traits.Feature, Traits.Features.CodeActionsUnsafeProject)] - public class UnsafeProjectTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest + [Trait(Traits.Feature, Traits.Features.CodeActionsUpdateProjectToAllowUnsafe)] + public class UpdateProjectToAllowUnsafeTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest { internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace) - => (null, new CSharpUnsafeProjectCodeFixProvider()); + => (null, new CSharpUpdateProjectToAllowUnsafeCodeFixProvider()); private async Task TestAllowUnsafeEnabledIfDisabledAsync(string initialMarkup) { diff --git a/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs b/src/Features/CSharp/Portable/UpdateProjectToAllowUnsafe/CSharpUpdateProjectToAllowUnsafeCodeFixProvider.cs similarity index 96% rename from src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs rename to src/Features/CSharp/Portable/UpdateProjectToAllowUnsafe/CSharpUpdateProjectToAllowUnsafeCodeFixProvider.cs index 685545473fb18..8040dceb7b142 100644 --- a/src/Features/CSharp/Portable/UnsafeProject/CSharpUnsafeProjectCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/UpdateProjectToAllowUnsafe/CSharpUpdateProjectToAllowUnsafeCodeFixProvider.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UnsafeProject { [ExportCodeFixProvider(LanguageNames.CSharp), Shared] - internal class CSharpUnsafeProjectCodeFixProvider : CodeFixProvider + internal class CSharpUpdateProjectToAllowUnsafeCodeFixProvider : CodeFixProvider { private const string CS0227 = nameof(CS0227); // error CS0227: Unsafe code may only appear if compiling with /unsafe diff --git a/src/Test/Utilities/Portable/Traits/Traits.cs b/src/Test/Utilities/Portable/Traits/Traits.cs index 1a36667fa3668..0e27994f5c654 100644 --- a/src/Test/Utilities/Portable/Traits/Traits.cs +++ b/src/Test/Utilities/Portable/Traits/Traits.cs @@ -33,7 +33,7 @@ public static class Features public const string CodeActionsAddConstructorParametersFromMembers = "CodeActions.AddConstructorParametersFromMembers"; public const string CodeActionsAddDocCommentNodes = "CodeActions.AddDocCommentParamNodes"; public const string CodeActionsAddAwait = "CodeActions.AddAwait"; - public const string CodeActionsUnsafeProject = "CodeActions.UnsafeProject"; + public const string CodeActionsUpdateProjectToAllowUnsafe = "CodeActions.UpdateProjectToAllowUnsafe"; public const string CodeActionsUpgradeProject = "CodeActions.UpgradeProject"; public const string CodeActionsAddAccessibilityModifiers = "CodeActions.AddAccessibilityModifiers"; public const string CodeActionsAddBraces = "CodeActions.AddBraces"; From 6fd37d08f28625ceb08fd3662fb56361ef9d9cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Tue, 3 Apr 2018 00:27:04 +0200 Subject: [PATCH 12/45] Updating namespaces --- .../UpdateProjectToAllowUnsafeTests.cs | 4 ++-- .../Diagnostics/UpgradeProject/UpgradeProjectTests.cs | 2 +- .../CSharpUpdateProjectToAllowUnsafeCodeFixProvider.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs index f6e4e1297bbf5..c8f2dba68179d 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs @@ -4,12 +4,12 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.UnsafeProject; +using Microsoft.CodeAnalysis.CSharp.UpdateProjectToAllowUnsafe; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Test.Utilities; using Xunit; -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.UnsafeProject +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.UpdateProjectToAllowUnsafe { [Trait(Traits.Feature, Traits.Features.CodeActionsUpdateProjectToAllowUnsafe)] public class UpdateProjectToAllowUnsafeTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs index db0f5e3aeb05b..11f334cce4d21 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs @@ -9,7 +9,7 @@ using Microsoft.CodeAnalysis.Test.Utilities; using Xunit; -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.Async +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.UpgradeProject { [Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] public partial class UpgradeProjectTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest diff --git a/src/Features/CSharp/Portable/UpdateProjectToAllowUnsafe/CSharpUpdateProjectToAllowUnsafeCodeFixProvider.cs b/src/Features/CSharp/Portable/UpdateProjectToAllowUnsafe/CSharpUpdateProjectToAllowUnsafeCodeFixProvider.cs index 8040dceb7b142..12d7cb94d0d61 100644 --- a/src/Features/CSharp/Portable/UpdateProjectToAllowUnsafe/CSharpUpdateProjectToAllowUnsafeCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/UpdateProjectToAllowUnsafe/CSharpUpdateProjectToAllowUnsafeCodeFixProvider.cs @@ -6,7 +6,7 @@ using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.UpgradeProject; -namespace Microsoft.CodeAnalysis.CSharp.UnsafeProject +namespace Microsoft.CodeAnalysis.CSharp.UpdateProjectToAllowUnsafe { [ExportCodeFixProvider(LanguageNames.CSharp), Shared] internal class CSharpUpdateProjectToAllowUnsafeCodeFixProvider : CodeFixProvider From 197caa431bb08f4dbf6e468758fe5ee2d4851120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Tue, 3 Apr 2018 00:35:36 +0200 Subject: [PATCH 13/45] Changing comment for missing fix all --- .../UpdateProjectToAllowUnsafeTests.cs | 2 +- .../CSharpUpdateProjectToAllowUnsafeCodeFixProvider.cs | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs index c8f2dba68179d..49eef8f5348cb 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs @@ -68,7 +68,7 @@ class C { void M() { - unsafe void [|Function|]() + unsafe void [|F|]() { } } diff --git a/src/Features/CSharp/Portable/UpdateProjectToAllowUnsafe/CSharpUpdateProjectToAllowUnsafeCodeFixProvider.cs b/src/Features/CSharp/Portable/UpdateProjectToAllowUnsafe/CSharpUpdateProjectToAllowUnsafeCodeFixProvider.cs index 12d7cb94d0d61..10bf91346e3a4 100644 --- a/src/Features/CSharp/Portable/UpdateProjectToAllowUnsafe/CSharpUpdateProjectToAllowUnsafeCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/UpdateProjectToAllowUnsafe/CSharpUpdateProjectToAllowUnsafeCodeFixProvider.cs @@ -18,13 +18,8 @@ internal class CSharpUpdateProjectToAllowUnsafeCodeFixProvider : CodeFixProvider public override FixAllProvider GetFixAllProvider() { - // Fix all could be implemented, but doesn't seem as important because for this to be useful, - // the user would have to have erroneous unsafe blocks in several projects, which sounds really unlikely. - // And after all, unsafe code itself is and should be an edge case - do we want to make it easier - // to convert to it on a larger scale? - // If we do this, we should create a custom FixAllProvider that only supports FixAllScope.Solution - // since Document and Project don't really make sense - the action would always be the same as for fix one - // and having these extra options would only be confusing. + // We're OK with users having to explicitly opt in each project. Unsafe code is itself an edge case and we don't + // need to make it easier to convert to it on a larger scale. It's also unlikely that anyone will need this. return null; } From 1d0e4ac3b615838d03d186887102c6c4e2f04da6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Tue, 3 Apr 2018 19:48:17 +0200 Subject: [PATCH 14/45] Adding integration tests --- .../AbstractIntegrationTest.cs | 4 +- .../CSharpUpdateProjectToAllowUnsafe.cs | 114 +++++++++++++++++ .../CSharp/CSharpUpgradeProject.cs | 116 ++++++++++++++++++ .../InProcess/SolutionExplorer_InProc.cs | 11 ++ .../SolutionExplorer_OutOfProc.cs | 3 + 5 files changed, 246 insertions(+), 2 deletions(-) create mode 100644 src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs create mode 100644 src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractIntegrationTest.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractIntegrationTest.cs index ebbfb89d1290b..7889424d4d39c 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractIntegrationTest.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractIntegrationTest.cs @@ -14,8 +14,8 @@ public abstract class AbstractIntegrationTest : IDisposable { public readonly VisualStudioInstance VisualStudio; - protected readonly string ProjectName = "TestProj"; - protected readonly string SolutionName = "TestSolution"; + protected const string ProjectName = "TestProj"; + protected const string SolutionName = "TestSolution"; private VisualStudioInstanceContext _visualStudioContext; diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs new file mode 100644 index 0000000000000..e0524f1e88e76 --- /dev/null +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.VisualStudio.IntegrationTest.Utilities; +using Roslyn.Test.Utilities; +using Xunit; +using ProjectUtils = Microsoft.VisualStudio.IntegrationTest.Utilities.Common.ProjectUtils; + +namespace Roslyn.VisualStudio.IntegrationTests.Other +{ + [Collection(nameof(SharedIntegrationHostFixture))] + public class CSharpUpdateProjectToAllowUnsafe : AbstractIntegrationTest + { + private readonly string OriginalProjectFile = $@" + + + + Debug + x64 + {{F4233BA4-A4CB-498B-BBC1-65A42206B1BA}} + Library + {ProjectName} + {ProjectName} + v4.5 + + + bin\x86\Debug\ + x86 + + + bin\x86\Release\ + x86 + true + + + bin\x64\Debug\ + x64 + false + + + bin\x64\Release\ + x64 + + + + +"; + + private readonly string ExpectedProjectFile = $@" + + + + Debug + x64 + {{F4233BA4-A4CB-498B-BBC1-65A42206B1BA}} + Library + {ProjectName} + {ProjectName} + v4.5 + + + bin\x86\Debug\ + x86 + true + + + bin\x86\Release\ + x86 + true + + + bin\x64\Debug\ + x64 + true + + + bin\x64\Release\ + x64 + true + + + + + +"; + + public CSharpUpdateProjectToAllowUnsafe(VisualStudioInstanceFactory instanceFactory) : base(instanceFactory) + { + } + + [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUpdateProjectToAllowUnsafe)] + public void AllConfigurationsUpdated() + { + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); + var project = new ProjectUtils.Project(ProjectName); + + VisualStudio.SolutionExplorer.AddCustomProject(project, ".csproj", OriginalProjectFile); + VisualStudio.SolutionExplorer.AddFile(project, "C.cs", @" +unsafe class C +{ +}", open: true); + + VisualStudio.Editor.PlaceCaret("C"); + VisualStudio.Editor.InvokeCodeActionList(); + VisualStudio.Editor.Verify.CodeAction("Allow unsafe code in this project", applyFix: true); + + // Save the project file. + VisualStudio.SolutionExplorer.SaveAll(); + + Assert.Equal(ExpectedProjectFile, VisualStudio.SolutionExplorer.GetFileContents(project, project.Name + ".csproj")); + } + } +} diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs new file mode 100644 index 0000000000000..cce7203695cf0 --- /dev/null +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs @@ -0,0 +1,116 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.VisualStudio.IntegrationTest.Utilities; +using Roslyn.Test.Utilities; +using Xunit; +using ProjectUtils = Microsoft.VisualStudio.IntegrationTest.Utilities.Common.ProjectUtils; + +namespace Roslyn.VisualStudio.IntegrationTests.Other +{ + [Collection(nameof(SharedIntegrationHostFixture))] + public class CSharpUpgradeProject : AbstractIntegrationTest + { + // Be explicit about 7.0 in Debug|x64 so that this doesn't break when a new major version is released. + private readonly string OriginalProjectFile = $@" + + + + Debug + x64 + {{F4233BA4-A4CB-498B-BBC1-65A42206B1BA}} + Library + {ProjectName} + {ProjectName} + v4.5 + + + bin\x86\Debug\ + x86 + + + bin\x86\Release\ + x86 + 7.1 + + + bin\x64\Debug\ + x64 + 7.0 + + + bin\x64\Release\ + x64 + + + + +"; + + private readonly string ExpectedProjectFile = $@" + + + + Debug + x64 + {{F4233BA4-A4CB-498B-BBC1-65A42206B1BA}} + Library + {ProjectName} + {ProjectName} + v4.5 + + + bin\x86\Debug\ + x86 + 7.1 + + + bin\x86\Release\ + x86 + 7.1 + + + bin\x64\Debug\ + x64 + 7.1 + + + bin\x64\Release\ + x64 + 7.1 + + + + + +"; + + public CSharpUpgradeProject(VisualStudioInstanceFactory instanceFactory) : base(instanceFactory) + { + } + + [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] + public void AllConfigurationsUpdated() + { + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); + var project = new ProjectUtils.Project(ProjectName); + + VisualStudio.SolutionExplorer.AddCustomProject(project, ".csproj", OriginalProjectFile); + VisualStudio.SolutionExplorer.AddFile(project, "C.cs", @" +class C +{ + int i = default; +}", open: true); + + VisualStudio.Editor.PlaceCaret("default"); + VisualStudio.Editor.InvokeCodeActionList(); + VisualStudio.Editor.Verify.CodeAction("Upgrade this project to C# language version '7.1'", applyFix: true); + + // Save the project file. + VisualStudio.SolutionExplorer.SaveAll(); + + Assert.Equal(ExpectedProjectFile, VisualStudio.SolutionExplorer.GetFileContents(project, project.Name + ".csproj")); + } + } +} diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs index 929e636dc436e..055ede3a48f78 100644 --- a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs +++ b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs @@ -308,6 +308,17 @@ public void AddProject(string projectName, string projectTemplate, string langua _solution.AddFromTemplate(projectTemplatePath, projectPath, projectName, Exclusive: false); } + public void AddCustomProject(string projectName, string projectFileExtension, string projectFileContent) + { + var projectPath = Path.Combine(DirectoryName, projectName); + Directory.CreateDirectory(projectPath); + + var projectFilePath = Path.Combine(projectPath, projectName + projectFileExtension); + File.WriteAllText(projectFilePath, projectFileContent); + + _solution.AddFromFile(projectFilePath); + } + // TODO: Adjust language name based on whether we are using a web template private string GetProjectTemplatePath(string projectTemplate, string languageName) { diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/SolutionExplorer_OutOfProc.cs b/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/SolutionExplorer_OutOfProc.cs index 0be408e9dfd3a..f8eccf6c9c47e 100644 --- a/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/SolutionExplorer_OutOfProc.cs +++ b/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/SolutionExplorer_OutOfProc.cs @@ -44,6 +44,9 @@ public void OpenSolution(string path, bool saveExistingSolutionIfExists = false) public void AddProject(ProjectUtils.Project projectName, string projectTemplate, string languageName) => _inProc.AddProject(projectName.Name, projectTemplate, languageName); + + public void AddCustomProject(ProjectUtils.Project projectName, string projectFileExtension, string projectFileContent) + => _inProc.AddCustomProject(projectName.Name, projectFileExtension, projectFileContent); public void AddProjectReference(ProjectUtils.Project fromProjectName, ProjectUtils.ProjectReference toProjectName) { From b2a6df7fd259a088177d671a731f860de1a7eca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Thu, 5 Apr 2018 00:41:09 +0200 Subject: [PATCH 15/45] Using WpfFact for integration tests --- .../IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs | 2 +- .../IntegrationTests/CSharp/CSharpUpgradeProject.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs index e0524f1e88e76..07c42d5750754 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs @@ -89,7 +89,7 @@ public CSharpUpdateProjectToAllowUnsafe(VisualStudioInstanceFactory instanceFact } [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] - [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUpdateProjectToAllowUnsafe)] + [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpdateProjectToAllowUnsafe)] public void AllConfigurationsUpdated() { VisualStudio.SolutionExplorer.CreateSolution(SolutionName); diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs index cce7203695cf0..bc1b4bbad0c92 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs @@ -90,7 +90,7 @@ public CSharpUpgradeProject(VisualStudioInstanceFactory instanceFactory) : base( } [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] - [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] + [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] public void AllConfigurationsUpdated() { VisualStudio.SolutionExplorer.CreateSolution(SolutionName); From 7003d31fd2d7280f3f70cd41cd84f2258ffe288a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sat, 7 Apr 2018 23:44:42 +0200 Subject: [PATCH 16/45] Using XML checks for expected project file in tests --- .../CSharpUpdateProjectToAllowUnsafe.cs | 47 ++++--------------- .../CSharp/CSharpUpgradeProject.cs | 47 ++++--------------- 2 files changed, 16 insertions(+), 78 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs index 07c42d5750754..35f9f61d2e277 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Linq; +using System.Xml.Linq; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.VisualStudio.IntegrationTest.Utilities; using Roslyn.Test.Utilities; @@ -46,44 +48,6 @@ public class CSharpUpdateProjectToAllowUnsafe : AbstractIntegrationTest "; - private readonly string ExpectedProjectFile = $@" - - - - Debug - x64 - {{F4233BA4-A4CB-498B-BBC1-65A42206B1BA}} - Library - {ProjectName} - {ProjectName} - v4.5 - - - bin\x86\Debug\ - x86 - true - - - bin\x86\Release\ - x86 - true - - - bin\x64\Debug\ - x64 - true - - - bin\x64\Release\ - x64 - true - - - - - -"; - public CSharpUpdateProjectToAllowUnsafe(VisualStudioInstanceFactory instanceFactory) : base(instanceFactory) { } @@ -108,7 +72,12 @@ unsafe class C // Save the project file. VisualStudio.SolutionExplorer.SaveAll(); - Assert.Equal(ExpectedProjectFile, VisualStudio.SolutionExplorer.GetFileContents(project, project.Name + ".csproj")); + var updatedProjectFile = VisualStudio.SolutionExplorer.GetFileContents(project, project.Name + ".csproj"); + var updatedProjectElement = XElement.Parse(updatedProjectFile); + + Assert.True(updatedProjectElement.Elements() + .Where(e => e.Name.LocalName == "PropertyGroup" && e.Attributes().Any(a => a.Name.LocalName == "Condition")) + .All(g => g.Elements().Single(e => e.Name.LocalName == "AllowUnsafeBlocks").Value == "true")); } } } diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs index bc1b4bbad0c92..71d8e9ace411b 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Linq; +using System.Xml.Linq; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.VisualStudio.IntegrationTest.Utilities; using Roslyn.Test.Utilities; @@ -47,44 +49,6 @@ public class CSharpUpgradeProject : AbstractIntegrationTest "; - private readonly string ExpectedProjectFile = $@" - - - - Debug - x64 - {{F4233BA4-A4CB-498B-BBC1-65A42206B1BA}} - Library - {ProjectName} - {ProjectName} - v4.5 - - - bin\x86\Debug\ - x86 - 7.1 - - - bin\x86\Release\ - x86 - 7.1 - - - bin\x64\Debug\ - x64 - 7.1 - - - bin\x64\Release\ - x64 - 7.1 - - - - - -"; - public CSharpUpgradeProject(VisualStudioInstanceFactory instanceFactory) : base(instanceFactory) { } @@ -110,7 +74,12 @@ class C // Save the project file. VisualStudio.SolutionExplorer.SaveAll(); - Assert.Equal(ExpectedProjectFile, VisualStudio.SolutionExplorer.GetFileContents(project, project.Name + ".csproj")); + var updatedProjectFile = VisualStudio.SolutionExplorer.GetFileContents(project, project.Name + ".csproj"); + var updatedProjectElement = XElement.Parse(updatedProjectFile); + + Assert.True(updatedProjectElement.Elements() + .Where(e => e.Name.LocalName == "PropertyGroup" && e.Attributes().Any(a => a.Name.LocalName == "Condition")) + .All(g => g.Elements().Single(e => e.Name.LocalName == "LangVersion").Value == "7.1")); } } } From c5275a0dc3645eec94a32d37cde131f9b574b40a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 8 Apr 2018 02:10:43 +0200 Subject: [PATCH 17/45] Using IVsBuildPropertyStorage for CPS projects --- ...dioWorkspaceImpl.ProjectPropertyStorage.cs | 58 +++++++++++++++++++ .../VisualStudioWorkspaceImpl.cs | 52 ++++++----------- 2 files changed, 77 insertions(+), 33 deletions(-) create mode 100644 src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs new file mode 100644 index 0000000000000..dab7030808d8a --- /dev/null +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Linq; +using EnvDTE; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using Roslyn.Utilities; + +namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem +{ + internal partial class VisualStudioWorkspaceImpl + { + private abstract class ProjectPropertyStorage + { + public static ProjectPropertyStorage Get(Project project, IServiceProvider serviceProvider) + { + var solution = (IVsSolution)serviceProvider.GetService(typeof(SVsSolution)); + solution.GetProjectOfUniqueName(project.UniqueName, out var hierarchy); + + return hierarchy.IsCapabilityMatch("CPS") + ? new BuildPropertyStorage((IVsBuildPropertyStorage)hierarchy) + : new PerConfigurationPropertyStorage(project.ConfigurationManager) as ProjectPropertyStorage; + } + + public abstract void SetProperty(string buildPropertyName, string configurationPropertyName, string value); + + private sealed class BuildPropertyStorage : ProjectPropertyStorage + { + private readonly IVsBuildPropertyStorage propertyStorage; + + public BuildPropertyStorage(IVsBuildPropertyStorage propertyStorage) + => this.propertyStorage = propertyStorage; + + public override void SetProperty(string buildPropertyName, string configurationPropertyName, string value) + { + propertyStorage.SetPropertyValue(buildPropertyName, null, (uint)_PersistStorageType.PST_PROJECT_FILE, value); + } + } + + private sealed class PerConfigurationPropertyStorage : ProjectPropertyStorage + { + private readonly ConfigurationManager configurationManager; + + public PerConfigurationPropertyStorage(ConfigurationManager configurationManager) + => this.configurationManager = configurationManager; + + public override void SetProperty(string buildPropertyName, string configurationPropertyName, string value) + { + foreach (Configuration configuration in configurationManager) + { + configuration.Properties.Cast().First(property => property.Name == configurationPropertyName).Value = value; + } + } + } + } + } +} diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs index 9bf2644b18637..095ace96479ac 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs @@ -17,6 +17,7 @@ using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.SolutionCrawler; using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis.VisualBasic; using Microsoft.VisualStudio.ComponentModelHost; using Microsoft.VisualStudio.Editor; using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.Extensions; @@ -27,6 +28,7 @@ using Roslyn.Utilities; using VSLangProj; using VSLangProj140; +using VSLangProj80; using OleInterop = Microsoft.VisualStudio.OLE.Interop; namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem @@ -327,20 +329,16 @@ protected override void ApplyCompilationOptionsChanged(ProjectId projectId, Comp throw new ArgumentNullException(nameof(options)); } - GetProjectData(projectId, out var hostProject, out var hierarchy, out var project); - foreach (Configuration configuration in project.ConfigurationManager) - { - switch (hostProject.Language) - { - case LanguageNames.CSharp: - var csharpProperties = (VSLangProj80.CSharpProjectConfigurationProperties3)configuration.Object; + var storage = ProjectPropertyStorage.Get(TryGetDTEProject(projectId), DeferredState.ServiceProvider); - csharpProperties.AllowUnsafeBlocks = ((CSharpCompilationOptions)options).AllowUnsafe; - break; - - case LanguageNames.VisualBasic: - throw new InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_compilation_options); - } + switch (options) + { + case CSharpCompilationOptions csharpOptions: + storage.SetProperty("AllowUnsafeBlocks", nameof(ProjectConfigurationProperties3.AllowUnsafeBlocks), + csharpOptions.AllowUnsafe.ToString().ToLowerInvariant()); + break; + case VisualBasicCompilationOptions _: + throw new InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_compilation_options); } } @@ -356,28 +354,16 @@ protected override void ApplyParseOptionsChanged(ProjectId projectId, ParseOptio throw new ArgumentNullException(nameof(options)); } - var parseOptionsService = CurrentSolution.GetProject(projectId).LanguageServices.GetService(); - Contract.ThrowIfNull(parseOptionsService, nameof(parseOptionsService)); + var storage = ProjectPropertyStorage.Get(TryGetDTEProject(projectId), DeferredState.ServiceProvider); - string newVersion = parseOptionsService.GetLanguageVersion(options); - - GetProjectData(projectId, out var hostProject, out var hierarchy, out var project); - foreach (Configuration configuration in project.ConfigurationManager) + switch (options) { - switch (hostProject.Language) - { - case LanguageNames.CSharp: - var csharpProperties = (VSLangProj80.CSharpProjectConfigurationProperties3)configuration.Object; - - if (newVersion != csharpProperties.LanguageVersion) - { - csharpProperties.LanguageVersion = newVersion; - } - break; - - case LanguageNames.VisualBasic: - throw new InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_parse_options); - } + case CSharpParseOptions csharpOptions: + storage.SetProperty("LangVersion", nameof(CSharpProjectConfigurationProperties3.LanguageVersion), + csharpOptions.SpecifiedLanguageVersion.ToDisplayString()); + break; + case VisualBasicParseOptions _: + throw new InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_parse_options); } } From 4ba8b423844ccf3d94c11a35fa527e7d6cb8244e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 8 Apr 2018 03:04:29 +0200 Subject: [PATCH 18/45] Adding tests for CPS projects --- .../CSharpUpdateProjectToAllowUnsafe.cs | 56 +++++++++++++----- .../CSharp/CSharpUpgradeProject.cs | 59 ++++++++++++++----- .../WellKnownProjectTemplates.cs | 2 + 3 files changed, 88 insertions(+), 29 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs index 35f9f61d2e277..6d3eeab6de361 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Xml.Linq; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.VisualStudio.IntegrationTest.Utilities; using Roslyn.Test.Utilities; @@ -13,7 +14,46 @@ namespace Roslyn.VisualStudio.IntegrationTests.Other [Collection(nameof(SharedIntegrationHostFixture))] public class CSharpUpdateProjectToAllowUnsafe : AbstractIntegrationTest { - private readonly string OriginalProjectFile = $@" + public CSharpUpdateProjectToAllowUnsafe(VisualStudioInstanceFactory instanceFactory) : base(instanceFactory) + { + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpdateProjectToAllowUnsafe)] + public void CPSProject_GeneralPropertyGroupUpdated() + { + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); + var project = new ProjectUtils.Project(ProjectName); + + VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.CSharpNetStandardClassLibrary, LanguageNames.CSharp); + + VisualStudio.SolutionExplorer.AddFile(project, "C.cs", @" +unsafe class C +{ +}", open: true); + + VisualStudio.Editor.PlaceCaret("C"); + VisualStudio.Editor.InvokeCodeActionList(); + VisualStudio.Editor.Verify.CodeAction("Allow unsafe code in this project", applyFix: true); + + // Save the project file. + VisualStudio.SolutionExplorer.SaveAll(); + + var updatedProjectFile = VisualStudio.SolutionExplorer.GetFileContents(project, project.Name + ".csproj"); + var updatedProjectElement = XElement.Parse(updatedProjectFile); + + Assert.True(updatedProjectElement.Elements() + .Where(e => e.Name.LocalName == "PropertyGroup" && !e.Attributes().Any(a => a.Name.LocalName == "Condition")) + .Any(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "AllowUnsafeBlocks")?.Value == "true")); + } + + [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] + [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpdateProjectToAllowUnsafe)] + public void LegacyProject_AllConfigurationsUpdated() + { + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); + var project = new ProjectUtils.Project(ProjectName); + + VisualStudio.SolutionExplorer.AddCustomProject(project, ".csproj", $@" @@ -46,20 +86,8 @@ public class CSharpUpdateProjectToAllowUnsafe : AbstractIntegrationTest -"; - - public CSharpUpdateProjectToAllowUnsafe(VisualStudioInstanceFactory instanceFactory) : base(instanceFactory) - { - } - - [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] - [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpdateProjectToAllowUnsafe)] - public void AllConfigurationsUpdated() - { - VisualStudio.SolutionExplorer.CreateSolution(SolutionName); - var project = new ProjectUtils.Project(ProjectName); +"); - VisualStudio.SolutionExplorer.AddCustomProject(project, ".csproj", OriginalProjectFile); VisualStudio.SolutionExplorer.AddFile(project, "C.cs", @" unsafe class C { diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs index 71d8e9ace411b..ccb9f9b10b923 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Xml.Linq; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.VisualStudio.IntegrationTest.Utilities; using Roslyn.Test.Utilities; @@ -13,8 +14,48 @@ namespace Roslyn.VisualStudio.IntegrationTests.Other [Collection(nameof(SharedIntegrationHostFixture))] public class CSharpUpgradeProject : AbstractIntegrationTest { - // Be explicit about 7.0 in Debug|x64 so that this doesn't break when a new major version is released. - private readonly string OriginalProjectFile = $@" + public CSharpUpgradeProject(VisualStudioInstanceFactory instanceFactory) : base(instanceFactory) + { + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] + public void CPSProject_GeneralPropertyGroupUpdated() + { + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); + var project = new ProjectUtils.Project(ProjectName); + + VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.CSharpNetStandardClassLibrary, LanguageNames.CSharp); + + VisualStudio.SolutionExplorer.AddFile(project, "C.cs", @" +class C +{ + int i = default; +}", open: true); + + VisualStudio.Editor.PlaceCaret("default"); + VisualStudio.Editor.InvokeCodeActionList(); + VisualStudio.Editor.Verify.CodeAction("Upgrade this project to C# language version '7.1'", applyFix: true); + + // Save the project file. + VisualStudio.SolutionExplorer.SaveAll(); + + var updatedProjectFile = VisualStudio.SolutionExplorer.GetFileContents(project, project.Name + ".csproj"); + var updatedProjectElement = XElement.Parse(updatedProjectFile); + + Assert.True(updatedProjectElement.Elements() + .Where(e => e.Name.LocalName == "PropertyGroup" && !e.Attributes().Any(a => a.Name.LocalName == "Condition")) + .Any(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "LangVersion")?.Value == "7.1")); + } + + [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] + [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] + public void LegacyProject_AllConfigurationsUpdated() + { + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); + var project = new ProjectUtils.Project(ProjectName); + + // Be explicit about 7.0 in Debug|x64 so that this doesn't break when a new major version is released. + VisualStudio.SolutionExplorer.AddCustomProject(project, ".csproj", $@" @@ -47,20 +88,8 @@ public class CSharpUpgradeProject : AbstractIntegrationTest -"; - - public CSharpUpgradeProject(VisualStudioInstanceFactory instanceFactory) : base(instanceFactory) - { - } - - [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] - [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] - public void AllConfigurationsUpdated() - { - VisualStudio.SolutionExplorer.CreateSolution(SolutionName); - var project = new ProjectUtils.Project(ProjectName); +"); - VisualStudio.SolutionExplorer.AddCustomProject(project, ".csproj", OriginalProjectFile); VisualStudio.SolutionExplorer.AddFile(project, "C.cs", @" class C { diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/WellKnownProjectTemplates.cs b/src/VisualStudio/IntegrationTest/TestUtilities/WellKnownProjectTemplates.cs index 265750c6d281e..ce60832aede33 100644 --- a/src/VisualStudio/IntegrationTest/TestUtilities/WellKnownProjectTemplates.cs +++ b/src/VisualStudio/IntegrationTest/TestUtilities/WellKnownProjectTemplates.cs @@ -14,6 +14,8 @@ public static class WellKnownProjectTemplates public const string VisualBasicNetCoreClassLibrary = "Microsoft.VisualBasic.NETCore.ClassLibrary"; public const string CSharpNetCoreConsoleApplication = "Microsoft.CSharp.NETCore.ConsoleApplication"; public const string VisualBasicNetCoreConsoleApplication = "Microsoft.VisualBasic.NETCore.ConsoleApplication"; + public const string CSharpNetStandardClassLibrary = "Microsoft.CSharp.NETStandard.ClassLibrary"; + public const string VisualBasicNetStandardClassLibrary = "Microsoft.VisualBasic.NETStandard.ClassLibrary"; public const string CSharpNetCoreUnitTest = "Microsoft.CSharp.NETCore.UnitTest"; public const string CSharpNetCoreXUnitTest = "Microsoft.CSharp.NETCore.XUnitTest"; } From b0d60cfcb43f7741d8813f72d686526d4309af47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 8 Apr 2018 03:22:25 +0200 Subject: [PATCH 19/45] Helper test methods --- .../CSharpUpdateProjectToAllowUnsafe.cs | 40 +++++++----------- .../CSharp/CSharpUpgradeProject.cs | 41 +++++++------------ 2 files changed, 28 insertions(+), 53 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs index 6d3eeab6de361..e3143dd43d72d 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs @@ -18,14 +18,8 @@ public CSharpUpdateProjectToAllowUnsafe(VisualStudioInstanceFactory instanceFact { } - [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpdateProjectToAllowUnsafe)] - public void CPSProject_GeneralPropertyGroupUpdated() + private XElement InvokeFixAndGetProjectFileElement(ProjectUtils.Project project) { - VisualStudio.SolutionExplorer.CreateSolution(SolutionName); - var project = new ProjectUtils.Project(ProjectName); - - VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.CSharpNetStandardClassLibrary, LanguageNames.CSharp); - VisualStudio.SolutionExplorer.AddFile(project, "C.cs", @" unsafe class C { @@ -39,9 +33,18 @@ unsafe class C VisualStudio.SolutionExplorer.SaveAll(); var updatedProjectFile = VisualStudio.SolutionExplorer.GetFileContents(project, project.Name + ".csproj"); - var updatedProjectElement = XElement.Parse(updatedProjectFile); + return XElement.Parse(updatedProjectFile); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpdateProjectToAllowUnsafe)] + public void CPSProject_GeneralPropertyGroupUpdated() + { + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); + var project = new ProjectUtils.Project(ProjectName); + + VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.CSharpNetStandardClassLibrary, LanguageNames.CSharp); - Assert.True(updatedProjectElement.Elements() + Assert.True(InvokeFixAndGetProjectFileElement(project).Elements() .Where(e => e.Name.LocalName == "PropertyGroup" && !e.Attributes().Any(a => a.Name.LocalName == "Condition")) .Any(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "AllowUnsafeBlocks")?.Value == "true")); } @@ -88,24 +91,9 @@ public void LegacyProject_AllConfigurationsUpdated() "); - VisualStudio.SolutionExplorer.AddFile(project, "C.cs", @" -unsafe class C -{ -}", open: true); - - VisualStudio.Editor.PlaceCaret("C"); - VisualStudio.Editor.InvokeCodeActionList(); - VisualStudio.Editor.Verify.CodeAction("Allow unsafe code in this project", applyFix: true); - - // Save the project file. - VisualStudio.SolutionExplorer.SaveAll(); - - var updatedProjectFile = VisualStudio.SolutionExplorer.GetFileContents(project, project.Name + ".csproj"); - var updatedProjectElement = XElement.Parse(updatedProjectFile); - - Assert.True(updatedProjectElement.Elements() + Assert.True(InvokeFixAndGetProjectFileElement(project).Elements() .Where(e => e.Name.LocalName == "PropertyGroup" && e.Attributes().Any(a => a.Name.LocalName == "Condition")) - .All(g => g.Elements().Single(e => e.Name.LocalName == "AllowUnsafeBlocks").Value == "true")); + .All(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "AllowUnsafeBlocks")?.Value == "true")); } } } diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs index ccb9f9b10b923..c5f72dec0a758 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs @@ -18,14 +18,8 @@ public CSharpUpgradeProject(VisualStudioInstanceFactory instanceFactory) : base( { } - [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] - public void CPSProject_GeneralPropertyGroupUpdated() + private XElement InvokeFixAndGetProjectFileElement(ProjectUtils.Project project) { - VisualStudio.SolutionExplorer.CreateSolution(SolutionName); - var project = new ProjectUtils.Project(ProjectName); - - VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.CSharpNetStandardClassLibrary, LanguageNames.CSharp); - VisualStudio.SolutionExplorer.AddFile(project, "C.cs", @" class C { @@ -40,9 +34,18 @@ class C VisualStudio.SolutionExplorer.SaveAll(); var updatedProjectFile = VisualStudio.SolutionExplorer.GetFileContents(project, project.Name + ".csproj"); - var updatedProjectElement = XElement.Parse(updatedProjectFile); + return XElement.Parse(updatedProjectFile); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] + public void CPSProject_GeneralPropertyGroupUpdated() + { + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); + var project = new ProjectUtils.Project(ProjectName); + + VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.CSharpNetStandardClassLibrary, LanguageNames.CSharp); - Assert.True(updatedProjectElement.Elements() + Assert.True(InvokeFixAndGetProjectFileElement(project).Elements() .Where(e => e.Name.LocalName == "PropertyGroup" && !e.Attributes().Any(a => a.Name.LocalName == "Condition")) .Any(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "LangVersion")?.Value == "7.1")); } @@ -90,25 +93,9 @@ public void LegacyProject_AllConfigurationsUpdated() "); - VisualStudio.SolutionExplorer.AddFile(project, "C.cs", @" -class C -{ - int i = default; -}", open: true); - - VisualStudio.Editor.PlaceCaret("default"); - VisualStudio.Editor.InvokeCodeActionList(); - VisualStudio.Editor.Verify.CodeAction("Upgrade this project to C# language version '7.1'", applyFix: true); - - // Save the project file. - VisualStudio.SolutionExplorer.SaveAll(); - - var updatedProjectFile = VisualStudio.SolutionExplorer.GetFileContents(project, project.Name + ".csproj"); - var updatedProjectElement = XElement.Parse(updatedProjectFile); - - Assert.True(updatedProjectElement.Elements() + Assert.True(InvokeFixAndGetProjectFileElement(project).Elements() .Where(e => e.Name.LocalName == "PropertyGroup" && e.Attributes().Any(a => a.Name.LocalName == "Condition")) - .All(g => g.Elements().Single(e => e.Name.LocalName == "LangVersion").Value == "7.1")); + .All(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "LangVersion")?.Value == "7.1")); } } } From 4f90119d8517a492fe82d929d124d12c9c92189e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 8 Apr 2018 03:33:33 +0200 Subject: [PATCH 20/45] Adding test with default template for legacy project --- .../CSharp/CSharpUpdateProjectToAllowUnsafe.cs | 15 ++++++++++++++- .../CSharp/CSharpUpgradeProject.cs | 15 ++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs index e3143dd43d72d..93446d134e06e 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs @@ -49,9 +49,22 @@ public void CPSProject_GeneralPropertyGroupUpdated() .Any(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "AllowUnsafeBlocks")?.Value == "true")); } + [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] + public void LegacyProject_AllConfigurationsUpdated() + { + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); + var project = new ProjectUtils.Project(ProjectName); + + VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.ClassLibrary, LanguageNames.CSharp); + + Assert.True(InvokeFixAndGetProjectFileElement(project).Elements() + .Where(e => e.Name.LocalName == "PropertyGroup" && e.Attributes().Any(a => a.Name.LocalName == "Condition")) + .All(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "AllowUnsafeBlocks")?.Value == "true")); + } + [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpdateProjectToAllowUnsafe)] - public void LegacyProject_AllConfigurationsUpdated() + public void LegacyProject_MultiplePlatforms_AllConfigurationsUpdated() { VisualStudio.SolutionExplorer.CreateSolution(SolutionName); var project = new ProjectUtils.Project(ProjectName); diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs index c5f72dec0a758..30d12e48a6af3 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs @@ -50,13 +50,26 @@ public void CPSProject_GeneralPropertyGroupUpdated() .Any(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "LangVersion")?.Value == "7.1")); } - [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] public void LegacyProject_AllConfigurationsUpdated() { VisualStudio.SolutionExplorer.CreateSolution(SolutionName); var project = new ProjectUtils.Project(ProjectName); + VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.ClassLibrary, LanguageNames.CSharp); + + Assert.True(InvokeFixAndGetProjectFileElement(project).Elements() + .Where(e => e.Name.LocalName == "PropertyGroup" && e.Attributes().Any(a => a.Name.LocalName == "Condition")) + .All(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "LangVersion")?.Value == "7.1")); + } + + [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] + [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] + public void LegacyProject_MultiplePlatforms_AllConfigurationsUpdated() + { + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); + var project = new ProjectUtils.Project(ProjectName); + // Be explicit about 7.0 in Debug|x64 so that this doesn't break when a new major version is released. VisualStudio.SolutionExplorer.AddCustomProject(project, ".csproj", $@" From b56a8018f2faec5bb7604ebdfd98ca7966806b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 8 Apr 2018 04:04:11 +0200 Subject: [PATCH 21/45] Test cleanup --- .../AbstractUpdateProjectTest.cs | 31 +++++++++++++++++++ .../CSharpUpdateProjectToAllowUnsafe.cs | 21 +++++-------- .../CSharp/CSharpUpgradeProject.cs | 21 +++++-------- 3 files changed, 45 insertions(+), 28 deletions(-) create mode 100644 src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs new file mode 100644 index 0000000000000..63d9e6e157f60 --- /dev/null +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Linq; +using System.Xml.Linq; +using Microsoft.VisualStudio.IntegrationTest.Utilities; +using Xunit; + +namespace Roslyn.VisualStudio.IntegrationTests +{ + public abstract class AbstractUpdateProjectTest : AbstractIntegrationTest + { + protected AbstractUpdateProjectTest(VisualStudioInstanceFactory instanceFactory) + : base(instanceFactory) + { + } + + protected void VerifyPropertyOutsideConfiguration(XElement projectElement, string name, string value) + { + Assert.True(projectElement.Elements() + .Where(e => e.Name.LocalName == "PropertyGroup" && !e.Attributes().Any(a => a.Name.LocalName == "Condition")) + .Any(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == name)?.Value == value)); + } + + protected void VerifyPropertyInEachConfiguration(XElement projectElement, string name, string value) + { + Assert.True(projectElement.Elements() + .Where(e => e.Name.LocalName == "PropertyGroup" && e.Attributes().Any(a => a.Name.LocalName == "Condition")) + .All(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == name)?.Value == value)); + } + } +} diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs index 93446d134e06e..e51ae9a699606 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs @@ -1,6 +1,5 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Linq; using System.Xml.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Test.Utilities; @@ -12,7 +11,7 @@ namespace Roslyn.VisualStudio.IntegrationTests.Other { [Collection(nameof(SharedIntegrationHostFixture))] - public class CSharpUpdateProjectToAllowUnsafe : AbstractIntegrationTest + public class CSharpUpdateProjectToAllowUnsafe : AbstractUpdateProjectTest { public CSharpUpdateProjectToAllowUnsafe(VisualStudioInstanceFactory instanceFactory) : base(instanceFactory) { @@ -39,36 +38,32 @@ unsafe class C [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpdateProjectToAllowUnsafe)] public void CPSProject_GeneralPropertyGroupUpdated() { - VisualStudio.SolutionExplorer.CreateSolution(SolutionName); var project = new ProjectUtils.Project(ProjectName); + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.CSharpNetStandardClassLibrary, LanguageNames.CSharp); - Assert.True(InvokeFixAndGetProjectFileElement(project).Elements() - .Where(e => e.Name.LocalName == "PropertyGroup" && !e.Attributes().Any(a => a.Name.LocalName == "Condition")) - .Any(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "AllowUnsafeBlocks")?.Value == "true")); + VerifyPropertyOutsideConfiguration(InvokeFixAndGetProjectFileElement(project), "AllowUnsafeBlocks", "true"); } [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] public void LegacyProject_AllConfigurationsUpdated() { - VisualStudio.SolutionExplorer.CreateSolution(SolutionName); var project = new ProjectUtils.Project(ProjectName); + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.ClassLibrary, LanguageNames.CSharp); - Assert.True(InvokeFixAndGetProjectFileElement(project).Elements() - .Where(e => e.Name.LocalName == "PropertyGroup" && e.Attributes().Any(a => a.Name.LocalName == "Condition")) - .All(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "AllowUnsafeBlocks")?.Value == "true")); + VerifyPropertyInEachConfiguration(InvokeFixAndGetProjectFileElement(project), "AllowUnsafeBlocks", "true"); } [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpdateProjectToAllowUnsafe)] public void LegacyProject_MultiplePlatforms_AllConfigurationsUpdated() { - VisualStudio.SolutionExplorer.CreateSolution(SolutionName); var project = new ProjectUtils.Project(ProjectName); + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); VisualStudio.SolutionExplorer.AddCustomProject(project, ".csproj", $@" @@ -104,9 +99,7 @@ public void LegacyProject_MultiplePlatforms_AllConfigurationsUpdated() "); - Assert.True(InvokeFixAndGetProjectFileElement(project).Elements() - .Where(e => e.Name.LocalName == "PropertyGroup" && e.Attributes().Any(a => a.Name.LocalName == "Condition")) - .All(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "AllowUnsafeBlocks")?.Value == "true")); + VerifyPropertyInEachConfiguration(InvokeFixAndGetProjectFileElement(project), "AllowUnsafeBlocks", "true"); } } } diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs index 30d12e48a6af3..8306ba66ec316 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs @@ -1,6 +1,5 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Linq; using System.Xml.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Test.Utilities; @@ -12,7 +11,7 @@ namespace Roslyn.VisualStudio.IntegrationTests.Other { [Collection(nameof(SharedIntegrationHostFixture))] - public class CSharpUpgradeProject : AbstractIntegrationTest + public class CSharpUpgradeProject : AbstractUpdateProjectTest { public CSharpUpgradeProject(VisualStudioInstanceFactory instanceFactory) : base(instanceFactory) { @@ -40,37 +39,33 @@ class C [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] public void CPSProject_GeneralPropertyGroupUpdated() { - VisualStudio.SolutionExplorer.CreateSolution(SolutionName); var project = new ProjectUtils.Project(ProjectName); + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.CSharpNetStandardClassLibrary, LanguageNames.CSharp); - Assert.True(InvokeFixAndGetProjectFileElement(project).Elements() - .Where(e => e.Name.LocalName == "PropertyGroup" && !e.Attributes().Any(a => a.Name.LocalName == "Condition")) - .Any(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "LangVersion")?.Value == "7.1")); + VerifyPropertyOutsideConfiguration(InvokeFixAndGetProjectFileElement(project), "LangVersion", "7.1"); } [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] public void LegacyProject_AllConfigurationsUpdated() { - VisualStudio.SolutionExplorer.CreateSolution(SolutionName); var project = new ProjectUtils.Project(ProjectName); + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.ClassLibrary, LanguageNames.CSharp); - Assert.True(InvokeFixAndGetProjectFileElement(project).Elements() - .Where(e => e.Name.LocalName == "PropertyGroup" && e.Attributes().Any(a => a.Name.LocalName == "Condition")) - .All(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "LangVersion")?.Value == "7.1")); + VerifyPropertyInEachConfiguration(InvokeFixAndGetProjectFileElement(project), "LangVersion", "7.1"); } [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] public void LegacyProject_MultiplePlatforms_AllConfigurationsUpdated() { - VisualStudio.SolutionExplorer.CreateSolution(SolutionName); var project = new ProjectUtils.Project(ProjectName); // Be explicit about 7.0 in Debug|x64 so that this doesn't break when a new major version is released. + VisualStudio.SolutionExplorer.CreateSolution(SolutionName); VisualStudio.SolutionExplorer.AddCustomProject(project, ".csproj", $@" @@ -106,9 +101,7 @@ public void LegacyProject_MultiplePlatforms_AllConfigurationsUpdated() "); - Assert.True(InvokeFixAndGetProjectFileElement(project).Elements() - .Where(e => e.Name.LocalName == "PropertyGroup" && e.Attributes().Any(a => a.Name.LocalName == "Condition")) - .All(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == "LangVersion")?.Value == "7.1")); + VerifyPropertyInEachConfiguration(InvokeFixAndGetProjectFileElement(project), "LangVersion", "7.1"); } } } From 06c8c5ef652a4603e1fb48286a79430175478666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 8 Apr 2018 04:29:37 +0200 Subject: [PATCH 22/45] More test cleanup --- .../AbstractUpdateProjectTest.cs | 15 +++++++++++++-- .../CSharp/CSharpUpdateProjectToAllowUnsafe.cs | 18 +++++++----------- .../CSharp/CSharpUpgradeProject.cs | 18 +++++++----------- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs index 63d9e6e157f60..9cbcb39f4877d 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs @@ -1,9 +1,11 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.IO; using System.Linq; using System.Xml.Linq; using Microsoft.VisualStudio.IntegrationTest.Utilities; using Xunit; +using ProjectUtils = Microsoft.VisualStudio.IntegrationTest.Utilities.Common.ProjectUtils; namespace Roslyn.VisualStudio.IntegrationTests { @@ -14,14 +16,23 @@ protected AbstractUpdateProjectTest(VisualStudioInstanceFactory instanceFactory) { } - protected void VerifyPropertyOutsideConfiguration(XElement projectElement, string name, string value) + protected XElement GetProjectFileElement(ProjectUtils.Project project) + { + // Save the project file. + VisualStudio.SolutionExplorer.SaveAll(); + + var projectFileContent = VisualStudio.SolutionExplorer.GetFileContents(project, Path.GetFileName(project.RelativePath)); + return XElement.Parse(projectFileContent); + } + + protected static void VerifyPropertyOutsideConfiguration(XElement projectElement, string name, string value) { Assert.True(projectElement.Elements() .Where(e => e.Name.LocalName == "PropertyGroup" && !e.Attributes().Any(a => a.Name.LocalName == "Condition")) .Any(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == name)?.Value == value)); } - protected void VerifyPropertyInEachConfiguration(XElement projectElement, string name, string value) + protected static void VerifyPropertyInEachConfiguration(XElement projectElement, string name, string value) { Assert.True(projectElement.Elements() .Where(e => e.Name.LocalName == "PropertyGroup" && e.Attributes().Any(a => a.Name.LocalName == "Condition")) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs index e51ae9a699606..04a00b69d5c18 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs @@ -1,6 +1,5 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Xml.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.VisualStudio.IntegrationTest.Utilities; @@ -17,7 +16,7 @@ public CSharpUpdateProjectToAllowUnsafe(VisualStudioInstanceFactory instanceFact { } - private XElement InvokeFixAndGetProjectFileElement(ProjectUtils.Project project) + private void InvokeFixFromNewFile(ProjectUtils.Project project) { VisualStudio.SolutionExplorer.AddFile(project, "C.cs", @" unsafe class C @@ -27,12 +26,6 @@ unsafe class C VisualStudio.Editor.PlaceCaret("C"); VisualStudio.Editor.InvokeCodeActionList(); VisualStudio.Editor.Verify.CodeAction("Allow unsafe code in this project", applyFix: true); - - // Save the project file. - VisualStudio.SolutionExplorer.SaveAll(); - - var updatedProjectFile = VisualStudio.SolutionExplorer.GetFileContents(project, project.Name + ".csproj"); - return XElement.Parse(updatedProjectFile); } [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpdateProjectToAllowUnsafe)] @@ -43,7 +36,8 @@ public void CPSProject_GeneralPropertyGroupUpdated() VisualStudio.SolutionExplorer.CreateSolution(SolutionName); VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.CSharpNetStandardClassLibrary, LanguageNames.CSharp); - VerifyPropertyOutsideConfiguration(InvokeFixAndGetProjectFileElement(project), "AllowUnsafeBlocks", "true"); + InvokeFixFromNewFile(project); + VerifyPropertyOutsideConfiguration(GetProjectFileElement(project), "AllowUnsafeBlocks", "true"); } [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] @@ -54,7 +48,8 @@ public void LegacyProject_AllConfigurationsUpdated() VisualStudio.SolutionExplorer.CreateSolution(SolutionName); VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.ClassLibrary, LanguageNames.CSharp); - VerifyPropertyInEachConfiguration(InvokeFixAndGetProjectFileElement(project), "AllowUnsafeBlocks", "true"); + InvokeFixFromNewFile(project); + VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "AllowUnsafeBlocks", "true"); } [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] @@ -99,7 +94,8 @@ public void LegacyProject_MultiplePlatforms_AllConfigurationsUpdated() "); - VerifyPropertyInEachConfiguration(InvokeFixAndGetProjectFileElement(project), "AllowUnsafeBlocks", "true"); + InvokeFixFromNewFile(project); + VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "AllowUnsafeBlocks", "true"); } } } diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs index 8306ba66ec316..9f60665141d1c 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs @@ -1,6 +1,5 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Xml.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.VisualStudio.IntegrationTest.Utilities; @@ -17,7 +16,7 @@ public CSharpUpgradeProject(VisualStudioInstanceFactory instanceFactory) : base( { } - private XElement InvokeFixAndGetProjectFileElement(ProjectUtils.Project project) + private void InvokeFixFromNewFile(ProjectUtils.Project project) { VisualStudio.SolutionExplorer.AddFile(project, "C.cs", @" class C @@ -28,12 +27,6 @@ class C VisualStudio.Editor.PlaceCaret("default"); VisualStudio.Editor.InvokeCodeActionList(); VisualStudio.Editor.Verify.CodeAction("Upgrade this project to C# language version '7.1'", applyFix: true); - - // Save the project file. - VisualStudio.SolutionExplorer.SaveAll(); - - var updatedProjectFile = VisualStudio.SolutionExplorer.GetFileContents(project, project.Name + ".csproj"); - return XElement.Parse(updatedProjectFile); } [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] @@ -44,7 +37,8 @@ public void CPSProject_GeneralPropertyGroupUpdated() VisualStudio.SolutionExplorer.CreateSolution(SolutionName); VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.CSharpNetStandardClassLibrary, LanguageNames.CSharp); - VerifyPropertyOutsideConfiguration(InvokeFixAndGetProjectFileElement(project), "LangVersion", "7.1"); + InvokeFixFromNewFile(project); + VerifyPropertyOutsideConfiguration(GetProjectFileElement(project), "LangVersion", "7.1"); } [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] @@ -55,7 +49,8 @@ public void LegacyProject_AllConfigurationsUpdated() VisualStudio.SolutionExplorer.CreateSolution(SolutionName); VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.ClassLibrary, LanguageNames.CSharp); - VerifyPropertyInEachConfiguration(InvokeFixAndGetProjectFileElement(project), "LangVersion", "7.1"); + InvokeFixFromNewFile(project); + VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "LangVersion", "7.1"); } [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] @@ -101,7 +96,8 @@ public void LegacyProject_MultiplePlatforms_AllConfigurationsUpdated() "); - VerifyPropertyInEachConfiguration(InvokeFixAndGetProjectFileElement(project), "LangVersion", "7.1"); + InvokeFixFromNewFile(project); + VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "LangVersion", "7.1"); } } } From 82c43421aec576c6d6e102ca00a55786e19b2e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 8 Apr 2018 12:22:05 +0200 Subject: [PATCH 23/45] Fixing trait --- .../IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs index 04a00b69d5c18..2923fe40b5be8 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs @@ -40,7 +40,7 @@ public void CPSProject_GeneralPropertyGroupUpdated() VerifyPropertyOutsideConfiguration(GetProjectFileElement(project), "AllowUnsafeBlocks", "true"); } - [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] + [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpdateProjectToAllowUnsafe)] public void LegacyProject_AllConfigurationsUpdated() { var project = new ProjectUtils.Project(ProjectName); From 50c3160fbe47de302ebc6ecfdb778e2dc12547b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Thu, 12 Apr 2018 22:37:31 +0200 Subject: [PATCH 24/45] Using deconstruction --- .../UpdateProjectToAllowUnsafeTests.cs | 5 ++--- .../Diagnostics/UpgradeProject/UpgradeProjectTests.cs | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs index 49eef8f5348cb..8ab3c30a351dd 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Linq; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; @@ -25,9 +26,7 @@ private async Task TestAllowUnsafeEnabledIfDisabledAsync(string initialMarkup) var actions = await GetCodeActionsAsync(workspace, parameters); var operations = await VerifyInputsAndGetOperationsAsync(0, actions, priority: null); - var appliedChanges = ApplyOperationsAndGetSolution(workspace, operations); - var oldSolution = appliedChanges.Item1; - var newSolution = appliedChanges.Item2; + var (oldSolution, newSolution) = ApplyOperationsAndGetSolution(workspace, operations); Assert.True(((CSharpCompilationOptions)newSolution.Projects.Single().CompilationOptions).AllowUnsafe); } diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs index 0ee1b798f8cba..0fc8cd4093a98 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Linq; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; @@ -29,9 +30,7 @@ private async Task TestLanguageVersionUpgradedAsync( var actions = await GetCodeActionsAsync(workspace, parameters); var operations = await VerifyInputsAndGetOperationsAsync(index, actions, priority: null); - var appliedChanges = ApplyOperationsAndGetSolution(workspace, operations); - var oldSolution = appliedChanges.Item1; - var newSolution = appliedChanges.Item2; + var (oldSolution, newSolution) = ApplyOperationsAndGetSolution(workspace, operations); Assert.All(newSolution.Projects.Where(p => p.Language == LanguageNames.CSharp), p => Assert.Equal(expected, ((CSharpParseOptions)p.ParseOptions).SpecifiedLanguageVersion)); } From 28f3ee0d27a88bf412b16837832ab626baec3108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Fri, 20 Apr 2018 19:09:19 +0200 Subject: [PATCH 25/45] Addressing feedback --- .../TestWorkspace_XmlConsumption.cs | 2 +- ...dioWorkspaceImpl.ProjectPropertyStorage.cs | 2 +- .../VisualStudioWorkspaceImpl.cs | 4 ++-- .../AbstractUpdateProjectTest.cs | 21 +++++++++++++------ 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs index 31ed16d4237db..6c29bb054d919 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs @@ -466,7 +466,7 @@ private static CompilationOptions CreateCompilationOptions(TestWorkspace workspa var strongNameProvider = default(StrongNameProvider); var delaySign = default(bool?); var checkOverflow = false; - bool allowUnsafe = false; + var allowUnsafe = false; if (compilationOptionsElement != null) { diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs index dab7030808d8a..c2bc68ddcc210 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs @@ -13,7 +13,7 @@ internal partial class VisualStudioWorkspaceImpl { private abstract class ProjectPropertyStorage { - public static ProjectPropertyStorage Get(Project project, IServiceProvider serviceProvider) + public static ProjectPropertyStorage Create(Project project, IServiceProvider serviceProvider) { var solution = (IVsSolution)serviceProvider.GetService(typeof(SVsSolution)); solution.GetProjectOfUniqueName(project.UniqueName, out var hierarchy); diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs index 095ace96479ac..dd81478fad64e 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs @@ -329,7 +329,7 @@ protected override void ApplyCompilationOptionsChanged(ProjectId projectId, Comp throw new ArgumentNullException(nameof(options)); } - var storage = ProjectPropertyStorage.Get(TryGetDTEProject(projectId), DeferredState.ServiceProvider); + var storage = ProjectPropertyStorage.Create(TryGetDTEProject(projectId), DeferredState.ServiceProvider); switch (options) { @@ -354,7 +354,7 @@ protected override void ApplyParseOptionsChanged(ProjectId projectId, ParseOptio throw new ArgumentNullException(nameof(options)); } - var storage = ProjectPropertyStorage.Get(TryGetDTEProject(projectId), DeferredState.ServiceProvider); + var storage = ProjectPropertyStorage.Create(TryGetDTEProject(projectId), DeferredState.ServiceProvider); switch (options) { diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs index 9cbcb39f4877d..12c9be093dd09 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs @@ -27,16 +27,25 @@ protected XElement GetProjectFileElement(ProjectUtils.Project project) protected static void VerifyPropertyOutsideConfiguration(XElement projectElement, string name, string value) { - Assert.True(projectElement.Elements() - .Where(e => e.Name.LocalName == "PropertyGroup" && !e.Attributes().Any(a => a.Name.LocalName == "Condition")) - .Any(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == name)?.Value == value)); + Assert.Contains( + projectElement.Elements().Where(IsUnconditionalPropertyGroup), + group => GetPropertyValue(group, name) == value); + + bool IsUnconditionalPropertyGroup(XElement element) + => element.Name.LocalName == "PropertyGroup" && !element.Attributes().Any(a => a.Name.LocalName == "Condition"); } protected static void VerifyPropertyInEachConfiguration(XElement projectElement, string name, string value) { - Assert.True(projectElement.Elements() - .Where(e => e.Name.LocalName == "PropertyGroup" && e.Attributes().Any(a => a.Name.LocalName == "Condition")) - .All(g => g.Elements().SingleOrDefault(e => e.Name.LocalName == name)?.Value == value)); + Assert.All( + projectElement.Elements().Where(IsConditionalPropertyGroup), + group => Assert.Equal(value, GetPropertyValue(group, name))); + + bool IsConditionalPropertyGroup(XElement element) + => element.Name.LocalName == "PropertyGroup" && element.Attributes().Any(a => a.Name.LocalName == "Condition"); } + + private static string GetPropertyValue(XElement propertyGroup, string propertyName) + => propertyGroup.Elements().SingleOrDefault(e => e.Name.LocalName == propertyName)?.Value; } } From 1482394273278ab77f3ed075570807f445c81eca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Fri, 20 Apr 2018 21:43:36 +0200 Subject: [PATCH 26/45] Trying to fix flaky tests --- .../IntegrationTests/AbstractUpdateProjectTest.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs index 12c9be093dd09..7492b82a8dace 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Xml.Linq; +using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.IntegrationTest.Utilities; using Xunit; using ProjectUtils = Microsoft.VisualStudio.IntegrationTest.Utilities.Common.ProjectUtils; @@ -20,6 +21,7 @@ protected XElement GetProjectFileElement(ProjectUtils.Project project) { // Save the project file. VisualStudio.SolutionExplorer.SaveAll(); + VisualStudio.Workspace.WaitForAsyncOperations(FeatureAttribute.Workspace); var projectFileContent = VisualStudio.SolutionExplorer.GetFileContents(project, Path.GetFileName(project.RelativePath)); return XElement.Parse(projectFileContent); From 46e9abd2343cc87abb4769d43e94cf970a2a33e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Fri, 20 Apr 2018 22:53:06 +0200 Subject: [PATCH 27/45] Trying different fix --- .../IntegrationTests/AbstractUpdateProjectTest.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs index 7492b82a8dace..66e522827ea2e 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs @@ -3,7 +3,6 @@ using System.IO; using System.Linq; using System.Xml.Linq; -using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.IntegrationTest.Utilities; using Xunit; using ProjectUtils = Microsoft.VisualStudio.IntegrationTest.Utilities.Common.ProjectUtils; @@ -21,7 +20,7 @@ protected XElement GetProjectFileElement(ProjectUtils.Project project) { // Save the project file. VisualStudio.SolutionExplorer.SaveAll(); - VisualStudio.Workspace.WaitForAsyncOperations(FeatureAttribute.Workspace); + VisualStudio.WaitForApplicationIdle(cancellationToken: default); var projectFileContent = VisualStudio.SolutionExplorer.GetFileContents(project, Path.GetFileName(project.RelativePath)); return XElement.Parse(projectFileContent); From cdb4dcf678960d397af8ffcc20669c66859453c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Fri, 20 Apr 2018 22:55:30 +0200 Subject: [PATCH 28/45] Simplifying configuration property access --- .../VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs index c2bc68ddcc210..7be79f3b3065c 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs @@ -1,11 +1,9 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Linq; using EnvDTE; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; -using Roslyn.Utilities; namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem { @@ -49,7 +47,7 @@ public override void SetProperty(string buildPropertyName, string configurationP { foreach (Configuration configuration in configurationManager) { - configuration.Properties.Cast().First(property => property.Name == configurationPropertyName).Value = value; + configuration.Properties.Item(configurationPropertyName).Value = value; } } } From 613e5132c308487b757c151cf5542e387b42c070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sat, 26 May 2018 16:34:51 +0200 Subject: [PATCH 29/45] Fix after merge --- .../UpdateProjectToAllowUnsafeTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs index 8ab3c30a351dd..23d734ea04224 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/UpdateProjectToAllowUnsafe/UpdateProjectToAllowUnsafeTests.cs @@ -23,8 +23,8 @@ private async Task TestAllowUnsafeEnabledIfDisabledAsync(string initialMarkup) var parameters = new TestParameters(); using (var workspace = CreateWorkspaceFromOptions(initialMarkup, parameters)) { - var actions = await GetCodeActionsAsync(workspace, parameters); - var operations = await VerifyInputsAndGetOperationsAsync(0, actions, priority: null); + var (_, action) = await GetCodeActionsAsync(workspace, parameters); + var operations = await VerifyActionAndGetOperationsAsync(action, default); var (oldSolution, newSolution) = ApplyOperationsAndGetSolution(workspace, operations); Assert.True(((CSharpCompilationOptions)newSolution.Projects.Single().CompilationOptions).AllowUnsafe); From 99046c640e743c782a89feadc18fc929c23f5d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Mon, 24 Sep 2018 18:50:18 +0200 Subject: [PATCH 30/45] Fixing namespace for integration tests --- .../IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs | 2 +- .../IntegrationTests/CSharp/CSharpUpgradeProject.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs index 2923fe40b5be8..8082c524e8f10 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs @@ -7,7 +7,7 @@ using Xunit; using ProjectUtils = Microsoft.VisualStudio.IntegrationTest.Utilities.Common.ProjectUtils; -namespace Roslyn.VisualStudio.IntegrationTests.Other +namespace Roslyn.VisualStudio.IntegrationTests.CSharp { [Collection(nameof(SharedIntegrationHostFixture))] public class CSharpUpdateProjectToAllowUnsafe : AbstractUpdateProjectTest diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs index 9f60665141d1c..eef2109ff983b 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs @@ -7,7 +7,7 @@ using Xunit; using ProjectUtils = Microsoft.VisualStudio.IntegrationTest.Utilities.Common.ProjectUtils; -namespace Roslyn.VisualStudio.IntegrationTests.Other +namespace Roslyn.VisualStudio.IntegrationTests.CSharp { [Collection(nameof(SharedIntegrationHostFixture))] public class CSharpUpgradeProject : AbstractUpdateProjectTest From 139944e4353bb922e10d96e2cd0ffce829481c15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Mon, 24 Sep 2018 19:18:11 +0200 Subject: [PATCH 31/45] Removing WaitForApplicationIdle --- .../IntegrationTests/AbstractUpdateProjectTest.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs index 66e522827ea2e..12c9be093dd09 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/AbstractUpdateProjectTest.cs @@ -20,7 +20,6 @@ protected XElement GetProjectFileElement(ProjectUtils.Project project) { // Save the project file. VisualStudio.SolutionExplorer.SaveAll(); - VisualStudio.WaitForApplicationIdle(cancellationToken: default); var projectFileContent = VisualStudio.SolutionExplorer.GetFileContents(project, Path.GetFileName(project.RelativePath)); return XElement.Parse(projectFileContent); From 2b7dd403ea21b82c358044f46b4fb2073bd76d00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Tue, 25 Sep 2018 14:06:58 +0200 Subject: [PATCH 32/45] Making upgrade project integration tests future-proof Using #error version should ensure that integration tests that use the default new project template will continue working when the default language version becomes C# 8 --- .../CSharp/CSharpUpgradeProject.cs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs index eef2109ff983b..7e7a07d241e3c 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs @@ -19,14 +19,12 @@ public CSharpUpgradeProject(VisualStudioInstanceFactory instanceFactory) : base( private void InvokeFixFromNewFile(ProjectUtils.Project project) { VisualStudio.SolutionExplorer.AddFile(project, "C.cs", @" -class C -{ - int i = default; -}", open: true); +#error version:latest +", open: true); - VisualStudio.Editor.PlaceCaret("default"); + VisualStudio.Editor.PlaceCaret("version:latest"); VisualStudio.Editor.InvokeCodeActionList(); - VisualStudio.Editor.Verify.CodeAction("Upgrade this project to C# language version '7.1'", applyFix: true); + VisualStudio.Editor.Verify.CodeAction("Upgrade this project to C# language version 'latest'", applyFix: true); } [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] @@ -38,7 +36,7 @@ public void CPSProject_GeneralPropertyGroupUpdated() VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.CSharpNetStandardClassLibrary, LanguageNames.CSharp); InvokeFixFromNewFile(project); - VerifyPropertyOutsideConfiguration(GetProjectFileElement(project), "LangVersion", "7.1"); + VerifyPropertyOutsideConfiguration(GetProjectFileElement(project), "LangVersion", "latest"); } [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)] @@ -50,7 +48,7 @@ public void LegacyProject_AllConfigurationsUpdated() VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.ClassLibrary, LanguageNames.CSharp); InvokeFixFromNewFile(project); - VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "LangVersion", "7.1"); + VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "LangVersion", "latest"); } [WorkItem(23342, "https://github.com/dotnet/roslyn/issues/23342")] @@ -59,7 +57,6 @@ public void LegacyProject_MultiplePlatforms_AllConfigurationsUpdated() { var project = new ProjectUtils.Project(ProjectName); - // Be explicit about 7.0 in Debug|x64 so that this doesn't break when a new major version is released. VisualStudio.SolutionExplorer.CreateSolution(SolutionName); VisualStudio.SolutionExplorer.AddCustomProject(project, ".csproj", $@" @@ -97,7 +94,7 @@ public void LegacyProject_MultiplePlatforms_AllConfigurationsUpdated() "); InvokeFixFromNewFile(project); - VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "LangVersion", "7.1"); + VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "LangVersion", "latest"); } } } From 461e397be017bde6704b032ffe9b899e4f476649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Tue, 25 Sep 2018 15:54:24 +0200 Subject: [PATCH 33/45] Adding an explanatory comment to ProjectPropertyStorage --- ...alStudioWorkspaceImpl.ProjectPropertyStorage.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs index 7be79f3b3065c..9e30fa7ce2b87 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs @@ -11,6 +11,20 @@ internal partial class VisualStudioWorkspaceImpl { private abstract class ProjectPropertyStorage { + // For CPS projects, we prefer to use IVsBuildPropertyStorage since that allows us to easily modify the project + // properties independent of configuration. However this is problematic in the legacy project system, where setting + // the build property would indeed change its value, however that change would only be visible after the project is + // unloaded and reloaded. The language service would not be updated (the error we're trying to fix would still + // be visible) and any checkbox in the project properties dialog would not be updated. The language service issue + // could be worked around by using VSProject.Refresh, but that does not fix the project properties dialog. Therefore + // for the legacy project system, we choose to use ConfigurationManager to iterate & update each configuration, + // which works correctly, even though it is a little less convinient because it creates a more verbose project file + // (although we're dealing with a legacy project file... it's already verbose anyway). + + // It's important to note that the property name may differ in these two implementations. The build property name + // corresponds to the name of the property in the project file (for example LangVersion), whereas the configuration + // property name comes from an interface such as CSharpProjectConfigurationProperties3 (for example LanguageVersion). + public static ProjectPropertyStorage Create(Project project, IServiceProvider serviceProvider) { var solution = (IVsSolution)serviceProvider.GetService(typeof(SVsSolution)); From 48bb6d8ed5fe2f612518729c456f3030b6b5488b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Tue, 25 Sep 2018 19:04:37 +0200 Subject: [PATCH 34/45] Fixing name violation --- ...sualStudioWorkspaceImpl.ProjectPropertyStorage.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs index 9e30fa7ce2b87..bc6d94be0e628 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs @@ -39,27 +39,27 @@ public static ProjectPropertyStorage Create(Project project, IServiceProvider se private sealed class BuildPropertyStorage : ProjectPropertyStorage { - private readonly IVsBuildPropertyStorage propertyStorage; + private readonly IVsBuildPropertyStorage _propertyStorage; public BuildPropertyStorage(IVsBuildPropertyStorage propertyStorage) - => this.propertyStorage = propertyStorage; + => this._propertyStorage = propertyStorage; public override void SetProperty(string buildPropertyName, string configurationPropertyName, string value) { - propertyStorage.SetPropertyValue(buildPropertyName, null, (uint)_PersistStorageType.PST_PROJECT_FILE, value); + _propertyStorage.SetPropertyValue(buildPropertyName, null, (uint)_PersistStorageType.PST_PROJECT_FILE, value); } } private sealed class PerConfigurationPropertyStorage : ProjectPropertyStorage { - private readonly ConfigurationManager configurationManager; + private readonly ConfigurationManager _configurationManager; public PerConfigurationPropertyStorage(ConfigurationManager configurationManager) - => this.configurationManager = configurationManager; + => this._configurationManager = configurationManager; public override void SetProperty(string buildPropertyName, string configurationPropertyName, string value) { - foreach (Configuration configuration in configurationManager) + foreach (Configuration configuration in _configurationManager) { configuration.Properties.Item(configurationPropertyName).Value = value; } From a930d92dfc8c464db5c96300ee260d4261750068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Wed, 26 Sep 2018 12:53:02 +0200 Subject: [PATCH 35/45] Running integration tests that use a project template in the existing C# file as opposed to creating a new one --- .../CSharp/CSharpUpdateProjectToAllowUnsafe.cs | 15 +++++++++------ .../CSharp/CSharpUpgradeProject.cs | 15 +++++++++------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs index 8082c524e8f10..9fce22cc0a8d0 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpdateProjectToAllowUnsafe.cs @@ -16,12 +16,13 @@ public CSharpUpdateProjectToAllowUnsafe(VisualStudioInstanceFactory instanceFact { } - private void InvokeFixFromNewFile(ProjectUtils.Project project) + private void InvokeFix() { - VisualStudio.SolutionExplorer.AddFile(project, "C.cs", @" + VisualStudio.Editor.SetText(@" unsafe class C { -}", open: true); +}"); + VisualStudio.Editor.Activate(); VisualStudio.Editor.PlaceCaret("C"); VisualStudio.Editor.InvokeCodeActionList(); @@ -36,7 +37,7 @@ public void CPSProject_GeneralPropertyGroupUpdated() VisualStudio.SolutionExplorer.CreateSolution(SolutionName); VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.CSharpNetStandardClassLibrary, LanguageNames.CSharp); - InvokeFixFromNewFile(project); + InvokeFix(); VerifyPropertyOutsideConfiguration(GetProjectFileElement(project), "AllowUnsafeBlocks", "true"); } @@ -48,7 +49,7 @@ public void LegacyProject_AllConfigurationsUpdated() VisualStudio.SolutionExplorer.CreateSolution(SolutionName); VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.ClassLibrary, LanguageNames.CSharp); - InvokeFixFromNewFile(project); + InvokeFix(); VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "AllowUnsafeBlocks", "true"); } @@ -94,7 +95,9 @@ public void LegacyProject_MultiplePlatforms_AllConfigurationsUpdated() "); - InvokeFixFromNewFile(project); + VisualStudio.SolutionExplorer.AddFile(project, "C.cs", open: true); + + InvokeFix(); VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "AllowUnsafeBlocks", "true"); } } diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs index 7e7a07d241e3c..7e3550a2f98f5 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpUpgradeProject.cs @@ -16,11 +16,12 @@ public CSharpUpgradeProject(VisualStudioInstanceFactory instanceFactory) : base( { } - private void InvokeFixFromNewFile(ProjectUtils.Project project) + private void InvokeFix() { - VisualStudio.SolutionExplorer.AddFile(project, "C.cs", @" + VisualStudio.Editor.SetText(@" #error version:latest -", open: true); +"); + VisualStudio.Editor.Activate(); VisualStudio.Editor.PlaceCaret("version:latest"); VisualStudio.Editor.InvokeCodeActionList(); @@ -35,7 +36,7 @@ public void CPSProject_GeneralPropertyGroupUpdated() VisualStudio.SolutionExplorer.CreateSolution(SolutionName); VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.CSharpNetStandardClassLibrary, LanguageNames.CSharp); - InvokeFixFromNewFile(project); + InvokeFix(); VerifyPropertyOutsideConfiguration(GetProjectFileElement(project), "LangVersion", "latest"); } @@ -47,7 +48,7 @@ public void LegacyProject_AllConfigurationsUpdated() VisualStudio.SolutionExplorer.CreateSolution(SolutionName); VisualStudio.SolutionExplorer.AddProject(project, WellKnownProjectTemplates.ClassLibrary, LanguageNames.CSharp); - InvokeFixFromNewFile(project); + InvokeFix(); VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "LangVersion", "latest"); } @@ -93,7 +94,9 @@ public void LegacyProject_MultiplePlatforms_AllConfigurationsUpdated() "); - InvokeFixFromNewFile(project); + VisualStudio.SolutionExplorer.AddFile(project, "C.cs", open: true); + + InvokeFix(); VerifyPropertyInEachConfiguration(GetProjectFileElement(project), "LangVersion", "latest"); } } From 7e2746db425f40edce3a950e3b8b7d016d0c73dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sat, 20 Oct 2018 09:34:31 +0200 Subject: [PATCH 36/45] Simplifying after merge --- .../ProjectSystem/VisualStudioWorkspaceImpl.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs index 31d9e1d608f03..3c73542465db5 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs @@ -438,13 +438,14 @@ protected override void ApplyCompilationOptionsChanged(ProjectId projectId, Comp throw new ArgumentNullException(nameof(options)); } - var compilationOptionsService = CurrentSolution.GetProject(projectId).LanguageServices.GetService(); + var project = CurrentSolution.GetProject(projectId); + + var compilationOptionsService = project.LanguageServices.GetService(); Contract.ThrowIfNull(compilationOptionsService, nameof(compilationOptionsService)); var storage = ProjectPropertyStorage.Create(TryGetDTEProject(projectId), ServiceProvider.GlobalProvider); - GetProjectData(projectId, out var hierarchy, out var project); - switch (CurrentSolution.GetProject(projectId).Language) + switch (project.Language) { case LanguageNames.CSharp: storage.SetProperty("AllowUnsafeBlocks", nameof(ProjectConfigurationProperties3.AllowUnsafeBlocks), @@ -467,13 +468,14 @@ protected override void ApplyParseOptionsChanged(ProjectId projectId, ParseOptio throw new ArgumentNullException(nameof(options)); } - var parseOptionsService = CurrentSolution.GetProject(projectId).LanguageServices.GetService(); + var project = CurrentSolution.GetProject(projectId); + + var parseOptionsService = project.LanguageServices.GetService(); Contract.ThrowIfNull(parseOptionsService, nameof(parseOptionsService)); var storage = ProjectPropertyStorage.Create(TryGetDTEProject(projectId), ServiceProvider.GlobalProvider); - GetProjectData(projectId, out var hierarchy, out var project); - switch (CurrentSolution.GetProject(projectId).Language) + switch (project.Language) { case LanguageNames.CSharp: storage.SetProperty("LangVersion", nameof(CSharpProjectConfigurationProperties3.LanguageVersion), From ec87d24c6a7fdc9938a4378c08a7b86e49af3b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Thu, 6 Dec 2018 21:29:40 +0100 Subject: [PATCH 37/45] Moving IParseOptionsService & ICompilationOptionsService to Microsoft.VisualStudio.LanguageServices --- .../Impl/Utilities}/CSharpCompilationOptionsService.cs | 6 ++++-- .../CSharp/Impl/Utilities}/CSharpParseOptionsService.cs | 6 ++++-- .../Core/Def/Utilities}/ICompilationOptionsService.cs | 5 ++++- .../Core/Def/Utilities}/IParseOptionsService.cs | 5 ++++- 4 files changed, 16 insertions(+), 6 deletions(-) rename src/{Workspaces/CSharp/Portable/LanguageServices => VisualStudio/CSharp/Impl/Utilities}/CSharpCompilationOptionsService.cs (79%) rename src/{Workspaces/CSharp/Portable/LanguageServices => VisualStudio/CSharp/Impl/Utilities}/CSharpParseOptionsService.cs (82%) rename src/{Workspaces/Core/Portable/Workspace/Host/ParseOptions => VisualStudio/Core/Def/Utilities}/ICompilationOptionsService.cs (77%) rename src/{Workspaces/Core/Portable/Workspace/Host/ParseOptions => VisualStudio/Core/Def/Utilities}/IParseOptionsService.cs (74%) diff --git a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpCompilationOptionsService.cs b/src/VisualStudio/CSharp/Impl/Utilities/CSharpCompilationOptionsService.cs similarity index 79% rename from src/Workspaces/CSharp/Portable/LanguageServices/CSharpCompilationOptionsService.cs rename to src/VisualStudio/CSharp/Impl/Utilities/CSharpCompilationOptionsService.cs index c750bf0f6b17e..4a8e6bbc2ebf7 100644 --- a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpCompilationOptionsService.cs +++ b/src/VisualStudio/CSharp/Impl/Utilities/CSharpCompilationOptionsService.cs @@ -1,10 +1,12 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Composition; -using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.VisualStudio.LanguageServices.Utilities; -namespace Microsoft.CodeAnalysis.CSharp +namespace Microsoft.VisualStudio.LanguageServices.CSharp.Utilities { [ExportLanguageService(typeof(ICompilationOptionsService), LanguageNames.CSharp), Shared] internal class CSharpCompilationOptionsService : ICompilationOptionsService diff --git a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpParseOptionsService.cs b/src/VisualStudio/CSharp/Impl/Utilities/CSharpParseOptionsService.cs similarity index 82% rename from src/Workspaces/CSharp/Portable/LanguageServices/CSharpParseOptionsService.cs rename to src/VisualStudio/CSharp/Impl/Utilities/CSharpParseOptionsService.cs index 91f30fe11dcbc..d1129da70d833 100644 --- a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpParseOptionsService.cs +++ b/src/VisualStudio/CSharp/Impl/Utilities/CSharpParseOptionsService.cs @@ -1,11 +1,13 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Composition; -using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.VisualStudio.LanguageServices.Utilities; using Roslyn.Utilities; -namespace Microsoft.CodeAnalysis.CSharp +namespace Microsoft.VisualStudio.LanguageServices.CSharp.Utilities { [ExportLanguageService(typeof(IParseOptionsService), LanguageNames.CSharp), Shared] internal class CSharpParseOptionsService : IParseOptionsService diff --git a/src/Workspaces/Core/Portable/Workspace/Host/ParseOptions/ICompilationOptionsService.cs b/src/VisualStudio/Core/Def/Utilities/ICompilationOptionsService.cs similarity index 77% rename from src/Workspaces/Core/Portable/Workspace/Host/ParseOptions/ICompilationOptionsService.cs rename to src/VisualStudio/Core/Def/Utilities/ICompilationOptionsService.cs index c6aac26640c5b..59885a768641d 100644 --- a/src/Workspaces/Core/Portable/Workspace/Host/ParseOptions/ICompilationOptionsService.cs +++ b/src/VisualStudio/Core/Def/Utilities/ICompilationOptionsService.cs @@ -1,6 +1,9 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.CodeAnalysis.Host +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Host; + +namespace Microsoft.VisualStudio.LanguageServices.Utilities { internal interface ICompilationOptionsService : ILanguageService { diff --git a/src/Workspaces/Core/Portable/Workspace/Host/ParseOptions/IParseOptionsService.cs b/src/VisualStudio/Core/Def/Utilities/IParseOptionsService.cs similarity index 74% rename from src/Workspaces/Core/Portable/Workspace/Host/ParseOptions/IParseOptionsService.cs rename to src/VisualStudio/Core/Def/Utilities/IParseOptionsService.cs index 7050105b191eb..be2ab3394079a 100644 --- a/src/Workspaces/Core/Portable/Workspace/Host/ParseOptions/IParseOptionsService.cs +++ b/src/VisualStudio/Core/Def/Utilities/IParseOptionsService.cs @@ -1,6 +1,9 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.CodeAnalysis.Host +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Host; + +namespace Microsoft.VisualStudio.LanguageServices.Utilities { internal interface IParseOptionsService : ILanguageService { From b30466086e04f094b777b99387129d54e746d6c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Thu, 6 Dec 2018 23:30:06 +0100 Subject: [PATCH 38/45] Adding IParseOptionsChangingService and ICompilationOptionsChangingService --- ...isualStudio.LanguageServices.CSharp.csproj | 1 + ...CSharpCompilationOptionsChangingService.cs | 32 +++++++++ .../CSharpCompilationOptionsService.cs | 22 ------ .../CSharpParseOptionsChangingService.cs | 32 +++++++++ .../Utilities/CSharpParseOptionsService.cs | 26 ------- ...dioWorkspaceImpl.ProjectPropertyStorage.cs | 70 ------------------ .../VisualStudioWorkspaceImpl.cs | 54 +++++--------- ... => ICompilationOptionsChangingService.cs} | 8 +-- ...ice.cs => IParseOptionsChangingService.cs} | 7 +- .../Def/Utilities/ProjectPropertyStorage.cs | 71 +++++++++++++++++++ 10 files changed, 161 insertions(+), 162 deletions(-) create mode 100644 src/VisualStudio/CSharp/Impl/Utilities/CSharpCompilationOptionsChangingService.cs delete mode 100644 src/VisualStudio/CSharp/Impl/Utilities/CSharpCompilationOptionsService.cs create mode 100644 src/VisualStudio/CSharp/Impl/Utilities/CSharpParseOptionsChangingService.cs delete mode 100644 src/VisualStudio/CSharp/Impl/Utilities/CSharpParseOptionsService.cs delete mode 100644 src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs rename src/VisualStudio/Core/Def/Utilities/{ICompilationOptionsService.cs => ICompilationOptionsChangingService.cs} (55%) rename src/VisualStudio/Core/Def/Utilities/{IParseOptionsService.cs => IParseOptionsChangingService.cs} (57%) create mode 100644 src/VisualStudio/Core/Def/Utilities/ProjectPropertyStorage.cs diff --git a/src/VisualStudio/CSharp/Impl/Microsoft.VisualStudio.LanguageServices.CSharp.csproj b/src/VisualStudio/CSharp/Impl/Microsoft.VisualStudio.LanguageServices.CSharp.csproj index cd7b6e159f882..1cff0cd720bdc 100644 --- a/src/VisualStudio/CSharp/Impl/Microsoft.VisualStudio.LanguageServices.CSharp.csproj +++ b/src/VisualStudio/CSharp/Impl/Microsoft.VisualStudio.LanguageServices.CSharp.csproj @@ -53,6 +53,7 @@ + diff --git a/src/VisualStudio/CSharp/Impl/Utilities/CSharpCompilationOptionsChangingService.cs b/src/VisualStudio/CSharp/Impl/Utilities/CSharpCompilationOptionsChangingService.cs new file mode 100644 index 0000000000000..01e4e8e763d10 --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/Utilities/CSharpCompilationOptionsChangingService.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Composition; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.VisualStudio.LanguageServices.Utilities; +using VSLangProj80; + +namespace Microsoft.VisualStudio.LanguageServices.CSharp.Utilities +{ + [ExportLanguageService(typeof(ICompilationOptionsChangingService), LanguageNames.CSharp), Shared] + internal class CSharpCompilationOptionsChangingService : ICompilationOptionsChangingService + { + public bool CanApplyChange(CompilationOptions oldOptions, CompilationOptions newOptions) + { + var oldCSharpOptions = (CSharpCompilationOptions)oldOptions; + var newCSharpOptions = (CSharpCompilationOptions)newOptions; + + // Currently, only changes to AllowUnsafe of compilation options are supported. + return oldCSharpOptions.WithAllowUnsafe(newCSharpOptions.AllowUnsafe) == newOptions; + } + + public void Apply(CompilationOptions options, ProjectPropertyStorage storage) + { + var csharpOptions = (CSharpCompilationOptions)options; + + storage.SetProperty("AllowUnsafeBlocks", nameof(ProjectConfigurationProperties3.AllowUnsafeBlocks), + csharpOptions.AllowUnsafe); + } + } +} diff --git a/src/VisualStudio/CSharp/Impl/Utilities/CSharpCompilationOptionsService.cs b/src/VisualStudio/CSharp/Impl/Utilities/CSharpCompilationOptionsService.cs deleted file mode 100644 index 4a8e6bbc2ebf7..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Utilities/CSharpCompilationOptionsService.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Composition; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.VisualStudio.LanguageServices.Utilities; - -namespace Microsoft.VisualStudio.LanguageServices.CSharp.Utilities -{ - [ExportLanguageService(typeof(ICompilationOptionsService), LanguageNames.CSharp), Shared] - internal class CSharpCompilationOptionsService : ICompilationOptionsService - { - public bool SupportsUnsafe => true; - - public bool GetAllowUnsafe(CompilationOptions options) - => ((CSharpCompilationOptions)options).AllowUnsafe; - - public CompilationOptions WithAllowUnsafe(CompilationOptions old, bool allowUnsafe) - => ((CSharpCompilationOptions)old).WithAllowUnsafe(allowUnsafe); - } -} diff --git a/src/VisualStudio/CSharp/Impl/Utilities/CSharpParseOptionsChangingService.cs b/src/VisualStudio/CSharp/Impl/Utilities/CSharpParseOptionsChangingService.cs new file mode 100644 index 0000000000000..2b62661fb3902 --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/Utilities/CSharpParseOptionsChangingService.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Composition; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.VisualStudio.LanguageServices.Utilities; +using VSLangProj80; + +namespace Microsoft.VisualStudio.LanguageServices.CSharp.Utilities +{ + [ExportLanguageService(typeof(IParseOptionsChangingService), LanguageNames.CSharp), Shared] + internal class CSharpParseOptionsChangingService : IParseOptionsChangingService + { + public bool CanApplyChange(ParseOptions oldOptions, ParseOptions newOptions) + { + var oldCSharpOptions = (CSharpParseOptions)oldOptions; + var newCSharpOptions = (CSharpParseOptions)newOptions; + + // Currently, only changes to the LanguageVersion of parse options are supported. + return oldCSharpOptions.WithLanguageVersion(newCSharpOptions.LanguageVersion) == newOptions; + } + + public void Apply(ParseOptions options, ProjectPropertyStorage storage) + { + var csharpOptions = (CSharpParseOptions)options; + + storage.SetProperty("LangVersion", nameof(CSharpProjectConfigurationProperties3.LanguageVersion), + LanguageVersionFacts.ToDisplayString(csharpOptions.LanguageVersion)); + } + } +} diff --git a/src/VisualStudio/CSharp/Impl/Utilities/CSharpParseOptionsService.cs b/src/VisualStudio/CSharp/Impl/Utilities/CSharpParseOptionsService.cs deleted file mode 100644 index d1129da70d833..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Utilities/CSharpParseOptionsService.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Composition; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.VisualStudio.LanguageServices.Utilities; -using Roslyn.Utilities; - -namespace Microsoft.VisualStudio.LanguageServices.CSharp.Utilities -{ - [ExportLanguageService(typeof(IParseOptionsService), LanguageNames.CSharp), Shared] - internal class CSharpParseOptionsService : IParseOptionsService - { - public string GetLanguageVersion(ParseOptions options) => - ((CSharpParseOptions)options).SpecifiedLanguageVersion.ToDisplayString(); - - public ParseOptions WithLanguageVersion(ParseOptions options, string version) - { - var csharpOptions = (CSharpParseOptions)options; - Contract.ThrowIfFalse(LanguageVersionFacts.TryParse(version, out var newVersion)); - - return csharpOptions.WithLanguageVersion(newVersion); - } - } -} diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs deleted file mode 100644 index bc6d94be0e628..0000000000000 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.ProjectPropertyStorage.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using EnvDTE; -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Shell.Interop; - -namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem -{ - internal partial class VisualStudioWorkspaceImpl - { - private abstract class ProjectPropertyStorage - { - // For CPS projects, we prefer to use IVsBuildPropertyStorage since that allows us to easily modify the project - // properties independent of configuration. However this is problematic in the legacy project system, where setting - // the build property would indeed change its value, however that change would only be visible after the project is - // unloaded and reloaded. The language service would not be updated (the error we're trying to fix would still - // be visible) and any checkbox in the project properties dialog would not be updated. The language service issue - // could be worked around by using VSProject.Refresh, but that does not fix the project properties dialog. Therefore - // for the legacy project system, we choose to use ConfigurationManager to iterate & update each configuration, - // which works correctly, even though it is a little less convinient because it creates a more verbose project file - // (although we're dealing with a legacy project file... it's already verbose anyway). - - // It's important to note that the property name may differ in these two implementations. The build property name - // corresponds to the name of the property in the project file (for example LangVersion), whereas the configuration - // property name comes from an interface such as CSharpProjectConfigurationProperties3 (for example LanguageVersion). - - public static ProjectPropertyStorage Create(Project project, IServiceProvider serviceProvider) - { - var solution = (IVsSolution)serviceProvider.GetService(typeof(SVsSolution)); - solution.GetProjectOfUniqueName(project.UniqueName, out var hierarchy); - - return hierarchy.IsCapabilityMatch("CPS") - ? new BuildPropertyStorage((IVsBuildPropertyStorage)hierarchy) - : new PerConfigurationPropertyStorage(project.ConfigurationManager) as ProjectPropertyStorage; - } - - public abstract void SetProperty(string buildPropertyName, string configurationPropertyName, string value); - - private sealed class BuildPropertyStorage : ProjectPropertyStorage - { - private readonly IVsBuildPropertyStorage _propertyStorage; - - public BuildPropertyStorage(IVsBuildPropertyStorage propertyStorage) - => this._propertyStorage = propertyStorage; - - public override void SetProperty(string buildPropertyName, string configurationPropertyName, string value) - { - _propertyStorage.SetPropertyValue(buildPropertyName, null, (uint)_PersistStorageType.PST_PROJECT_FILE, value); - } - } - - private sealed class PerConfigurationPropertyStorage : ProjectPropertyStorage - { - private readonly ConfigurationManager _configurationManager; - - public PerConfigurationPropertyStorage(ConfigurationManager configurationManager) - => this._configurationManager = configurationManager; - - public override void SetProperty(string buildPropertyName, string configurationPropertyName, string value) - { - foreach (Configuration configuration in _configurationManager) - { - configuration.Properties.Item(configurationPropertyName).Value = value; - } - } - } - } - } -} diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs index 419657d06a5f4..febfcd8ddfe5c 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs @@ -329,32 +329,24 @@ internal bool IsCPSProject(CodeAnalysis.Project project) protected override bool CanApplyCompilationOptionChange(CompilationOptions oldOptions, CompilationOptions newOptions, CodeAnalysis.Project project) { - var compilationOptionsService = project.LanguageServices.GetService(); - if (compilationOptionsService == null || !compilationOptionsService.SupportsUnsafe) + var compilationOptionsService = project.LanguageServices.GetService(); + if (compilationOptionsService == null) { return false; } - // Currently, only changes to AllowUnsafe of compilation options are supported. - var newAllowUnsafe = compilationOptionsService.GetAllowUnsafe(newOptions); - var updated = compilationOptionsService.WithAllowUnsafe(oldOptions, newAllowUnsafe); - - return newOptions == updated; + return compilationOptionsService.CanApplyChange(oldOptions, newOptions); } protected override bool CanApplyParseOptionChange(ParseOptions oldOptions, ParseOptions newOptions, CodeAnalysis.Project project) { - var parseOptionsService = project.LanguageServices.GetService(); + var parseOptionsService = project.LanguageServices.GetService(); if (parseOptionsService == null) { return false; } - // Currently, only changes to the LanguageVersion of parse options are supported. - var newLanguageVersion = parseOptionsService.GetLanguageVersion(newOptions); - var updated = parseOptionsService.WithLanguageVersion(oldOptions, newLanguageVersion); - - return newOptions == updated; + return parseOptionsService.CanApplyChange(oldOptions, newOptions); } private void AddTextBufferCloneServiceToBuffer(object sender, TextBufferCreatedEventArgs e) @@ -454,20 +446,14 @@ protected override void ApplyCompilationOptionsChanged(ProjectId projectId, Comp var project = CurrentSolution.GetProject(projectId); - var compilationOptionsService = project.LanguageServices.GetService(); - Contract.ThrowIfNull(compilationOptionsService, nameof(compilationOptionsService)); - - var storage = ProjectPropertyStorage.Create(TryGetDTEProject(projectId), ServiceProvider.GlobalProvider); - - switch (project.Language) + var compilationOptionsService = project.LanguageServices.GetService(); + if (compilationOptionsService == null) { - case LanguageNames.CSharp: - storage.SetProperty("AllowUnsafeBlocks", nameof(ProjectConfigurationProperties3.AllowUnsafeBlocks), - compilationOptionsService.GetAllowUnsafe(options).ToString().ToLowerInvariant()); - break; - case LanguageNames.VisualBasic: - throw new InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_compilation_options); + throw new InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_compilation_options); } + + var storage = ProjectPropertyStorage.Create(TryGetDTEProject(projectId), ServiceProvider.GlobalProvider); + compilationOptionsService.Apply(options, storage); } protected override void ApplyParseOptionsChanged(ProjectId projectId, ParseOptions options) @@ -484,20 +470,14 @@ protected override void ApplyParseOptionsChanged(ProjectId projectId, ParseOptio var project = CurrentSolution.GetProject(projectId); - var parseOptionsService = project.LanguageServices.GetService(); - Contract.ThrowIfNull(parseOptionsService, nameof(parseOptionsService)); - - var storage = ProjectPropertyStorage.Create(TryGetDTEProject(projectId), ServiceProvider.GlobalProvider); - - switch (project.Language) + var parseOptionsService = project.LanguageServices.GetService(); + if (parseOptionsService == null) { - case LanguageNames.CSharp: - storage.SetProperty("LangVersion", nameof(CSharpProjectConfigurationProperties3.LanguageVersion), - parseOptionsService.GetLanguageVersion(options)); - break; - case LanguageNames.VisualBasic: - throw new InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_parse_options); + throw new InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_parse_options); } + + var storage = ProjectPropertyStorage.Create(TryGetDTEProject(projectId), ServiceProvider.GlobalProvider); + parseOptionsService.Apply(options, storage); } protected override void ApplyAnalyzerReferenceAdded(ProjectId projectId, AnalyzerReference analyzerReference) diff --git a/src/VisualStudio/Core/Def/Utilities/ICompilationOptionsService.cs b/src/VisualStudio/Core/Def/Utilities/ICompilationOptionsChangingService.cs similarity index 55% rename from src/VisualStudio/Core/Def/Utilities/ICompilationOptionsService.cs rename to src/VisualStudio/Core/Def/Utilities/ICompilationOptionsChangingService.cs index 59885a768641d..193d0f0a2f852 100644 --- a/src/VisualStudio/Core/Def/Utilities/ICompilationOptionsService.cs +++ b/src/VisualStudio/Core/Def/Utilities/ICompilationOptionsChangingService.cs @@ -5,10 +5,10 @@ namespace Microsoft.VisualStudio.LanguageServices.Utilities { - internal interface ICompilationOptionsService : ILanguageService + internal interface ICompilationOptionsChangingService : ILanguageService { - bool SupportsUnsafe { get; } - bool GetAllowUnsafe(CompilationOptions options); - CompilationOptions WithAllowUnsafe(CompilationOptions old, bool allowUnsafe); + bool CanApplyChange(CompilationOptions oldOptions, CompilationOptions newOptions); + + void Apply(CompilationOptions options, ProjectPropertyStorage storage); } } diff --git a/src/VisualStudio/Core/Def/Utilities/IParseOptionsService.cs b/src/VisualStudio/Core/Def/Utilities/IParseOptionsChangingService.cs similarity index 57% rename from src/VisualStudio/Core/Def/Utilities/IParseOptionsService.cs rename to src/VisualStudio/Core/Def/Utilities/IParseOptionsChangingService.cs index be2ab3394079a..a57122c660623 100644 --- a/src/VisualStudio/Core/Def/Utilities/IParseOptionsService.cs +++ b/src/VisualStudio/Core/Def/Utilities/IParseOptionsChangingService.cs @@ -5,9 +5,10 @@ namespace Microsoft.VisualStudio.LanguageServices.Utilities { - internal interface IParseOptionsService : ILanguageService + internal interface IParseOptionsChangingService : ILanguageService { - string GetLanguageVersion(ParseOptions options); - ParseOptions WithLanguageVersion(ParseOptions old, string version); + bool CanApplyChange(ParseOptions oldOptions, ParseOptions newOptions); + + void Apply(ParseOptions options, ProjectPropertyStorage storage); } } diff --git a/src/VisualStudio/Core/Def/Utilities/ProjectPropertyStorage.cs b/src/VisualStudio/Core/Def/Utilities/ProjectPropertyStorage.cs new file mode 100644 index 0000000000000..978cce3ba3c6f --- /dev/null +++ b/src/VisualStudio/Core/Def/Utilities/ProjectPropertyStorage.cs @@ -0,0 +1,71 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Globalization; +using EnvDTE; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; + +namespace Microsoft.VisualStudio.LanguageServices.Utilities +{ + internal abstract class ProjectPropertyStorage + { + // For CPS projects, we prefer to use IVsBuildPropertyStorage since that allows us to easily modify the project + // properties independent of configuration. However this is problematic in the legacy project system, where setting + // the build property would indeed change its value, however that change would only be visible after the project is + // unloaded and reloaded. The language service would not be updated (the error we're trying to fix would still + // be visible) and any checkbox in the project properties dialog would not be updated. The language service issue + // could be worked around by using VSProject.Refresh, but that does not fix the project properties dialog. Therefore + // for the legacy project system, we choose to use ConfigurationManager to iterate & update each configuration, + // which works correctly, even though it is a little less convinient because it creates a more verbose project file + // (although we're dealing with a legacy project file... it's already verbose anyway). + + // It's important to note that the property name may differ in these two implementations. The build property name + // corresponds to the name of the property in the project file (for example LangVersion), whereas the configuration + // property name comes from an interface such as CSharpProjectConfigurationProperties3 (for example LanguageVersion). + + public static ProjectPropertyStorage Create(Project project, IServiceProvider serviceProvider) + { + var solution = (IVsSolution)serviceProvider.GetService(typeof(SVsSolution)); + solution.GetProjectOfUniqueName(project.UniqueName, out var hierarchy); + + return hierarchy.IsCapabilityMatch("CPS") + ? new BuildPropertyStorage((IVsBuildPropertyStorage)hierarchy) + : new PerConfigurationPropertyStorage(project.ConfigurationManager) as ProjectPropertyStorage; + } + + public abstract void SetProperty(string buildPropertyName, string configurationPropertyName, string value); + + public void SetProperty(string buildPropertyName, string configurationPropertyName, bool value) + => SetProperty(buildPropertyName, configurationPropertyName, value.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()); + + private sealed class BuildPropertyStorage : ProjectPropertyStorage + { + private readonly IVsBuildPropertyStorage _propertyStorage; + + public BuildPropertyStorage(IVsBuildPropertyStorage propertyStorage) + => this._propertyStorage = propertyStorage; + + public override void SetProperty(string buildPropertyName, string configurationPropertyName, string value) + { + _propertyStorage.SetPropertyValue(buildPropertyName, null, (uint)_PersistStorageType.PST_PROJECT_FILE, value); + } + } + + private sealed class PerConfigurationPropertyStorage : ProjectPropertyStorage + { + private readonly ConfigurationManager _configurationManager; + + public PerConfigurationPropertyStorage(ConfigurationManager configurationManager) + => this._configurationManager = configurationManager; + + public override void SetProperty(string buildPropertyName, string configurationPropertyName, string value) + { + foreach (Configuration configuration in _configurationManager) + { + configuration.Properties.Item(configurationPropertyName).Value = value; + } + } + } + } +} From 2289a5f8f72a51a893802301bb7350af4c662ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sat, 8 Dec 2018 17:03:53 +0100 Subject: [PATCH 39/45] Treating VB equally --- .../VisualStudioWorkspaceImpl.cs | 34 +++---------------- ...lBasicCompilationOptionsChangingService.vb | 21 ++++++++++++ .../VisualBasicParseOptionsChangingService.vb | 21 ++++++++++++ 3 files changed, 46 insertions(+), 30 deletions(-) create mode 100644 src/VisualStudio/VisualBasic/Impl/Utilities/VisualBasicCompilationOptionsChangingService.vb create mode 100644 src/VisualStudio/VisualBasic/Impl/Utilities/VisualBasicParseOptionsChangingService.vb diff --git a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs index febfcd8ddfe5c..01914cf16db95 100644 --- a/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs +++ b/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs @@ -329,24 +329,12 @@ internal bool IsCPSProject(CodeAnalysis.Project project) protected override bool CanApplyCompilationOptionChange(CompilationOptions oldOptions, CompilationOptions newOptions, CodeAnalysis.Project project) { - var compilationOptionsService = project.LanguageServices.GetService(); - if (compilationOptionsService == null) - { - return false; - } - - return compilationOptionsService.CanApplyChange(oldOptions, newOptions); + return project.LanguageServices.GetRequiredService().CanApplyChange(oldOptions, newOptions); } protected override bool CanApplyParseOptionChange(ParseOptions oldOptions, ParseOptions newOptions, CodeAnalysis.Project project) { - var parseOptionsService = project.LanguageServices.GetService(); - if (parseOptionsService == null) - { - return false; - } - - return parseOptionsService.CanApplyChange(oldOptions, newOptions); + return project.LanguageServices.GetRequiredService().CanApplyChange(oldOptions, newOptions); } private void AddTextBufferCloneServiceToBuffer(object sender, TextBufferCreatedEventArgs e) @@ -444,14 +432,7 @@ protected override void ApplyCompilationOptionsChanged(ProjectId projectId, Comp throw new ArgumentNullException(nameof(options)); } - var project = CurrentSolution.GetProject(projectId); - - var compilationOptionsService = project.LanguageServices.GetService(); - if (compilationOptionsService == null) - { - throw new InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_compilation_options); - } - + var compilationOptionsService = CurrentSolution.GetProject(projectId).LanguageServices.GetRequiredService(); var storage = ProjectPropertyStorage.Create(TryGetDTEProject(projectId), ServiceProvider.GlobalProvider); compilationOptionsService.Apply(options, storage); } @@ -468,14 +449,7 @@ protected override void ApplyParseOptionsChanged(ProjectId projectId, ParseOptio throw new ArgumentNullException(nameof(options)); } - var project = CurrentSolution.GetProject(projectId); - - var parseOptionsService = project.LanguageServices.GetService(); - if (parseOptionsService == null) - { - throw new InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_parse_options); - } - + var parseOptionsService = CurrentSolution.GetProject(projectId).LanguageServices.GetRequiredService(); var storage = ProjectPropertyStorage.Create(TryGetDTEProject(projectId), ServiceProvider.GlobalProvider); parseOptionsService.Apply(options, storage); } diff --git a/src/VisualStudio/VisualBasic/Impl/Utilities/VisualBasicCompilationOptionsChangingService.vb b/src/VisualStudio/VisualBasic/Impl/Utilities/VisualBasicCompilationOptionsChangingService.vb new file mode 100644 index 0000000000000..875a7619da796 --- /dev/null +++ b/src/VisualStudio/VisualBasic/Impl/Utilities/VisualBasicCompilationOptionsChangingService.vb @@ -0,0 +1,21 @@ +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +Imports System.Composition +Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.Host.Mef +Imports Microsoft.VisualStudio.LanguageServices.Utilities + +Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Utilities + + Friend NotInheritable Class VisualBasicCompilationOptionsChangingService + Implements ICompilationOptionsChangingService + + Public Function CanApplyChange(oldOptions As CompilationOptions, newOptions As CompilationOptions) As Boolean Implements ICompilationOptionsChangingService.CanApplyChange + Return False + End Function + + Public Sub Apply(options As CompilationOptions, storage As ProjectPropertyStorage) Implements ICompilationOptionsChangingService.Apply + Throw New InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_compilation_options) + End Sub + End Class +End Namespace diff --git a/src/VisualStudio/VisualBasic/Impl/Utilities/VisualBasicParseOptionsChangingService.vb b/src/VisualStudio/VisualBasic/Impl/Utilities/VisualBasicParseOptionsChangingService.vb new file mode 100644 index 0000000000000..a771e642297fd --- /dev/null +++ b/src/VisualStudio/VisualBasic/Impl/Utilities/VisualBasicParseOptionsChangingService.vb @@ -0,0 +1,21 @@ +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +Imports System.Composition +Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.Host.Mef +Imports Microsoft.VisualStudio.LanguageServices.Utilities + +Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Utilities + + Friend NotInheritable Class VisualBasicParseOptionsChangingService + Implements IParseOptionsChangingService + + Public Function CanApplyChange(oldOptions As ParseOptions, newOptions As ParseOptions) As Boolean Implements IParseOptionsChangingService.CanApplyChange + Return False + End Function + + Public Sub Apply(options As ParseOptions, storage As ProjectPropertyStorage) Implements IParseOptionsChangingService.Apply + Throw New InvalidOperationException(ServicesVSResources.This_workspace_does_not_support_updating_Visual_Basic_parse_options) + End Sub + End Class +End Namespace From 6070ba3a878e81debecb32b7d0bbc36ac4496421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Mon, 10 Dec 2018 22:16:29 +0100 Subject: [PATCH 40/45] Save solution after creating it as a workaround for CPS bug Co-authored-by: Sam Harwell --- .../TestUtilities/InProcess/SolutionExplorer_InProc.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs index 02b968bddd3f0..bbdd10fb10c6b 100644 --- a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs +++ b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs @@ -106,9 +106,14 @@ public void CreateSolution(string solutionName, bool saveExistingSolutionIfExist string solutionPath = IntegrationHelper.CreateTemporaryPath(); IntegrationHelper.DeleteDirectoryRecursively(solutionPath); + Directory.CreateDirectory(solutionPath); dte.Solution.Create(solutionPath, solutionName); + // Workaround for https://devdiv.visualstudio.com/DevDiv/_workitems/edit/627280 + var solution = GetGlobalService(); + ErrorHandler.ThrowOnFailure(solution.SaveSolutionElement((uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_ForceSave, null, 0)); + _solution = (Solution2)dte.Solution; _fileName = Path.Combine(solutionPath, $"{solutionName}.sln"); } From 7a5ff092a3cb29d698292b24822e9bd8353b281f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Tue, 11 Dec 2018 19:49:13 +0100 Subject: [PATCH 41/45] Embed interop types --- .../Impl/Microsoft.VisualStudio.LanguageServices.CSharp.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/VisualStudio/CSharp/Impl/Microsoft.VisualStudio.LanguageServices.CSharp.csproj b/src/VisualStudio/CSharp/Impl/Microsoft.VisualStudio.LanguageServices.CSharp.csproj index 1cff0cd720bdc..053df3b338ca3 100644 --- a/src/VisualStudio/CSharp/Impl/Microsoft.VisualStudio.LanguageServices.CSharp.csproj +++ b/src/VisualStudio/CSharp/Impl/Microsoft.VisualStudio.LanguageServices.CSharp.csproj @@ -54,6 +54,7 @@ + From 3c987478f254c2f460308f873e15b6489ff79040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Sun, 16 Dec 2018 17:18:37 +0100 Subject: [PATCH 42/45] Add exclusion for VSLangProj80 --- src/Setup/DevDivInsertionFiles/DevDivInsertionFiles.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Setup/DevDivInsertionFiles/DevDivInsertionFiles.csproj b/src/Setup/DevDivInsertionFiles/DevDivInsertionFiles.csproj index b6b7d25f91a81..ac99def482ad5 100644 --- a/src/Setup/DevDivInsertionFiles/DevDivInsertionFiles.csproj +++ b/src/Setup/DevDivInsertionFiles/DevDivInsertionFiles.csproj @@ -97,6 +97,7 @@ <_Dependency Remove="stdole"/> <_Dependency Remove="StreamJsonRpc"/> <_Dependency Remove="System.Threading.Tasks.Dataflow"/> + <_Dependency Remove="VSLangProj80"/> From 37e95621bcde18e37672be38f26fdfd8c8c17787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Mon, 17 Dec 2018 20:38:37 +0100 Subject: [PATCH 43/45] Adding VSLangProj & VSLangProj2 --- src/Setup/DevDivInsertionFiles/DevDivInsertionFiles.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Setup/DevDivInsertionFiles/DevDivInsertionFiles.csproj b/src/Setup/DevDivInsertionFiles/DevDivInsertionFiles.csproj index ac99def482ad5..60194f240af05 100644 --- a/src/Setup/DevDivInsertionFiles/DevDivInsertionFiles.csproj +++ b/src/Setup/DevDivInsertionFiles/DevDivInsertionFiles.csproj @@ -97,6 +97,8 @@ <_Dependency Remove="stdole"/> <_Dependency Remove="StreamJsonRpc"/> <_Dependency Remove="System.Threading.Tasks.Dataflow"/> + <_Dependency Remove="VSLangProj"/> + <_Dependency Remove="VSLangProj2"/> <_Dependency Remove="VSLangProj80"/> From 4a73fa0dd5ac9443047902be6f0b3b7ce9e51607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Fri, 4 Jan 2019 20:55:41 +0100 Subject: [PATCH 44/45] Removing duplicate code after merge --- .../TestUtilities/InProcess/SolutionExplorer_InProc.cs | 4 ---- .../TestUtilities/OutOfProcess/SolutionExplorer_OutOfProc.cs | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs index 2e9a74fb90b43..37e2df2aa7fdb 100644 --- a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs +++ b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs @@ -116,10 +116,6 @@ public void CreateSolution(string solutionName, bool saveExistingSolutionIfExist ErrorHandler.ThrowOnFailure(solution.CreateSolution(solutionPath, solutionFileName, (uint)__VSCREATESOLUTIONFLAGS.CSF_SILENT)); ErrorHandler.ThrowOnFailure(solution.SaveSolutionElement((uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_ForceSave, null, 0)); - // Workaround for https://devdiv.visualstudio.com/DevDiv/_workitems/edit/627280 - var solution = GetGlobalService(); - ErrorHandler.ThrowOnFailure(solution.SaveSolutionElement((uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_ForceSave, null, 0)); - _solution = (Solution2)dte.Solution; _fileName = Path.Combine(solutionPath, solutionFileName); } diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/SolutionExplorer_OutOfProc.cs b/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/SolutionExplorer_OutOfProc.cs index d3cf773446063..efd368d1f6eb2 100644 --- a/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/SolutionExplorer_OutOfProc.cs +++ b/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/SolutionExplorer_OutOfProc.cs @@ -47,7 +47,7 @@ public void AddProject(ProjectUtils.Project projectName, string projectTemplate, _inProc.AddProject(projectName.Name, projectTemplate, languageName); _instance.Workspace.WaitForAsyncOperations(FeatureAttribute.Workspace); } - + public void AddCustomProject(ProjectUtils.Project projectName, string projectFileExtension, string projectFileContent) { _inProc.AddCustomProject(projectName.Name, projectFileExtension, projectFileContent); From 9d42e1aca9ee44e3db4a0ac341996e3d9b4fb9ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Kon=C3=AD=C4=8Dek?= Date: Fri, 4 Jan 2019 21:25:21 +0100 Subject: [PATCH 45/45] Fixing language change implementation - WithLanguageVersion maps to SpecifiedLanguageVersion, not LanguageVersion --- .../Impl/Utilities/CSharpParseOptionsChangingService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VisualStudio/CSharp/Impl/Utilities/CSharpParseOptionsChangingService.cs b/src/VisualStudio/CSharp/Impl/Utilities/CSharpParseOptionsChangingService.cs index 2b62661fb3902..cc9e6e48b7dae 100644 --- a/src/VisualStudio/CSharp/Impl/Utilities/CSharpParseOptionsChangingService.cs +++ b/src/VisualStudio/CSharp/Impl/Utilities/CSharpParseOptionsChangingService.cs @@ -18,7 +18,7 @@ public bool CanApplyChange(ParseOptions oldOptions, ParseOptions newOptions) var newCSharpOptions = (CSharpParseOptions)newOptions; // Currently, only changes to the LanguageVersion of parse options are supported. - return oldCSharpOptions.WithLanguageVersion(newCSharpOptions.LanguageVersion) == newOptions; + return oldCSharpOptions.WithLanguageVersion(newCSharpOptions.SpecifiedLanguageVersion) == newOptions; } public void Apply(ParseOptions options, ProjectPropertyStorage storage) @@ -26,7 +26,7 @@ public void Apply(ParseOptions options, ProjectPropertyStorage storage) var csharpOptions = (CSharpParseOptions)options; storage.SetProperty("LangVersion", nameof(CSharpProjectConfigurationProperties3.LanguageVersion), - LanguageVersionFacts.ToDisplayString(csharpOptions.LanguageVersion)); + LanguageVersionFacts.ToDisplayString(csharpOptions.SpecifiedLanguageVersion)); } } }