diff --git a/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj b/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj index 5f3882b59022e2fcaf80d436ea70dbaf56a78b03..8b9e9e34b8533160473471ab893a24236e9bb069 100644 --- a/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj +++ b/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj @@ -310,6 +310,13 @@ + + + + + + + diff --git a/src/EditorFeatures/CSharpTest/CodeActions/EncapsulateField/EncapsulateFieldTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/EncapsulateField/EncapsulateFieldTests.cs index 48de8da3e7467547376dc368e89fb9af39611306..7899617902a3464ebdb29b48daa0c1cbcd6f34dd 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/EncapsulateField/EncapsulateFieldTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/EncapsulateField/EncapsulateFieldTests.cs @@ -1,10 +1,15 @@ // 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.Collections.Generic; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeRefactorings.EncapsulateField; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Notification; +using Microsoft.CodeAnalysis.Options; using Roslyn.Test.Utilities; using Xunit; @@ -17,6 +22,32 @@ protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspa return new EncapsulateFieldRefactoringProvider(); } + private static readonly Dictionary AllOptionsOff = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement }, + }; + + internal Task TestAllOptionsOffAsync( + string initialMarkup, string expectedMarkup, + ParseOptions parseOptions = null, + CompilationOptions compilationOptions = null, + int index = 0, bool compareTokens = true, + IDictionary options = null, + bool withScriptOption = false) + { + options = options ?? new Dictionary(); + foreach (var kvp in AllOptionsOff) + { + options.Add(kvp); + } + + return TestAsync(initialMarkup, expectedMarkup, + parseOptions, compilationOptions, index, compareTokens, options, + withScriptOption: withScriptOption); + } + [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] public async Task PrivateFieldToPropertyIgnoringReferences() { @@ -56,7 +87,7 @@ void baz() } } "; - await TestAsync(text, expected, compareTokens: false, index: 1); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 1); } [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] @@ -98,7 +129,89 @@ void baz() } } "; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); + } + + [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] + public async Task TestCodeStyle1() + { + var text = @" +class foo +{ + private int b[|a|]r; + + void baz() + { + var q = Bar; + } +} +"; + + var expected = @" +class foo +{ + private int bar; + + public int Bar + { + get + { + return bar; + } + + set + { + bar = value; + } + } + + void baz() + { + var q = Bar; + } +} +"; + await TestAsync(text, expected, + options: OptionsSet( + Tuple.Create((IOption)CSharpCodeStyleOptions.PreferExpressionBodiedProperties, true, NotificationOption.None), + Tuple.Create((IOption)CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, false, NotificationOption.None))); + } + + [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] + public async Task TestCodeStyle2() + { + var text = @" +class foo +{ + private int b[|a|]r; + + void baz() + { + var q = Bar; + } +} +"; + + var expected = @" +class foo +{ + private int bar; + + public int Bar + { + get => bar; + + set => bar = value; + } + + void baz() + { + var q = Bar; + } +} +"; + await TestAsync(text, expected, + options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithNoneEnforcement)); } [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] @@ -140,7 +253,7 @@ void baz() } } "; - await TestAsync(text, expected, compareTokens: false, index: 1); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 1); } [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] @@ -182,7 +295,7 @@ void baz() } } "; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); } [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] @@ -210,7 +323,7 @@ public static int Foo } } }"; - await TestAsync(text, expected, compareTokens: false); + await TestAllOptionsOffAsync(text, expected, compareTokens: false); } [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] @@ -242,7 +355,7 @@ public int Foo1 } } }"; - await TestAsync(text, expected, compareTokens: false); + await TestAllOptionsOffAsync(text, expected, compareTokens: false); } [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] @@ -272,7 +385,7 @@ public T Foo } } }"; - await TestAsync(text, expected, compareTokens: false); + await TestAllOptionsOffAsync(text, expected, compareTokens: false); } [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] @@ -304,7 +417,7 @@ public int X } } }"; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); } [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] @@ -329,7 +442,7 @@ public int X } } }"; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); } [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] @@ -373,7 +486,7 @@ protected int Foo1 } } }"; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); } [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] @@ -428,7 +541,7 @@ void bar() Y = 2; } }"; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); } [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] @@ -485,7 +598,7 @@ void bar() Y = 2; } }"; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); } [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] @@ -528,7 +641,7 @@ void bar() y = 2; } }"; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); } [WorkItem(694057, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/694057")] @@ -556,7 +669,7 @@ public static int Bar } } "; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); } [WorkItem(694276, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/694276")] @@ -584,7 +697,7 @@ public static int Bar } } "; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); } [WorkItem(694276, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/694276")] @@ -617,7 +730,7 @@ public int __ } } "; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); } [WorkItem(695046, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/695046")] @@ -659,7 +772,7 @@ protected static int Bar } } "; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); } [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] @@ -727,7 +840,7 @@ void bar() "; - await TestAsync(text, expected, new CodeAnalysis.CSharp.CSharpParseOptions(), TestOptions.ReleaseExe, compareTokens: false); + await TestAllOptionsOffAsync(text, expected, new CodeAnalysis.CSharp.CSharpParseOptions(), TestOptions.ReleaseExe, compareTokens: false); } [WorkItem(713269, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/713269")] @@ -760,7 +873,7 @@ class C } } "; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); } [WorkItem(713240, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/713240")] @@ -803,7 +916,7 @@ internal enum State WA } "; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); } [WorkItem(713191, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/713191")] @@ -839,7 +952,7 @@ public int Field } } }"; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); } [WorkItem(713191, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/713191")] @@ -875,7 +988,7 @@ public static int Field } } }"; - await TestAsync(text, expected, compareTokens: false, index: 0); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 0); } [WorkItem(765959, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/765959")] @@ -908,7 +1021,7 @@ public int X } } "; - await TestAsync(text, expected); + await TestAllOptionsOffAsync(text, expected); } [WorkItem(829178, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/829178")] @@ -984,7 +1097,7 @@ public int MyInt } }"; - await TestAsync(text, expected); + await TestAllOptionsOffAsync(text, expected); } [WorkItem(1096007, "https://github.com/dotnet/roslyn/issues/282")] @@ -1013,7 +1126,7 @@ public async Task AlwaysUseEnglishUSCultureWhenFixingVariableNames_TurkishDotted { using (new CultureContext("tr-TR")) { - await TestAsync(@" + await TestAllOptionsOffAsync(@" class C { int [|iyi|]; @@ -1045,7 +1158,7 @@ public async Task AlwaysUseEnglishUSCultureWhenFixingVariableNames_TurkishUndott { using (new CultureContext("tr-TR")) { - await TestAsync(@" + await TestAllOptionsOffAsync(@" class C { int [|ırak|]; @@ -1077,7 +1190,7 @@ public async Task AlwaysUseEnglishUSCultureWhenFixingVariableNames_Arabic() { using (new CultureContext("ar-EG")) { - await TestAsync(@" + await TestAllOptionsOffAsync(@" class C { int [|بيت|]; @@ -1109,7 +1222,7 @@ public async Task AlwaysUseEnglishUSCultureWhenFixingVariableNames_Spanish() { using (new CultureContext("es-ES")) { - await TestAsync(@" + await TestAllOptionsOffAsync(@" class C { int [|árbol|]; @@ -1141,7 +1254,7 @@ public async Task AlwaysUseEnglishUSCultureWhenFixingVariableNames_Greek() { using (new CultureContext("el-GR")) { - await TestAsync(@" + await TestAllOptionsOffAsync(@" class C { int [|σκύλος|]; @@ -1170,7 +1283,7 @@ class C [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] public async Task TestEncapsulateEscapedIdentifier() { - await TestAsync(@" + await TestAllOptionsOffAsync(@" class C { int [|@class|]; @@ -1199,7 +1312,7 @@ public int Class [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] public async Task TestEncapsulateEscapedIdentifierAndQualifiedAccess() { - await TestAsync(@" + await TestAllOptionsOffAsync(@" class C { int [|@class|]; @@ -1229,7 +1342,7 @@ public int Class [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)] public async Task ApplyCurrentThisPrefixStyle() { - await TestAsync(@" + await TestAllOptionsOffAsync(@" class C { int [|i|]; @@ -1256,7 +1369,7 @@ public int I } [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField), Test.Utilities.CompilerTrait(Test.Utilities.CompilerFeature.Tuples)] - public async Task Tuple() + public async Task TestTuple() { var text = @" class C @@ -1294,7 +1407,7 @@ void M() } } "; - await TestAsync(text, expected, compareTokens: false, index: 1, parseOptions: TestOptions.Regular, withScriptOption: true); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 1, parseOptions: TestOptions.Regular, withScriptOption: true); } [Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField), Test.Utilities.CompilerTrait(Test.Utilities.CompilerFeature.Tuples)] @@ -1336,7 +1449,7 @@ void M() } } "; - await TestAsync(text, expected, compareTokens: false, index: 1, parseOptions: TestOptions.Regular, withScriptOption: true); + await TestAllOptionsOffAsync(text, expected, compareTokens: false, index: 1, parseOptions: TestOptions.Regular, withScriptOption: true); } } } diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractMethodTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractMethodTests.cs index 3764ceb2cab57bb7a51660e344e1cbb14544f8e8..50277275756aeb50917b80901a99f0c6c360fbc4 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractMethodTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/ExtractMethod/ExtractMethodTests.cs @@ -3,6 +3,8 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.CodeRefactorings.ExtractMethod; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; @@ -26,6 +28,16 @@ public async Task TestPartialSelection() index: 0); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractMethod)] + public async Task TestCodeStyle1() + { + await TestAsync( +@"class Program { static void Main ( string [ ] args ) { bool b = true ; System . Console . WriteLine ( [|b != true|] ? b = true : b = false ) ; } } ", +@"class Program { static void Main ( string [ ] args ) { bool b = true ; System . Console . WriteLine ( {|Rename:NewMethod|} ( b ) ? b = true : b = false ) ; } +private static bool NewMethod ( bool b ) => b != true ; } ", +options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.TrueWithNoneEnforcement)); + } + [WorkItem(540796, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540796")] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractMethod)] public async Task TestReadOfDataThatDoesNotFlowIn() diff --git a/src/EditorFeatures/CSharpTest/CodeActions/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs index 8f2d3e1da29447a84337410aaaa1caca74ec044a..a2342043f9c6b19a5c29708ce2bf83ad788e65c8 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/GenerateFromMembers/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.cs @@ -4,6 +4,7 @@ using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.CodeRefactorings.GenerateFromMembers.GenerateConstructorFromMembers; using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; @@ -26,6 +27,15 @@ public async Task TestSingleField() index: 0); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructorFromMembers)] + public async Task TestSingleFieldWithCodeStyle() + { + await TestAsync( +@"using System . Collections . Generic ; class Z { [|int a ;|] } ", +@"using System . Collections . Generic ; class Z { int a ; public Z ( int a ) => this . a = a ; } ", +options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CodeStyleOptions.TrueWithNoneEnforcement)); + } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructorFromMembers)] public async Task TestMultipleFields() { @@ -193,4 +203,4 @@ public async Task Tuple() withScriptOption: true); } } -} +} \ No newline at end of file diff --git a/src/EditorFeatures/CSharpTest/CodeActions/GenerateFromMembers/GenerateEqualsAndGetHashCode/GenerateEqualsAndGetHashCodeTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/GenerateFromMembers/GenerateEqualsAndGetHashCode/GenerateEqualsAndGetHashCodeTests.cs index 2d7818a045df6427ebba035a8d002b5201026735..c182b1012d59237167db97decbd4e3ba510346d9 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/GenerateFromMembers/GenerateEqualsAndGetHashCode/GenerateEqualsAndGetHashCodeTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/GenerateFromMembers/GenerateEqualsAndGetHashCode/GenerateEqualsAndGetHashCodeTests.cs @@ -3,6 +3,8 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.CodeRefactorings.GenerateFromMembers.GenerateEqualsAndGetHashCode; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; @@ -125,6 +127,17 @@ public async Task TestGetHashCodeSingleField() index: 1); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateEqualsAndGetHashCode)] + public async Task TestGetHashCodeSingleField_CodeStyle1() + { + await TestAsync( +@"using System . Collections . Generic ; class Program { [|int i ;|] } ", +@"using System . Collections . Generic ; class Program { int i ; +public override int GetHashCode ( ) => EqualityComparer < int > . Default . GetHashCode ( i ) ; } ", +index: 1, +options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.TrueWithNoneEnforcement)); + } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateEqualsAndGetHashCode)] public async Task TestGetHashCodeTypeParameter() { diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs index 08e35ddfaa9eeeb2fa696e4bcbeb59d7b14ae2e8..2ef1d301d284e4c6a17647a1b2c931895b5d8c04 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs @@ -2,8 +2,10 @@ using System.Linq; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Completion.Providers; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.Text; @@ -24,6 +26,12 @@ internal override CompletionProvider CreateCompletionProvider() return new OverrideCompletionProvider(); } + protected override void SetWorkspaceOptions(TestWorkspace workspace) + { + workspace.Options = workspace.Options.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement) + .WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement); + } + #region "CompletionItem tests" [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/AddUsing/AddUsingTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/AddUsing/AddUsingTests.cs index 49a68e43e97f3d79ec6993cf0f54eb3937098e85..ca213c0845ee6773d7085cbcde9017c3dbe98252 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/AddUsing/AddUsingTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/AddUsing/AddUsingTests.cs @@ -765,8 +765,8 @@ public async Task TestWithReferenceDirective() using System.Linq.Expressions; Expression", -parseOptions: GetScriptOptions(), -compilationOptions: TestOptions.ReleaseDll.WithMetadataReferenceResolver(resolver), +GetScriptOptions(), +TestOptions.ReleaseDll.WithMetadataReferenceResolver(resolver), compareTokens: false); } diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateConstructor/GenerateConstructorTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateConstructor/GenerateConstructorTests.cs index cb56df33b28baa3c32ae42fce74e97879f00384e..87623986804e7c1595ff431374e0c1498c73a0fc 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateConstructor/GenerateConstructorTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateConstructor/GenerateConstructorTests.cs @@ -5,6 +5,7 @@ using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeFixes.GenerateConstructor; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Diagnostics; @@ -29,6 +30,15 @@ public async Task TestWithSimpleArgument() @"class C { private int v; public C(int v) { this.v = v; } void M() { new C(1); } }"); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)] + public async Task TestWithSimpleArgument_UseExpressionBody1() + { + await TestAsync( +@"class C { void M() { new [|C|](1); } }", +@"class C { private int v; public C(int v) => this.v = v; void M() { new C(1); } }", +options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CodeStyleOptions.TrueWithNoneEnforcement)); + } + [Fact, WorkItem(910589, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/910589"), Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)] public async Task TestWithNoArgs() { diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateConversionTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateConversionTests.cs index fcfa40b9abc9f01ea9268892382427a781d642b5..6303a97c5dcf2b15367459ff20eff7a0615d1313 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateConversionTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateConversionTests.cs @@ -3,7 +3,9 @@ using System; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeFixes.GenerateMethod; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics; using Roslyn.Test.Utilities; using Xunit; @@ -35,6 +37,16 @@ public async Task TestGenerateImplicitConversionClass() @"using System ; class Program { void Test ( int [ ] a ) { C x1 = 1 ; } } class C { public static implicit operator C ( int v ) { throw new NotImplementedException ( ) ; } } "); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)] + public async Task TestGenerateImplicitConversionClass_CodeStyle() + { + await TestAsync( +@"class Program { void Test ( int [ ] a ) { C x1 = [|1|] ; } } class C { } ", +@"using System ; class Program { void Test ( int [ ] a ) { C x1 = 1 ; } } +class C { public static implicit operator C ( int v ) => throw new NotImplementedException ( ) ; } ", +options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.TrueWithNoneEnforcement)); + } + [WorkItem(774321, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/774321")] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)] public async Task TestGenerateImplicitConversionAwaitExpression() diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateMethodTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateMethodTests.cs index 0fdabe545ff3f5d295fcb84d38a9cec251d4fe88..74d5a9f74246f6c754c79235ab0c5d75fe2434c4 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateMethodTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateMethodTests.cs @@ -3,7 +3,9 @@ using System; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeFixes.GenerateMethod; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Diagnostics; using Roslyn.Test.Utilities; @@ -26,6 +28,15 @@ public async Task TestSimpleInvocationIntoSameType() @"using System; class Class { void Method() { Foo(); } private void Foo() { throw new NotImplementedException(); } }"); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)] + public async Task TestSimpleInvocationIntoSameType_CodeStyle1() + { + await TestAsync( +@"class Class { void Method() { [|Foo|](); } }", +@"using System; class Class { void Method() { Foo(); } private void Foo() => throw new NotImplementedException(); }", +options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.TrueWithNoneEnforcement)); + } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)] [WorkItem(11518, "https://github.com/dotnet/roslyn/issues/11518")] public async Task NameMatchesNamespaceName() diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/ImplementAbstractClass/ImplementAbstractClassTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/ImplementAbstractClass/ImplementAbstractClassTests.cs index 1ff065aae92430415f359c357470a1e8d22f9067..d5e0624e0755f3dc6cbaf25969e790fd5e071431 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/ImplementAbstractClass/ImplementAbstractClassTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/ImplementAbstractClass/ImplementAbstractClassTests.cs @@ -1,10 +1,15 @@ // 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.Collections.Generic; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeFixes.ImplementAbstractClass; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Options; using Roslyn.Test.Utilities; using Xunit; @@ -17,11 +22,35 @@ public partial class ImplementAbstractClassTests : AbstractCSharpDiagnosticProvi return new Tuple( null, new ImplementAbstractClassCodeFixProvider()); } + private static readonly Dictionary AllOptionsOff = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.FalseWithNoneEnforcement }, + }; + + internal Task TestAllOptionsOffAsync( + string initialMarkup, string expectedMarkup, + int index = 0, bool compareTokens = true, + IDictionary options = null) + { + options = options ?? new Dictionary(); + foreach (var kvp in AllOptionsOff) + { + options.Add(kvp); + } + + return TestAsync(initialMarkup, expectedMarkup, index, compareTokens, options); + } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestSimpleMethods() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class Foo { protected abstract string FooMethod ( ) ; public abstract void Blah ( ) ; } abstract class Bar : Foo { public abstract bool BarMethod ( ) ; public override void Blah ( ) { } } class [|Program|] : Foo { static void Main ( string [ ] args ) { } } ", @"using System ; abstract class Foo { protected abstract string FooMethod ( ) ; public abstract void Blah ( ) ; } abstract class Bar : Foo { public abstract bool BarMethod ( ) ; public override void Blah ( ) { } } class Program : Foo { static void Main ( string [ ] args ) { } public override void Blah ( ) { throw new NotImplementedException ( ) ; } protected override string FooMethod ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -37,7 +66,7 @@ public async Task TestNotAvailableForStruct() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOptionalIntParameter() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class d { public abstract void foo ( int x = 3 ) ; } class [|b|] : d { }", @"using System ; abstract class d { public abstract void foo ( int x = 3 ) ; } class b : d { public override void foo ( int x = 3 ) { throw new NotImplementedException ( ) ; } }"); } @@ -45,7 +74,7 @@ public async Task TestOptionalIntParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOptionalCharParameter() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class d { public abstract void foo ( char x = 'a' ) ; } class [|b|] : d { }", @"using System ; abstract class d { public abstract void foo ( char x = 'a' ) ; } class b : d { public override void foo ( char x = 'a' ) { throw new NotImplementedException ( ) ; } }"); } @@ -53,7 +82,7 @@ public async Task TestOptionalCharParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOptionalStringParameter() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class d { public abstract void foo ( string x = ""x"" ) ; } class [|b|] : d { }", @"using System ; abstract class d { public abstract void foo ( string x = ""x"" ) ; } class b : d { public override void foo ( string x = ""x"" ) { throw new NotImplementedException ( ) ; } }"); } @@ -61,7 +90,7 @@ public async Task TestOptionalStringParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOptionalShortParameter() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class d { public abstract void foo ( short x = 3 ) ; } class [|b|] : d { }", @"using System ; abstract class d { public abstract void foo ( short x = 3 ) ; } class b : d { public override void foo ( short x = 3 ) { throw new NotImplementedException ( ) ; } }"); } @@ -69,7 +98,7 @@ public async Task TestOptionalShortParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOptionalDecimalParameter() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class d { public abstract void foo ( decimal x = 3 ) ; } class [|b|] : d { }", @"using System ; abstract class d { public abstract void foo ( decimal x = 3 ) ; } class b : d { public override void foo ( decimal x = 3 ) { throw new NotImplementedException ( ) ; } }"); } @@ -77,7 +106,7 @@ public async Task TestOptionalDecimalParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOptionalDoubleParameter() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class d { public abstract void foo ( double x = 3 ) ; } class [|b|] : d { }", @"using System ; abstract class d { public abstract void foo ( double x = 3 ) ; } class b : d { public override void foo ( double x = 3 ) { throw new NotImplementedException ( ) ; } }"); } @@ -85,7 +114,7 @@ public async Task TestOptionalDoubleParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOptionalLongParameter() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class d { public abstract void foo ( long x = 3 ) ; } class [|b|] : d { }", @"using System ; abstract class d { public abstract void foo ( long x = 3 ) ; } class b : d { public override void foo ( long x = 3 ) { throw new NotImplementedException ( ) ; } }"); } @@ -93,7 +122,7 @@ public async Task TestOptionalLongParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOptionalFloatParameter() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class d { public abstract void foo ( float x = 3 ) ; } class [|b|] : d { }", @"using System ; abstract class d { public abstract void foo ( float x = 3 ) ; } class b : d { public override void foo ( float x = 3 ) { throw new NotImplementedException ( ) ; } }"); } @@ -101,7 +130,7 @@ public async Task TestOptionalFloatParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOptionalUshortParameter() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class d { public abstract void foo ( ushort x = 3 ) ; } class [|b|] : d { }", @"using System ; abstract class d { public abstract void foo ( ushort x = 3 ) ; } class b : d { public override void foo ( ushort x = 3 ) { throw new NotImplementedException ( ) ; } }"); } @@ -109,7 +138,7 @@ public async Task TestOptionalUshortParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOptionalUintParameter() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class d { public abstract void foo ( uint x = 3 ) ; } class [|b|] : d { }", @"using System ; abstract class d { public abstract void foo ( uint x = 3 ) ; } class b : d { public override void foo ( uint x = 3 ) { throw new NotImplementedException ( ) ; } }"); } @@ -117,7 +146,7 @@ public async Task TestOptionalUintParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOptionalUlongParameter() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class d { public abstract void foo ( ulong x = 3 ) ; } class [|b|] : d { }", @"using System ; abstract class d { public abstract void foo ( ulong x = 3 ) ; } class b : d { public override void foo ( ulong x = 3 ) { throw new NotImplementedException ( ) ; } }"); } @@ -125,7 +154,7 @@ public async Task TestOptionalUlongParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOptionalStructParameter() { - await TestAsync( + await TestAllOptionsOffAsync( @"struct b { } abstract class d { public abstract void foo ( b x = new b ( ) ) ; } class [|c|] : d { }", @"using System ; struct b { } abstract class d { public abstract void foo ( b x = new b ( ) ) ; } class c : d { public override void foo ( b x = default ( b ) ) { throw new NotImplementedException ( ) ; } }"); } @@ -134,7 +163,7 @@ public async Task TestOptionalStructParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOptionalNullableStructParameter() { - await TestAsync( + await TestAllOptionsOffAsync( @"struct b { } abstract class d { public abstract void m ( b? x = null, b? y = default(b?) ) ; } class [|c|] : d { }", @"using System ; struct b { } abstract class d { public abstract void m ( b? x = null, b? y = default(b?) ) ; } class c : d { public override void m ( b? x = default(b?), b? y = default(b?) ) { throw new NotImplementedException ( ) ; } }"); } @@ -143,7 +172,7 @@ public async Task TestOptionalNullableStructParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOptionalNullableIntParameter() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class d { public abstract void m ( int? x = 5, int? y = default(int?) ) ; } class [|c|] : d { }", @"using System ; abstract class d { public abstract void m ( int? x = 5, int? y = default(int?) ) ; } class c : d { public override void m ( int? x = 5, int? y = default(int?) ) { throw new NotImplementedException ( ) ; } }"); } @@ -151,7 +180,7 @@ public async Task TestOptionalNullableIntParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOptionalObjectParameter() { - await TestAsync( + await TestAllOptionsOffAsync( @"class b { } abstract class d { public abstract void foo ( b x = null ) ; } class [|c|] : d { }", @"using System ; class b { } abstract class d { public abstract void foo ( b x = null ) ; } class c : d { public override void foo ( b x = null ) { throw new NotImplementedException ( ) ; } }"); } @@ -160,7 +189,7 @@ public async Task TestOptionalObjectParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestDifferentAccessorAccessibility() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class c1 { public abstract c1 this [ c1 x ] { get ; internal set ; } } class [|c2|] : c1 { } ", @"using System ; abstract class c1 { public abstract c1 this [ c1 x ] { get ; internal set ; } } class c2 : c1 { public override c1 this [ c1 x ] { get { throw new NotImplementedException ( ) ; } internal set { throw new NotImplementedException ( ) ; } } } "); } @@ -168,7 +197,7 @@ public async Task TestDifferentAccessorAccessibility() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestEvent1() { - await TestAsync( + await TestAllOptionsOffAsync( @"using System ; abstract class C { public abstract event Action E ; } class [|D|] : C { } ", @"using System ; abstract class C { public abstract event Action E ; } class D : C { public override event Action E ; } "); } @@ -176,7 +205,7 @@ public async Task TestEvent1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestIndexer1() { - await TestAsync( + await TestAllOptionsOffAsync( @"using System ; abstract class C { public abstract int this [ string s ] { get { } internal set { } } } class [|D|] : C { } ", @"using System ; abstract class C { public abstract int this [ string s ] { get { } internal set { } } } class D : C { public override int this [ string s ] { get { throw new NotImplementedException ( ) ; } internal set { throw new NotImplementedException ( ) ; } } } "); } @@ -199,7 +228,7 @@ class [|Program|] : Foo [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestGenerateIntoNonHiddenPart() { - await TestAsync( + await TestAllOptionsOffAsync( @"using System; abstract class Foo { public abstract void F(); } @@ -235,7 +264,7 @@ public override void F() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestGenerateIfLocationAvailable() { - await TestAsync( + await TestAllOptionsOffAsync( @"#line default using System; @@ -276,7 +305,7 @@ void Bar() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestOnlyGenerateUnimplementedAccessors() { - await TestAsync( + await TestAllOptionsOffAsync( @"using System ; abstract class A { public abstract int X { get ; set ; } } abstract class B : A { public override int X { get { throw new NotImplementedException ( ) ; } } } class [|C|] : B { } ", @"using System ; abstract class A { public abstract int X { get ; set ; } } abstract class B : A { public override int X { get { throw new NotImplementedException ( ) ; } } } class C : B { public override int X { set { throw new NotImplementedException ( ) ; } } } "); } @@ -285,7 +314,7 @@ public async Task TestOnlyGenerateUnimplementedAccessors() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestParamsArray() { - await TestAsync( + await TestAllOptionsOffAsync( @"class A { public virtual void Foo ( int x , params int [ ] y ) { } } abstract class B : A { public abstract override void Foo ( int x , int [ ] y = null ) ; } class [|C|] : B { } ", @"using System ; class A { public virtual void Foo ( int x , params int [ ] y ) { } } abstract class B : A { public abstract override void Foo ( int x , int [ ] y = null ) ; } class C : B { public override void Foo ( int x , params int [ ] y ) { throw new NotImplementedException ( ) ; } } "); } @@ -294,7 +323,7 @@ public async Task TestParamsArray() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestNullPointerType() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class C { unsafe public abstract void Foo ( int * x = null ) ; } class [|D|] : C { } ", @"using System ; abstract class C { unsafe public abstract void Foo ( int * x = null ) ; } class D : C { public override unsafe void Foo ( int * x = null ) { throw new NotImplementedException ( ) ; } } "); } @@ -303,7 +332,7 @@ public async Task TestNullPointerType() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestErrorTypeCalledVar() { - await TestAsync( + await TestAllOptionsOffAsync( @"extern alias var ; abstract class C { public abstract void Foo ( var :: X x ) ; } class [|D|] : C { } ", @"extern alias var ; using System ; abstract class C { public abstract void Foo ( var :: X x ) ; } class D : C { public override void Foo ( X x ) { throw new NotImplementedException ( ) ; } } "); } @@ -312,7 +341,7 @@ public async Task TestErrorTypeCalledVar() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task Bugfix_581500() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class A { public abstract void M(T x); @@ -345,7 +374,7 @@ public override void M(B.T x) [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task Bugfix_625442() { - await TestAsync( + await TestAllOptionsOffAsync( @"abstract class A { public abstract void M(T x); @@ -378,7 +407,7 @@ public override void M(A.B>.B.T x) [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task ImplementClassWithInaccessibleMembers() { - await TestAsync( + await TestAllOptionsOffAsync( @"using System ; using System . Globalization ; public class [|x|] : EastAsianLunisolarCalendar { } ", @"using System ; using System . Globalization ; public class x : EastAsianLunisolarCalendar { public override int [ ] Eras { get { throw new NotImplementedException ( ) ; } } internal override EraInfo [ ] CalEraInfo { get { throw new NotImplementedException ( ) ; } } internal override int MaxCalendarYear { get { throw new NotImplementedException ( ) ; } } internal override DateTime MaxDate { get { throw new NotImplementedException ( ) ; } } internal override int MinCalendarYear { get { throw new NotImplementedException ( ) ; } } internal override DateTime MinDate { get { throw new NotImplementedException ( ) ; } } public override int GetEra ( DateTime time ) { throw new NotImplementedException ( ) ; } internal override int GetGregorianYear ( int year , int era ) { throw new NotImplementedException ( ) ; } internal override int GetYear ( int year , DateTime time ) { throw new NotImplementedException ( ) ; } internal override int GetYearInfo ( int LunarYear , int Index ) { throw new NotImplementedException ( ) ; } } "); } @@ -387,7 +416,7 @@ public async Task ImplementClassWithInaccessibleMembers() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestPartialClass1() { - await TestAsync( + await TestAllOptionsOffAsync( @" using System; @@ -416,7 +445,7 @@ partial class A { } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestPartialClass2() { - await TestAsync( + await TestAllOptionsOffAsync( @" using System; @@ -440,5 +469,284 @@ partial class A { partial class A : Base { } "); } + + [WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] + public async Task TestCodeStyle_Method1() + { + await TestAsync( +@"abstract class A +{ + public abstract void M(int x); +} + +class [|T|] : A { } +", +@"using System; + +abstract class A +{ + public abstract void M(int x); +} + +class T : A +{ + public override void M(int x) => throw new NotImplementedException(); +} +", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.TrueWithNoneEnforcement)); + } + + [WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] + public async Task TestCodeStyle_Property1() + { + await TestAsync( +@"abstract class A +{ + public abstract int M { get; } +} + +class [|T|] : A { } +", +@"using System; + +abstract class A +{ + public abstract int M { get; } +} + +class T : A +{ + public override int M => throw new NotImplementedException(); +} +", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.TrueWithNoneEnforcement)); + } + + [WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] + public async Task TestCodeStyle_Property3() + { + await TestAsync( +@"abstract class A +{ + public abstract int M { set; } +} + +class [|T|] : A { } +", +@"using System; + +abstract class A +{ + public abstract int M { set; } +} + +class T : A +{ + public override int M { set { throw new NotImplementedException(); } } +} +", options: OptionsSet( + Tuple.Create((IOption)CSharpCodeStyleOptions.PreferExpressionBodiedProperties, true, NotificationOption.None), + Tuple.Create((IOption)CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, false, NotificationOption.None))); + } + + [WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] + public async Task TestCodeStyle_Property4() + { + await TestAsync( +@"abstract class A +{ + public abstract int M { get; set; } +} + +class [|T|] : A { } +", +@"using System; + +abstract class A +{ + public abstract int M { get; set; } +} + +class T : A +{ + public override int M { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } +} +", options: OptionsSet( + Tuple.Create((IOption)CSharpCodeStyleOptions.PreferExpressionBodiedProperties, true, NotificationOption.None), + Tuple.Create((IOption)CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, false, NotificationOption.None))); + } + + [WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] + public async Task TestCodeStyle_Indexers1() + { + await TestAsync( +@"abstract class A +{ + public abstract int this[int i] { get; } +} + +class [|T|] : A { } +", +@"using System; + +abstract class A +{ + public abstract int this[int i] { get; } +} + +class T : A +{ + public override int this[int i] => throw new NotImplementedException(); +} +", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.TrueWithNoneEnforcement)); + } + + [WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] + public async Task TestCodeStyle_Indexer3() + { + await TestAsync( +@"abstract class A +{ + public abstract int this[int i] { set; } +} + +class [|T|] : A { } +", +@"using System; + +abstract class A +{ + public abstract int this[int i] { set; } +} + +class T : A +{ + public override int this[int i] { set { throw new NotImplementedException(); } } +} +", options: OptionsSet( + Tuple.Create((IOption)CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, true, NotificationOption.None), + Tuple.Create((IOption)CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, false, NotificationOption.None))); + } + + [WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] + public async Task TestCodeStyle_Indexer4() + { + await TestAsync( +@"abstract class A +{ + public abstract int this[int i] { get; set; } +} + +class [|T|] : A { } +", +@"using System; + +abstract class A +{ + public abstract int this[int i] { get; set; } +} + +class T : A +{ + public override int this[int i] { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } +} +", options: OptionsSet( + Tuple.Create((IOption)CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, true, NotificationOption.None), + Tuple.Create((IOption)CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, false, NotificationOption.None))); + } + + [WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] + public async Task TestCodeStyle_Accessor1() + { + await TestAsync( +@"abstract class A +{ + public abstract int M { get; } +} + +class [|T|] : A { } +", +@"using System; + +abstract class A +{ + public abstract int M { get; } +} + +class T : A +{ + public override int M { get => throw new NotImplementedException(); } +} +", options: OptionsSet( + Tuple.Create((IOption)CSharpCodeStyleOptions.PreferExpressionBodiedProperties, false, NotificationOption.None), + Tuple.Create((IOption)CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, true, NotificationOption.None))); + } + + [WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] + public async Task TestCodeStyle_Accessor3() + { + await TestAsync( +@"abstract class A +{ + public abstract int M { set; } +} + +class [|T|] : A { } +", +@"using System; + +abstract class A +{ + public abstract int M { set; } +} + +class T : A +{ + public override int M { set => throw new NotImplementedException(); } +} +", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithNoneEnforcement)); + } + + [WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] + public async Task TestCodeStyle_Accessor4() + { + await TestAsync( +@"abstract class A +{ + public abstract int M { get; set; } +} + +class [|T|] : A { } +", +@"using System; + +abstract class A +{ + public abstract int M { get; set; } +} + +class T : A +{ + public override int M { + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); + } +} +", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithNoneEnforcement)); + } } } \ No newline at end of file diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/ImplementInterface/ImplementInterfaceTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/ImplementInterface/ImplementInterfaceTests.cs index 113ad1aed051ea80668f977cb92abd4bdcc8d9a7..c1823d5d97bd7652f023cb02ba21ae8d6b8ae9db 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/ImplementInterface/ImplementInterfaceTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/ImplementInterface/ImplementInterfaceTests.cs @@ -1,12 +1,16 @@ // 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.Collections.Generic; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.CodeFixes.ImplementInterface; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Options; using Roslyn.Test.Utilities; using Xunit; @@ -19,14 +23,91 @@ public partial class ImplementInterfaceTests : AbstractCSharpDiagnosticProviderB return new Tuple(null, new ImplementInterfaceCodeFixProvider()); } + private static readonly Dictionary AllOptionsOff = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.FalseWithNoneEnforcement } + }; + + private static readonly Dictionary AllOptionsOn = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CodeStyleOptions.TrueWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.TrueWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.TrueWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.TrueWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.TrueWithNoneEnforcement } + }; + + private static readonly Dictionary AccessorOptionsOn = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.FalseWithNoneEnforcement } + }; + + internal async Task TestWithAllCodeStyleOptionsOffAsync( + string initialMarkup, string expectedMarkup, + int index = 0, bool compareTokens = true, + ParseOptions parseOptions = null, + bool withScriptOption = false) + { + await TestAsync(initialMarkup, expectedMarkup, parseOptions, null, + index, compareTokens, options: AllOptionsOff, withScriptOption: withScriptOption); + } + + internal async Task TestWithAllCodeStyleOptionsOnAsync( + string initialMarkup, string expectedMarkup, + int index = 0, bool compareTokens = true, + ParseOptions parseOptions = null, + bool withScriptOption = false) + { + await TestAsync(initialMarkup, expectedMarkup, parseOptions, null, + index, compareTokens, options: AllOptionsOn, withScriptOption: withScriptOption); + } + + internal async Task TestWithAccessorCodeStyleOptionsOnAsync( + string initialMarkup, string expectedMarkup, + int index = 0, bool compareTokens = true, + ParseOptions parseOptions = null, + bool withScriptOption = false) + { + await TestAsync(initialMarkup, expectedMarkup, parseOptions, null, + index, compareTokens, options: AccessorOptionsOn, withScriptOption: withScriptOption); + } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestMethod() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface { void Method1 ( ) ; } class Class : [|IInterface|] { } ", @"using System; interface IInterface { void Method1 ( ) ; } class Class : IInterface { public void Method1 ( ) { throw new NotImplementedException ( ) ; } } "); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestExpressionBodiedMethod1() + { + await TestWithAllCodeStyleOptionsOnAsync( +@"interface IInterface { void Method1 ( ) ; } class Class : [|IInterface|] { } ", +@"using System; +interface IInterface { + void Method1 ( ) ; +} +class Class : IInterface { + public void Method1 ( ) => throw new NotImplementedException ( ) ; +}"); + } + private static readonly string s_tupleElementNamesAttribute = @"namespace System.Runtime.CompilerServices { @@ -38,7 +119,7 @@ public sealed class TupleElementNamesAttribute : Attribute { } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface), Test.Utilities.CompilerTrait(Test.Utilities.CompilerFeature.Tuples)] public async Task TupleWithNamesInMethod() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface { [return: System.Runtime.CompilerServices.TupleElementNames(new[] { ""a"", ""b"" })] (int a, int b)[] Method1 ((int c, string) x); } class Class : [|IInterface|] { } " + s_tupleElementNamesAttribute, @"using System; interface IInterface { [return: System.Runtime.CompilerServices.TupleElementNames(new[] { ""a"", ""b"" })] (int a, int b)[] Method1 ((int c, string) x) ; } class Class : IInterface { public (int a, int b)[] Method1 ((int c, string) x) { throw new NotImplementedException ( ) ; } } " + s_tupleElementNamesAttribute); } @@ -46,7 +127,7 @@ public async Task TupleWithNamesInMethod() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface), Test.Utilities.CompilerTrait(Test.Utilities.CompilerFeature.Tuples)] public async Task TupleWithNamesInMethod_Explicitly() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface { [return: System.Runtime.CompilerServices.TupleElementNames(new[] { ""a"", ""b"" })] (int a, int b)[] Method1 ((int c, string) x); } class Class : [|IInterface|] { } " + s_tupleElementNamesAttribute, @"using System; interface IInterface { [return: System.Runtime.CompilerServices.TupleElementNames(new[] { ""a"", ""b"" })] (int a, int b)[] Method1 ((int c, string) x) ; } class Class : IInterface { (int a, int b)[] IInterface.Method1 ((int c, string) x) { throw new NotImplementedException ( ) ; } } " + s_tupleElementNamesAttribute, index: 1); @@ -55,7 +136,7 @@ public async Task TupleWithNamesInMethod_Explicitly() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface), Test.Utilities.CompilerTrait(Test.Utilities.CompilerFeature.Tuples)] public async Task TupleWithNamesInProperty() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface { [System.Runtime.CompilerServices.TupleElementNames(new[] { ""a"", ""b"" })] (int a, int b)[] Property1 { [System.Runtime.CompilerServices.TupleElementNames(new[] { ""a"", ""b"" })] get; [System.Runtime.CompilerServices.TupleElementNames(new[] { ""a"", ""b"" })] set; } } class Class : [|IInterface|] { } " + s_tupleElementNamesAttribute, @"using System; interface IInterface { [System.Runtime.CompilerServices.TupleElementNames(new[] { ""a"", ""b"" })] (int a, int b)[] Property1 { [System.Runtime.CompilerServices.TupleElementNames(new[] { ""a"", ""b"" })] get; [System.Runtime.CompilerServices.TupleElementNames(new[] { ""a"", ""b"" })] set; } } class Class : IInterface { public (int a, int b)[] Property1 { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } } " + s_tupleElementNamesAttribute); } @@ -63,7 +144,7 @@ public async Task TupleWithNamesInProperty() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface), Test.Utilities.CompilerTrait(Test.Utilities.CompilerFeature.Tuples)] public async Task TupleWithNamesInEvent() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface { [System.Runtime.CompilerServices.TupleElementNames(new[] { ""a"", ""b"" })] event Func<(int a, int b)> Event1; } class Class : [|IInterface|] { } " + s_tupleElementNamesAttribute, @"interface IInterface { [System.Runtime.CompilerServices.TupleElementNames(new[] { ""a"", ""b"" })] event Func<(int a, int b)> Event1; } class Class : IInterface { public event Func<(int a, int b)> Event1; } " + s_tupleElementNamesAttribute); } @@ -71,7 +152,7 @@ public async Task TupleWithNamesInEvent() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task NoDynamicAttributeInMethod() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface { [return: System.Runtime.CompilerServices.DynamicAttribute()] object Method1 (); } class Class : [|IInterface|] { } ", @"using System; interface IInterface { [return: System.Runtime.CompilerServices.DynamicAttribute()] object Method1 (); } class Class : IInterface { public object Method1 () { throw new NotImplementedException ( ) ; } } "); } @@ -79,7 +160,7 @@ public async Task NoDynamicAttributeInMethod() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestMethodWhenClassBracesAreMissing() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface { void Method1 ( ) ; } class Class : [|IInterface|] ", @"using System; interface IInterface { void Method1 ( ) ; } class Class : IInterface { public void Method1 ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -87,7 +168,7 @@ public async Task TestMethodWhenClassBracesAreMissing() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestInheritance1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface1 { void Method1 ( ) ; } interface IInterface2 : IInterface1 { } class Class : [|IInterface2|] { } ", @"using System; interface IInterface1 { void Method1 ( ) ; } interface IInterface2 : IInterface1 { } class Class : IInterface2 { public void Method1 ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -95,7 +176,7 @@ public async Task TestInheritance1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestInheritance2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface1 { } interface IInterface2 : IInterface1 { void Method1 ( ) ; } class Class : [|IInterface2|] { } ", @"using System; interface IInterface1 { } interface IInterface2 : IInterface1 { void Method1 ( ) ; } class Class : IInterface2 { public void Method1 ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -103,7 +184,7 @@ public async Task TestInheritance2() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestInheritance3() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface1 { void Method1 ( ) ; } interface IInterface2 : IInterface1 { void Method2 ( ) ; } class Class : [|IInterface2|] { } ", @"using System; interface IInterface1 { void Method1 ( ) ; } interface IInterface2 : IInterface1 { void Method2 ( ) ; } class Class : IInterface2 { public void Method1 ( ) { throw new NotImplementedException ( ) ; } public void Method2 ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -111,7 +192,7 @@ public async Task TestInheritance3() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestInheritanceMatchingMethod() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface1 { void Method1 ( ) ; } interface IInterface2 : IInterface1 { void Method1 ( ) ; } class Class : [|IInterface2|] { } ", @"using System; interface IInterface1 { void Method1 ( ) ; } interface IInterface2 : IInterface1 { void Method1 ( ) ; } class Class : IInterface2 { public void Method1 ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -119,7 +200,7 @@ public async Task TestInheritanceMatchingMethod() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestExistingConflictingMethodReturnType() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface1 { void Method1 ( ) ; } class Class : [|IInterface1|] { public int Method1 ( ) { return 0 ; } } ", @"using System; interface IInterface1 { void Method1 ( ) ; } class Class : IInterface1 { public int Method1 ( ) { return 0 ; } void IInterface1 . Method1 ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -127,7 +208,7 @@ public async Task TestExistingConflictingMethodReturnType() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestExistingConflictingMethodParameters() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface1 { void Method1 ( int i ) ; } class Class : [|IInterface1|] { public void Method1 ( string i ) { } } ", @"using System; interface IInterface1 { void Method1 ( int i ) ; } class Class : IInterface1 { public void Method1 ( int i ) { throw new NotImplementedException ( ) ; } public void Method1 ( string i ) { } } "); } @@ -135,7 +216,7 @@ public async Task TestExistingConflictingMethodParameters() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementGenericType() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface1 < T > { void Method1 ( T t ) ; } class Class : [|IInterface1 < int >|] { } ", @"using System; interface IInterface1 < T > { void Method1 ( T t ) ; } class Class : IInterface1 < int > { public void Method1 ( int t ) { throw new NotImplementedException ( ) ; } } "); } @@ -143,7 +224,7 @@ public async Task TestImplementGenericType() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementGenericTypeWithGenericMethod() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface1 < T > { void Method1 < U > ( T t , U u ) ; } class Class : [|IInterface1 < int >|] { } ", @"using System; interface IInterface1 < T > { void Method1 < U > ( T t , U u ) ; } class Class : IInterface1 < int > { public void Method1 < U > ( int t , U u ) { throw new NotImplementedException ( ) ; } } "); } @@ -151,7 +232,7 @@ public async Task TestImplementGenericTypeWithGenericMethod() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementGenericTypeWithGenericMethodWithNaturalConstraint() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface1 < T > { void Method1 < U > ( T t , U u ) where U : IList < T > ; } class Class : [|IInterface1 < int >|] { } ", @"using System; interface IInterface1 < T > { void Method1 < U > ( T t , U u ) where U : IList < T > ; } class Class : IInterface1 < int > { public void Method1 < U > ( int t , U u ) where U : IList { throw new NotImplementedException ( ) ; } } "); } @@ -159,7 +240,7 @@ public async Task TestImplementGenericTypeWithGenericMethodWithNaturalConstraint [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementGenericTypeWithGenericMethodWithUnexpressibleConstraint() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface1 < T > { void Method1 < U > ( T t , U u ) where U : T ; } class Class : [|IInterface1 < int >|] { } ", @"using System; interface IInterface1 < T > { void Method1 < U > ( T t , U u ) where U : T ; } class Class : IInterface1 < int > { void IInterface1 < int > . Method1 < U > ( int t , U u ) { throw new NotImplementedException ( ) ; } } "); } @@ -167,7 +248,7 @@ public async Task TestImplementGenericTypeWithGenericMethodWithUnexpressibleCons [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestArrayType() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { string [ ] M ( ) ; } class C : [|I|] { } ", @"using System; interface I { string [ ] M ( ) ; } class C : I { public string [ ] M ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -175,7 +256,7 @@ public async Task TestArrayType() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementThroughFieldMember() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Method1 ( ) ; } class C : [|I|] { I i ; } ", @"interface I { void Method1 ( ) ; } class C : I { I i ; public void Method1 ( ) { i . Method1 ( ) ; } } ", index: 1); @@ -184,7 +265,7 @@ public async Task TestImplementThroughFieldMember() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementThroughFieldMemberInterfaceWithIndexer() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IFoo { int this[int x] { get; set; } } class Foo : [|IFoo|] { IFoo f; }", @"interface IFoo { int this[int x] { get; set; } } class Foo : IFoo { IFoo f; public int this[int x] { get { return f[x]; } set { f[x] = value; } } }", index: 1); @@ -194,7 +275,7 @@ public async Task TestImplementThroughFieldMemberInterfaceWithIndexer() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementThroughFieldMemberRemoveUnnecessaryCast() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System.Collections; sealed class X : [|IComparer|] { X x; }", @"using System.Collections; sealed class X : IComparer { X x; public int Compare(object x, object y) { return this.x.Compare(x, y); } }", index: 1); @@ -204,7 +285,7 @@ public async Task TestImplementThroughFieldMemberRemoveUnnecessaryCast() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementThroughFieldMemberRemoveUnnecessaryCastAndThis() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System.Collections; sealed class X : [|IComparer|] { X a; }", @"using System.Collections; sealed class X : IComparer { X a; public int Compare(object x, object y) { return a.Compare(x, y); } }", index: 1); @@ -213,7 +294,7 @@ public async Task TestImplementThroughFieldMemberRemoveUnnecessaryCastAndThis() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementAbstract() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Method1 ( ) ; } abstract class C : [|I|] { } ", @"interface I { void Method1 ( ) ; } abstract class C : I { public abstract void Method1 ( ) ; } ", index: 1); @@ -222,7 +303,7 @@ public async Task TestImplementAbstract() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementInterfaceWithRefOutParameters() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"class C : [|I|] { I foo ; } interface I { void Method1 ( ref int x , out int y , int z ) ; int Method2 ( ) ; } ", @"class C : I { I foo ; public void Method1 ( ref int x , out int y , int z ) { foo . Method1 ( ref x , out y , z ) ; } public int Method2 ( ) { return foo . Method2 ( ) ; } } interface I { void Method1 ( ref int x , out int y , int z ) ; int Method2 ( ) ; } ", index: 1); @@ -231,7 +312,7 @@ public async Task TestImplementInterfaceWithRefOutParameters() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestConflictingMethods1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"class B { public int Method1 ( ) { } } class C : B , [|I|] { } interface I { void Method1 ( ) ; } ", @"using System; class B { public int Method1 ( ) { } } class C : B , I { void I.Method1 ( ) { throw new NotImplementedException ( ) ; } } interface I { void Method1 ( ) ; } "); } @@ -239,7 +320,7 @@ public async Task TestConflictingMethods1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestConflictingProperties() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"class Test : [|I1|] { int Prop { get ; set ; } } interface I1 { int Prop { get ; set ; } } ", @"using System ; class Test : I1 { int I1 . Prop { get { throw new NotImplementedException ( ) ; } set { throw new NotImplementedException ( ) ; } } int Prop { get ; set ; } } interface I1 { int Prop { get ; set ; } } "); } @@ -256,7 +337,7 @@ public async Task TestExplicitProperties() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestEscapedMethodName() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface { void @M ( ) ; } class Class : [|IInterface|] { } ", @"using System; interface IInterface { void @M ( ) ; } class Class : IInterface { public void M ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -265,7 +346,7 @@ public async Task TestEscapedMethodName() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestEscapedMethodKeyword() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface { void @int ( ) ; } class Class : [|IInterface|] { } ", @"using System; interface IInterface { void @int ( ) ; } class Class : IInterface { public void @int ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -274,7 +355,7 @@ public async Task TestEscapedMethodKeyword() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestEscapedInterfaceName1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface @IInterface { void M ( ) ; } class Class : [|@IInterface|] { string M ( ) ; } ", @"using System; interface @IInterface { void M ( ) ; } class Class : @IInterface { void IInterface . M ( ) { throw new NotImplementedException ( ) ; } string M ( ) ; } "); } @@ -283,7 +364,7 @@ public async Task TestEscapedInterfaceName1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestEscapedInterfaceName2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface @IInterface { void @M ( ) ; } class Class : [|@IInterface|] { string M ( ) ; } ", @"using System; interface @IInterface { void @M ( ) ; } class Class : @IInterface { void IInterface . M ( ) { throw new NotImplementedException ( ) ; } string M ( ) ; } "); } @@ -292,7 +373,7 @@ public async Task TestEscapedInterfaceName2() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestEscapedInterfaceKeyword1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface @int { void M ( ) ; } class Class : [|@int|] { string M ( ) ; } ", @"using System; interface @int { void M ( ) ; } class Class : @int { void @int . M ( ) { throw new NotImplementedException ( ) ; } string M ( ) ; } "); } @@ -301,7 +382,7 @@ public async Task TestEscapedInterfaceKeyword1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestEscapedInterfaceKeyword2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface @int { void @bool ( ) ; } class Class : [|@int|] { string @bool ( ) ; } ", @"using System; interface @int { void @bool ( ) ; } class Class : @int { void @int . @bool ( ) { throw new NotImplementedException ( ) ; } string @bool ( ) ; } "); } @@ -310,7 +391,7 @@ public async Task TestEscapedInterfaceKeyword2() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestPropertyFormatting() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"public interface DD { int Prop { get; set; } @@ -342,10 +423,322 @@ public int Prop compareTokens: false); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestProperty_PropertyCodeStyleOn1() + { + await TestWithAllCodeStyleOptionsOnAsync( +@"public interface DD +{ + int Prop { get; } +} +public class A : [|DD|] +{ +}", +@"using System; + +public interface DD +{ + int Prop { get; } +} +public class A : DD +{ + public int Prop => throw new NotImplementedException(); +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestProperty_AccessorCodeStyleOn1() + { + await TestWithAccessorCodeStyleOptionsOnAsync( +@"public interface DD +{ + int Prop { get; } +} +public class A : [|DD|] +{ +}", +@"using System; + +public interface DD +{ + int Prop { get; } +} +public class A : DD +{ + public int Prop { get => throw new NotImplementedException(); } +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestIndexer_IndexerCodeStyleOn1() + { + await TestWithAllCodeStyleOptionsOnAsync( +@"public interface DD +{ + int this[int i] { get; } +} +public class A : [|DD|] +{ +}", +@"using System; + +public interface DD +{ + int this[int i] { get; } +} +public class A : DD +{ + public int this[int i] => throw new NotImplementedException(); +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestIndexer_AccessorCodeStyleOn1() + { + await TestWithAccessorCodeStyleOptionsOnAsync( +@"public interface DD +{ + int this[int i] { get; } +} +public class A : [|DD|] +{ +}", +@"using System; + +public interface DD +{ + int this[int i] { get; } +} +public class A : DD +{ + public int this[int i] { get => throw new NotImplementedException(); } +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestMethod_AllCodeStyleOn1() + { + await TestWithAllCodeStyleOptionsOnAsync( +@"public interface DD +{ + int M(); +} +public class A : [|DD|] +{ +}", +@"using System; + +public interface DD +{ + int M(); +} +public class A : DD +{ + public int M() => throw new NotImplementedException(); +}"); + } + + [WorkItem(539522, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539522")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestReadonlyPropertyExpressionBodyYes1() + { + await TestWithAllCodeStyleOptionsOnAsync( +@"public interface DD +{ + int Prop { get; } +} +public class A : [|DD|] +{ +}", +@"using System; + +public interface DD +{ + int Prop { get; } +} +public class A : DD +{ + public int Prop => throw new NotImplementedException(); +}", compareTokens: false); + } + + [WorkItem(539522, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539522")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestReadonlyPropertyAccessorBodyYes1() + { + await TestWithAccessorCodeStyleOptionsOnAsync( +@"public interface DD +{ + int Prop { get; } +} +public class A : [|DD|] +{ +}", +@"using System; + +public interface DD +{ + int Prop { get; } +} +public class A : DD +{ + public int Prop { get => throw new NotImplementedException(); } +}"); + } + + [WorkItem(539522, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539522")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestReadonlyPropertyAccessorBodyYes2() + { + await TestWithAccessorCodeStyleOptionsOnAsync( +@"public interface DD +{ + int Prop { get; set; } +} +public class A : [|DD|] +{ +}", +@"using System; + +public interface DD +{ + int Prop { get; set; } +} +public class A : DD +{ + public int Prop { + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); + } +}"); + } + + [WorkItem(539522, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539522")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestReadonlyPropertyExpressionBodyNo1() + { + await TestWithAllCodeStyleOptionsOffAsync( +@"public interface DD +{ + int Prop { get; } +} +public class A : [|DD|] +{ +}", +@"using System; + +public interface DD +{ + int Prop { get; } +} +public class A : DD +{ + public int Prop { get { throw new NotImplementedException(); } } +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestIndexerExpressionBodyYes1() + { + await TestWithAllCodeStyleOptionsOnAsync( +@"public interface DD +{ + int this[int i] { get; } +} +public class A : [|DD|] +{ +}", +@"using System; + +public interface DD +{ + int this[int i] { get; } +} +public class A : DD +{ + public int this[int i] => throw new NotImplementedException(); +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestIndexerExpressionBodyNo1() + { + await TestWithAllCodeStyleOptionsOnAsync( +@"public interface DD +{ + int this[int i] { get; set; } +} +public class A : [|DD|] +{ +}", +@"using System; + +public interface DD +{ + int this[int i] { get; set; } +} +public class A : DD +{ + public int this[int i] { + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); + } +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestIndexerAccessorExpressionBodyYes1() + { + await TestWithAccessorCodeStyleOptionsOnAsync( +@"public interface DD +{ + int this[int i] { get; } +} +public class A : [|DD|] +{ +}", +@"using System; + +public interface DD +{ + int this[int i] { get; } +} +public class A : DD +{ + public int this[int i] { get => throw new NotImplementedException(); } +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestIndexerAccessorExpressionBodyYes2() + { + await TestWithAllCodeStyleOptionsOnAsync( +@"public interface DD +{ + int this[int i] { get; set; } +} +public class A : [|DD|] +{ +}", +@"using System; + +public interface DD +{ + int this[int i] { get; set; } +} +public class A : DD +{ + public int this[int i] { + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); + } +}"); + } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestCommentPlacement() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"public interface DD { void Foo(); @@ -375,7 +768,7 @@ public void Foo() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestBracePlacement() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; class C : [|IServiceProvider|]", @"using System; @@ -402,7 +795,7 @@ public async Task TestMissingWithIncompleteMember() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestExplicitProperty() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface i1 { int p { get ; set ; } } class c1 : [|i1|] { } ", @"using System ; interface i1 { int p { get ; set ; } } class c1 : i1 { int i1 . p { get { throw new NotImplementedException ( ) ; } set { throw new NotImplementedException ( ) ; } } } ", index: 1); @@ -415,15 +808,15 @@ public async Task TestNoDelegateThroughField1() await TestActionCountAsync( @"interface I { void Method1 ( ) ; } class C : [|I|] { I i { get ; set ; } } ", count: 3); - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Method1 ( ) ; } class C : [|I|] { I i { get ; set ; } } ", @"using System ; interface I { void Method1 ( ) ; } class C : I { I i { get ; set ; } public void Method1 ( ) { throw new NotImplementedException ( ) ; } } ", index: 0); - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Method1 ( ) ; } class C : [|I|] { I i { get ; set ; } } ", @"interface I { void Method1 ( ) ; } class C : I { I i { get ; set ; } public void Method1 ( ) { i . Method1 ( ); } } ", index: 1); - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Method1 ( ) ; } class C : [|I|] { I i { get ; set ; } } ", @"using System ; interface I { void Method1 ( ) ; } class C : I { I i { get ; set ; } void I . Method1 ( ) { throw new NotImplementedException ( ) ; } } ", index: 2); @@ -433,7 +826,7 @@ public async Task TestNoDelegateThroughField1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementIReadOnlyListThroughField() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System.Collections.Generic; class A : [|IReadOnlyList|] { int[] field; }", @"using System.Collections; using System.Collections.Generic; class A : IReadOnlyList { int[] field; @@ -448,7 +841,7 @@ public async Task TestImplementIReadOnlyListThroughField() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementIReadOnlyListThroughProperty() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System.Collections.Generic; class A : [|IReadOnlyList|] { int[] field { get; set; } }", @"using System.Collections; using System.Collections.Generic; class A : IReadOnlyList { public int this[int index] { get { return ((IReadOnlyList)field)[index]; } } @@ -463,7 +856,7 @@ public async Task TestImplementIReadOnlyListThroughProperty() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementInterfaceThroughField() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { int M(); } class A : I { int I.M() { return 0; } } class B : [|I|] { A a; }", @"interface I { int M(); } class A : I { int I.M() { return 0; } } class B : I { A a; public int M() { return ((I)a).M(); } }", index: 1); @@ -479,11 +872,11 @@ public async Task TestImplementInterfaceThroughField_FieldImplementsMultipleInte await TestActionCountAsync( @"interface I { int M(); } interface I2 { int M2() } class A : I, I2 { int I.M() { return 0; } int I2.M2() { return 0; } } class B : I, [|I2|] { A a; }", count: 3); - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { int M(); } interface I2 { int M2() } class A : I, I2 { int I.M() { return 0; } int I2.M2() { return 0; } } class B : [|I|], I2 { A a; }", @"interface I { int M(); } interface I2 { int M2() } class A : I, I2 { int I.M() { return 0; } int I2.M2() { return 0; } } class B : I, I2 { A a; public int M() { return ((I)a).M(); } }", index: 1); - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { int M(); } interface I2 { int M2() } class A : I, I2 { int I.M() { return 0; } int I2.M2() { return 0; } } class B : I, [|I2|] { A a; }", @"interface I { int M(); } interface I2 { int M2() } class A : I, I2 { int I.M() { return 0; } int I2.M2() { return 0; } } class B : I, I2 { A a; public int M2() { return ((I2)a).M2(); } }", index: 1); @@ -496,11 +889,11 @@ public async Task TestImplementInterfaceThroughField_MultipleFieldsCanImplementI await TestActionCountAsync( @"interface I { int M(); } class A : I { int I.M() { return 0; } } class B : [|I|] { A a; A aa; }", count: 4); - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { int M(); } class A : I { int I.M() { return 0; } } class B : [|I|] { A a; A aa; }", @"interface I { int M(); } class A : I { int I.M() { return 0; } } class B : I { A a; A aa; public int M() { return ((I)a).M(); } }", index: 1); - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { int M(); } class A : I { int I.M() { return 0; } } class B : [|I|] { A a; A aa; }", @"interface I { int M(); } class A : I { int I.M() { return 0; } } class B : I { A a; A aa; public int M() { return ((I)aa).M(); } }", index: 2); @@ -516,11 +909,11 @@ public async Task TestImplementInterfaceThroughField_MultipleFieldsForMultipleIn await TestActionCountAsync( @"interface I { int M(); } interface I2 { int M2() } class A : I { int I.M() { return 0; } } class B : I2 { int I2.M2() { return 0; } } class C : I, [|I2|] { A a; B b; }", count: 3); - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { int M(); } interface I2 { int M2() } class A : I { int I.M() { return 0; } } class B : I2 { int I2.M2() { return 0; } } class C : [|I|], I2 { A a; B b; }", @"interface I { int M(); } interface I2 { int M2() } class A : I { int I.M() { return 0; } } class B : I2 { int I2.M2() { return 0; } } class C : I, I2 { A a; B b; public int M() { return ((I)a).M(); } }", index: 1); - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { int M(); } interface I2 { int M2() } class A : I { int I.M() { return 0; } } class B : I2 { int I2.M2() { return 0; } } class C : I, [|I2|] { A a; B b; }", @"interface I { int M(); } interface I2 { int M2() } class A : I { int I.M() { return 0; } } class B : I2 { int I2.M2() { return 0; } } class C : I, I2 { A a; B b; public int M2() { return ((I2)b).M2(); } }", index: 1); @@ -547,7 +940,7 @@ public async Task TestNoImplementThroughWriteOnlyProperty() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementEvent() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IFoo { event System . EventHandler E ; } abstract class Foo : [|IFoo|] { } ", @"using System ; interface IFoo { event System . EventHandler E ; } abstract class Foo : IFoo { public event EventHandler E ; } ", index: 0); @@ -556,7 +949,7 @@ public async Task TestImplementEvent() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementEventAbstractly() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IFoo { event System . EventHandler E ; } abstract class Foo : [|IFoo|] { } ", @"using System ; interface IFoo { event System . EventHandler E ; } abstract class Foo : IFoo { public abstract event EventHandler E ; } ", index: 1); @@ -565,7 +958,7 @@ public async Task TestImplementEventAbstractly() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementEventExplicitly() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IFoo { event System . EventHandler E ; } abstract class Foo : [|IFoo|] { } ", @"using System ; interface IFoo { event System . EventHandler E ; } abstract class Foo : IFoo { event EventHandler IFoo . E { add { throw new NotImplementedException ( ) ; } remove { throw new NotImplementedException ( ) ; } } } ", index: 2); @@ -574,7 +967,7 @@ public async Task TestImplementEventExplicitly() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestFaultToleranceInStaticMembers() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IFoo { static string Name { set ; get ; } static int Foo ( string s ) ; } class Program : [|IFoo|] { } ", @"using System ; interface IFoo { static string Name { set ; get ; } static int Foo ( string s ) ; } class Program : IFoo { public string Name { get { throw new NotImplementedException ( ) ; } set { throw new NotImplementedException ( ) ; } } public int Foo ( string s ) { throw new NotImplementedException ( ) ; } } "); } @@ -582,7 +975,7 @@ public async Task TestFaultToleranceInStaticMembers() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestIndexers() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"public interface ISomeInterface { int this [ int index ] { get ; set ; } } class IndexerClass : [|ISomeInterface|] { } ", @"using System ; public interface ISomeInterface { int this [ int index ] { get ; set ; } } class IndexerClass : ISomeInterface { public int this [ int index ] { get { throw new NotImplementedException ( ) ; } set { throw new NotImplementedException ( ) ; } } } "); } @@ -590,7 +983,7 @@ public async Task TestIndexers() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestIndexersExplicit() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"public interface ISomeInterface { int this [ int index ] { get ; set ; } } class IndexerClass : [|ISomeInterface|] { } ", @"using System ; public interface ISomeInterface { int this [ int index ] { get ; set ; } } class IndexerClass : ISomeInterface { int ISomeInterface . this [ int index ] { get { throw new NotImplementedException ( ) ; } set { throw new NotImplementedException ( ) ; } } } ", index: 1); @@ -599,7 +992,7 @@ public async Task TestIndexersExplicit() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestIndexersWithASingleAccessor() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"public interface ISomeInterface { int this [ int index ] { get ; } } class IndexerClass : [|ISomeInterface|] { } ", @"using System ; public interface ISomeInterface { int this [ int index ] { get ; } } class IndexerClass : ISomeInterface { public int this [ int index ] { get { throw new NotImplementedException ( ) ; } } } "); } @@ -608,7 +1001,7 @@ public async Task TestIndexersWithASingleAccessor() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestConstraints1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Foo < T > ( ) where T : class ; } class A : [|I|] { } ", @"using System ; interface I { void Foo < T > ( ) where T : class ; } class A : I { public void Foo < T > ( ) where T : class { throw new NotImplementedException ( ) ; } } "); } @@ -617,7 +1010,7 @@ public async Task TestConstraints1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestConstraintsExplicit() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Foo < T > ( ) where T : class ; } class A : [|I|] { } ", @"using System ; interface I { void Foo < T > ( ) where T : class ; } class A : I { void I . Foo < T > ( ) { throw new NotImplementedException ( ) ; } } ", index: 1); @@ -627,7 +1020,7 @@ public async Task TestConstraintsExplicit() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUsingAddedForConstraint() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Foo < T > ( ) where T : System . Attribute ; } class A : [|I|] { } ", @"using System ; interface I { void Foo < T > ( ) where T : System . Attribute ; } class A : I { public void Foo < T > ( ) where T : Attribute { throw new NotImplementedException ( ) ; } } "); } @@ -636,7 +1029,7 @@ public async Task TestUsingAddedForConstraint() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestIndexer() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { int this [ int x ] { get ; set ; } } class C : [|I|] { } ", @"using System ; interface I { int this [ int x ] { get ; set ; } } class C : I { public int this [ int x ] { get { throw new NotImplementedException ( ) ; } set { throw new NotImplementedException ( ) ; } } } "); } @@ -645,7 +1038,7 @@ public async Task TestIndexer() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestRecursiveConstraint1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface I { void Foo < T > ( ) where T : IComparable < T > ; } class C : [|I|] { } ", @"using System ; interface I { void Foo < T > ( ) where T : IComparable < T > ; } class C : I { public void Foo < T > ( ) where T : IComparable < T > { throw new NotImplementedException ( ) ; } } "); } @@ -654,7 +1047,7 @@ public async Task TestRecursiveConstraint1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestRecursiveConstraint2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface I { void Foo < T > ( ) where T : IComparable < T > ; } class C : [|I|] { } ", @"using System ; interface I { void Foo < T > ( ) where T : IComparable < T > ; } class C : I { void I . Foo < T > ( ) { throw new NotImplementedException ( ) ; } } ", index: 1); @@ -664,7 +1057,7 @@ public async Task TestRecursiveConstraint2() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnexpressibleConstraint1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I < S > { void Foo < T > ( ) where T : class , S ; } class A : [|I < string >|] { } ", @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } class A : I < string > { void I < string > . Foo < T > ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -673,7 +1066,7 @@ public async Task TestUnexpressibleConstraint1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnexpressibleConstraint2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I < S > { void Foo < T > ( ) where T : class , S ; } class A : [|I < object >|] { } ", @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } class A : I < object > { public void Foo < T > ( ) where T : class { throw new NotImplementedException ( ) ; } } "); } @@ -682,7 +1075,7 @@ public async Task TestUnexpressibleConstraint2() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnexpressibleConstraint3() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I < S > { void Foo < T > ( ) where T : class , S ; } class A : [|I < object >|] { } ", @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } class A : I < object > { void I < object > . Foo < T > ( ) { throw new NotImplementedException ( ) ; } } ", index: 1); @@ -692,7 +1085,7 @@ public async Task TestUnexpressibleConstraint3() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnexpressibleConstraint4() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } class A : [|I < Delegate >|] { } ", @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } class A : I < Delegate > { void I < Delegate > . Foo < T > ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -701,7 +1094,7 @@ public async Task TestUnexpressibleConstraint4() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnexpressibleConstraint5() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } class A : [|I < MulticastDelegate >|] { } ", @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } class A : I < MulticastDelegate > { void I < MulticastDelegate > . Foo < T > ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -710,7 +1103,7 @@ public async Task TestUnexpressibleConstraint5() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnexpressibleConstraint6() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } delegate void Bar ( ) ; class A : [|I < Bar >|] { } ", @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } delegate void Bar ( ) ; class A : I < Bar > { void I < Bar > . Foo < T > ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -719,7 +1112,7 @@ public async Task TestUnexpressibleConstraint6() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnexpressibleConstraint7() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } class A : [|I < Enum >|] { } ", @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } class A : I < Enum > { void I < Enum > . Foo < T > ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -728,7 +1121,7 @@ public async Task TestUnexpressibleConstraint7() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnexpressibleConstraint8() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } class A : [|I < int [ ] >|] { } ", @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } class A : I < int [ ] > { void I < int [ ] > . Foo < T > ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -737,7 +1130,7 @@ public async Task TestUnexpressibleConstraint8() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnexpressibleConstraint9() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } enum E { } class A : [|I < E >|] { } ", @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } enum E { } class A : I < E > { void I < E > . Foo < T > ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -746,7 +1139,7 @@ public async Task TestUnexpressibleConstraint9() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnexpressibleConstraint10() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface I < S > { void Foo < T > ( ) where T : S ; } class A : [|I < ValueType >|] { } ", @"using System ; interface I < S > { void Foo < T > ( ) where T : S ; } class A : I < ValueType > { void I < ValueType > . Foo < T > ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -755,7 +1148,7 @@ public async Task TestUnexpressibleConstraint10() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestArrayConstraint() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface I < S > { void Foo < T > ( ) where T : S ; } class C : [|I < Array >|] { } ", @"using System ; interface I < S > { void Foo < T > ( ) where T : S ; } class C : I < Array > { void I < Array > . Foo < T > ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -764,7 +1157,7 @@ public async Task TestArrayConstraint() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestMultipleClassConstraints() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface I < S > { void Foo < T > ( ) where T : Exception , S ; } class C : [|I < Attribute >|] { } ", @"using System ; interface I < S > { void Foo < T > ( ) where T : Exception , S ; } class C : I < Attribute > { void I < Attribute > . Foo < T > ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -773,7 +1166,7 @@ public async Task TestMultipleClassConstraints() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestClassConstraintAndRefConstraint() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } class C : [|I < Exception >|] { } ", @"using System ; interface I < S > { void Foo < T > ( ) where T : class , S ; } class C : I < Exception > { void I < Exception > . Foo < T > ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -782,7 +1175,7 @@ public async Task TestClassConstraintAndRefConstraint() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestRenameConflictingTypeParameters1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; using System . Collections . Generic ; interface I < T > { void Foo < S > ( T x , IList < S > list ) where S : T ; } class A < S > : [|I < S >|] { } ", @"using System ; using System . Collections . Generic ; interface I < T > { void Foo < S > ( T x , IList < S > list ) where S : T ; } class A < S > : I < S > { public void Foo < S1 > ( S x , IList < S1 > list ) where S1 : S { throw new NotImplementedException ( ) ; } } "); } @@ -791,7 +1184,7 @@ public async Task TestRenameConflictingTypeParameters1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestRenameConflictingTypeParameters2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; using System . Collections . Generic ; interface I < T > { void Foo < S > ( T x , IList < S > list ) where S : T ; } class A < S > : [|I < S >|] { } ", @"using System ; using System . Collections . Generic ; interface I < T > { void Foo < S > ( T x , IList < S > list ) where S : T ; } class A < S > : I < S > { void I < S > . Foo < S1 > ( S x , IList < S1 > list ) { throw new NotImplementedException ( ) ; } } ", index: 1); @@ -801,7 +1194,7 @@ public async Task TestRenameConflictingTypeParameters2() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestRenameConflictingTypeParameters3() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; using System . Collections . Generic ; interface I < X , Y > { void Foo < A , B > ( X x , Y y , IList < A > list1 , IList < B > list2 ) where A : IList < B > where B : IList < A > ; } class C < A , B > : [|I < A , B >|] { } ", @"using System ; using System . Collections . Generic ; interface I < X , Y > { void Foo < A , B > ( X x , Y y , IList < A > list1 , IList < B > list2 ) where A : IList < B > where B : IList < A > ; } class C < A , B > : I < A , B > { public void Foo < A1 , B1 > ( A x , B y , IList < A1 > list1 , IList < B1 > list2 ) where A1 : IList < B1 > where B1 : IList < A1 > { throw new NotImplementedException ( ) ; } } "); } @@ -810,7 +1203,7 @@ public async Task TestRenameConflictingTypeParameters3() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestRenameConflictingTypeParameters4() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; using System . Collections . Generic ; interface I < X , Y > { void Foo < A , B > ( X x , Y y , IList < A > list1 , IList < B > list2 ) where A : IList < B > where B : IList < A > ; } class C < A , B > : [|I < A , B >|] { } ", @"using System ; using System . Collections . Generic ; interface I < X , Y > { void Foo < A , B > ( X x , Y y , IList < A > list1 , IList < B > list2 ) where A : IList < B > where B : IList < A > ; } class C < A , B > : I < A , B > { void I < A , B > . Foo < A1 , B1 > ( A x , B y , IList < A1 > list1 , IList < B1 > list2 ) { throw new NotImplementedException ( ) ; } } ", index: 1); @@ -820,7 +1213,7 @@ public async Task TestRenameConflictingTypeParameters4() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestNameSimplification() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; class A < T > { class B { } interface I { void Foo ( B x ) ; } class C < U > : [|I|] { } } ", @"using System ; class A < T > { class B { } interface I { void Foo ( B x ) ; } class C < U > : I { public void Foo ( B x ) { throw new NotImplementedException ( ) ; } } } "); } @@ -829,7 +1222,7 @@ public async Task TestNameSimplification() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestNameSimplification2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"class A < T > { class B { } interface I { void Foo ( B [ ] x ) ; } class C < U > : [|I|] { } } ", @"using System ; class A < T > { class B { } interface I { void Foo ( B [ ] x ) ; } class C < U > : I { public void Foo ( B [ ] x ) { throw new NotImplementedException ( ) ; } } } "); } @@ -838,7 +1231,7 @@ public async Task TestNameSimplification2() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestNameSimplification3() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"class A < T > { class B { } interface I { void Foo ( B [ ] [ , ] [ , , ] [ , , , ] x ) ; } class C < U > : [|I|] { } } ", @"using System ; class A < T > { class B { } interface I { void Foo ( B [ ] [ , ] [ , , ] [ , , , ] x ) ; } class C < U > : I { public void Foo ( B [ ] [ , ] [ , , ] [ , , , ] x ) { throw new NotImplementedException ( ) ; } } } "); } @@ -847,7 +1240,7 @@ public async Task TestNameSimplification3() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementAbstractProperty() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IFoo { int Gibberish { get ; set ; } } abstract class Foo : [|IFoo|] { } ", @"interface IFoo { int Gibberish { get ; set ; } } abstract class Foo : IFoo { public abstract int Gibberish { get ; set ; } } ", index: 1); @@ -865,7 +1258,7 @@ public async Task TestMissingOnWrongArity() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplicitDefaultValue() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IOptional { int Foo ( int g = 0 ) ; } class Opt : [|IOptional|] { } ", @"using System ; interface IOptional { int Foo ( int g = 0 ) ; } class Opt : IOptional { public int Foo ( int g = 0 ) { throw new NotImplementedException ( ) ; } } "); } @@ -874,7 +1267,7 @@ public async Task TestImplicitDefaultValue() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestExplicitDefaultValue() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IOptional { int Foo ( int g = 0 ) ; } class Opt : [|IOptional|] { } ", @"using System ; interface IOptional { int Foo ( int g = 0 ) ; } class Opt : IOptional { int IOptional . Foo ( int g ) { throw new NotImplementedException ( ) ; } } ", index: 1); @@ -896,7 +1289,7 @@ class Program : [|IComparable|] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestGenerateIntoVisiblePart() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"#line default using System; @@ -930,7 +1323,7 @@ void Foo() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestGenerateIfAvailableRegionExists() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; partial class Program : [|IComparable|] @@ -977,7 +1370,7 @@ class Foo : [|IComparable|] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestOptionalDateTime1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; using System . Runtime . CompilerServices ; using System . Runtime . InteropServices ; interface IFoo { void Foo ( [ Optional ] [ DateTimeConstant ( 100 ) ] DateTime x ) ; } public class C : [|IFoo|] { } ", @"using System ; using System . Runtime . CompilerServices ; using System . Runtime . InteropServices ; interface IFoo { void Foo ( [ Optional ] [ DateTimeConstant ( 100 ) ] DateTime x ) ; } public class C : IFoo { public void Foo ( [ DateTimeConstant ( 100 ), Optional ] DateTime x ) { throw new NotImplementedException ( ) ; } } "); } @@ -986,7 +1379,7 @@ public async Task TestOptionalDateTime1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestOptionalDateTime2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; using System . Runtime . CompilerServices ; using System . Runtime . InteropServices ; interface IFoo { void Foo ( [ Optional ] [ DateTimeConstant ( 100 ) ] DateTime x ) ; } public class C : [|IFoo|] { } ", @"using System ; using System . Runtime . CompilerServices ; using System . Runtime . InteropServices ; interface IFoo { void Foo ( [ Optional ] [ DateTimeConstant ( 100 ) ] DateTime x ) ; } public class C : IFoo { void IFoo . Foo ( DateTime x ) { throw new NotImplementedException ( ) ; } } ", index: 1); @@ -996,7 +1389,7 @@ public async Task TestOptionalDateTime2() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestIUnknownIDispatchAttributes1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System . Runtime . CompilerServices ; using System . Runtime . InteropServices ; interface IFoo { void Foo1 ( [ Optional ] [ IUnknownConstant ] object x ) ; void Foo2 ( [ Optional ] [ IDispatchConstant ] object x ) ; } public class C : [|IFoo|] { } ", @"using System ; using System . Runtime . CompilerServices ; using System . Runtime . InteropServices ; interface IFoo { void Foo1 ( [ Optional ] [ IUnknownConstant ] object x ) ; void Foo2 ( [ Optional ] [ IDispatchConstant ] object x ) ; } public class C : IFoo { public void Foo1 ( [ IUnknownConstant, Optional ] object x ) { throw new NotImplementedException ( ) ; } public void Foo2 ( [ IDispatchConstant, Optional ] object x ) { throw new NotImplementedException ( ) ; } } "); } @@ -1005,7 +1398,7 @@ public async Task TestIUnknownIDispatchAttributes1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestIUnknownIDispatchAttributes2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System . Runtime . CompilerServices ; using System . Runtime . InteropServices ; interface IFoo { void Foo1 ( [ Optional ] [ IUnknownConstant ] object x ) ; void Foo2 ( [ Optional ] [ IDispatchConstant ] object x ) ; } public class C : [|IFoo|] { } ", @"using System ; using System . Runtime . CompilerServices ; using System . Runtime . InteropServices ; interface IFoo { void Foo1 ( [ Optional ] [ IUnknownConstant ] object x ) ; void Foo2 ( [ Optional ] [ IDispatchConstant ] object x ) ; } public class C : IFoo { void IFoo . Foo1 ( object x ) { throw new NotImplementedException ( ) ; } void IFoo . Foo2 ( object x ) { throw new NotImplementedException ( ) ; } } ", index: 1); @@ -1015,7 +1408,7 @@ public async Task TestIUnknownIDispatchAttributes2() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestTypeNameConflict() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IFoo { void Foo ( ) ; } public class Foo : [|IFoo|] { } ", @"using System ; interface IFoo { void Foo ( ) ; } public class Foo : IFoo { void IFoo . Foo ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -1023,7 +1416,7 @@ public async Task TestTypeNameConflict() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestStringLiteral() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IFoo { void Foo ( string s = ""\"""" ) ; } class B : [|IFoo|] { } ", @"using System ; interface IFoo { void Foo ( string s = ""\"""" ) ; } class B : IFoo { public void Foo ( string s = ""\"""" ) { throw new NotImplementedException ( ) ; } } "); } @@ -1032,7 +1425,7 @@ public async Task TestStringLiteral() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestOptionalNullableStructParameter1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"struct b { } interface d { void m ( b? x = null, b? y = default(b?) ) ; } class c : [|d|] { }", @"using System ; struct b { } interface d { void m ( b? x = null, b? y = default(b?) ) ; } class c : d { public void m ( b? x = default(b?), b? y = default(b?) ) { throw new NotImplementedException ( ) ; } }"); } @@ -1041,7 +1434,7 @@ public async Task TestOptionalNullableStructParameter1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestOptionalNullableStructParameter2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"struct b { } interface d { void m ( b? x = null, b? y = default(b?) ) ; } class c : [|d|] { }", @"using System ; struct b { } interface d { void m ( b? x = null, b? y = default(b?) ) ; } class c : d { void d.m ( b? x, b? y ) { throw new NotImplementedException ( ) ; } }", 1); } @@ -1050,7 +1443,7 @@ public async Task TestOptionalNullableStructParameter2() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestOptionalNullableIntParameter() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface d { void m ( int? x = 5, int? y = null ) ; } class c : [|d|] { }", @"using System ; interface d { void m ( int? x = 5, int? y = null ) ; } class c : d { public void m ( int? x = 5, int? y = default(int?) ) { throw new NotImplementedException ( ) ; } }"); } @@ -1059,7 +1452,7 @@ public async Task TestOptionalNullableIntParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestOptionalWithNoDefaultValue() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System . Runtime . InteropServices ; interface I { void Foo ( [ Optional ] I o ) ; } class C : [|I|] { } ", @"using System ; using System . Runtime . InteropServices ; interface I { void Foo ( [ Optional ] I o ) ; } class C : I { public void Foo ( [ Optional ] I o ) { throw new NotImplementedException ( ) ; } } "); } @@ -1067,7 +1460,7 @@ public async Task TestOptionalWithNoDefaultValue() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestIntegralAndFloatLiterals() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void M01(short s = short.MinValue); @@ -1257,7 +1650,7 @@ public void M24(double s = double.MaxValue) [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestEnumLiterals() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; enum E @@ -1321,7 +1714,7 @@ public void M2(FlagE e = FlagE.A | FlagE.B) [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestCharLiterals() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; interface I @@ -1423,7 +1816,7 @@ public void M11(char c = '\u2029') [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestRemoveParenthesesAroundTypeReference1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface I { void Foo ( DayOfWeek x = DayOfWeek . Friday ) ; } class C : [|I|] { DayOfWeek DayOfWeek { get ; set ; } } ", @"using System ; interface I { void Foo ( DayOfWeek x = DayOfWeek . Friday ) ; } class C : I { DayOfWeek DayOfWeek { get ; set ; } public void Foo ( DayOfWeek x = DayOfWeek . Friday ) { throw new NotImplementedException ( ) ; } } "); } @@ -1432,7 +1825,7 @@ public async Task TestRemoveParenthesesAroundTypeReference1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestDecimalConstants1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Foo ( decimal x = decimal . MaxValue ) ; } class C : [|I|] { } ", @"using System ; interface I { void Foo ( decimal x = decimal . MaxValue ) ; } class C : I { public void Foo ( decimal x = decimal . MaxValue ) { throw new NotImplementedException ( ) ; } } "); } @@ -1441,7 +1834,7 @@ public async Task TestDecimalConstants1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestNullablePrimitiveLiteral() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Foo ( decimal ? x = decimal . MaxValue ) ; } class C : [|I|] { } ", @"using System ; interface I { void Foo ( decimal ? x = decimal . MaxValue ) ; } class C : I { public void Foo ( decimal ? x = decimal . MaxValue ) { throw new NotImplementedException ( ) ; } } "); } @@ -1450,7 +1843,7 @@ public async Task TestNullablePrimitiveLiteral() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestNullableEnumType() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface I { void Foo ( DayOfWeek ? x = DayOfWeek . Friday ) ; } class C : [|I|] { } ", @"using System ; interface I { void Foo ( DayOfWeek ? x = DayOfWeek . Friday ) ; } class C : I { public void Foo ( DayOfWeek ? x = DayOfWeek . Friday ) { throw new NotImplementedException ( ) ; } } "); } @@ -1459,7 +1852,7 @@ public async Task TestNullableEnumType() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestByteLiterals() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Foo ( byte x = 1 ) ; } class C : [|I|] { } ", @"using System ; interface I { void Foo ( byte x = 1 ) ; } class C : I { public void Foo ( byte x = 1 ) { throw new NotImplementedException ( ) ; } } "); } @@ -1494,14 +1887,14 @@ public void Foo(ConsoleColor x = (ConsoleColor)(-1)) } }"; - await TestAsync(code, expected, compareTokens: false); + await TestWithAllCodeStyleOptionsOffAsync(code, expected, compareTokens: false); } [WorkItem(545737, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545737")] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestCastedEnumValue() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface I { void Foo ( ConsoleColor x = ( ConsoleColor ) int . MaxValue ) ; } class C : [|I|] { } ", @"using System ; interface I { void Foo ( ConsoleColor x = ( ConsoleColor ) int . MaxValue ) ; } class C : I { public void Foo ( ConsoleColor x = ( ConsoleColor ) int . MaxValue ) { throw new NotImplementedException ( ) ; } } "); } @@ -1510,7 +1903,7 @@ public async Task TestCastedEnumValue() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestNoCastFromZeroToEnum() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"enum E { A = 1 , } interface I { void Foo ( E x = 0 ) ; } class C : [|I|] { } ", @"using System ; enum E { A = 1 , } interface I { void Foo ( E x = 0 ) ; } class C : I { public void Foo ( E x = 0 ) { throw new NotImplementedException ( ) ; } } "); } @@ -1519,7 +1912,7 @@ public async Task TestNoCastFromZeroToEnum() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestMultiDimArray() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System . Runtime . InteropServices ; interface I { void Foo ( [ Optional ] [ DefaultParameterValue ( 1 ) ] int x , int [ , ] y ) ; } class C : [|I|] { } ", @"using System ; using System . Runtime . InteropServices ; interface I { void Foo ( [ Optional ] [ DefaultParameterValue ( 1 ) ] int x , int [ , ] y ) ; } class C : I { public void Foo ( [ DefaultParameterValue ( 1 ), Optional ] int x = 1 , int [ , ] y = null ) { throw new NotImplementedException ( ) ; } } "); } @@ -1528,7 +1921,7 @@ public async Task TestMultiDimArray() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestParametersAfterOptionalParameter() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System . Runtime . InteropServices ; interface I { void Foo ( [ Optional , DefaultParameterValue ( 1 ) ] int x , int [ ] y , int [ ] z ) ; } class C : [|I|] { } ", @"using System ; using System . Runtime . InteropServices ; interface I { void Foo ( [ Optional , DefaultParameterValue ( 1 ) ] int x , int [ ] y , int [ ] z ) ; } class C : I { public void Foo ( [ DefaultParameterValue ( 1 ), Optional ] int x = 1 , int [ ] y = null , int [ ] z = null ) { throw new NotImplementedException ( ) ; } } "); } @@ -1537,7 +1930,7 @@ public async Task TestParametersAfterOptionalParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestAttributeInParameter() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -1573,7 +1966,7 @@ public void Foo([DateTimeConstant(100), Optional] DateTime d1, [IUnknownConstant [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestNameConflictBetweenMethodAndTypeParameter() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I < S > { void T1 < T > ( S x , T y ) ; } class C < T > : [|I < T >|] { } ", @"using System ; interface I < S > { void T1 < T > ( S x , T y ) ; } class C < T > : I < T > { public void T1 < T2 > ( T x , T2 y ) { throw new NotImplementedException ( ) ; } } "); } @@ -1582,7 +1975,7 @@ public async Task TestNameConflictBetweenMethodAndTypeParameter() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestTypeParameterReplacementWithOuterType() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System . Collections . Generic ; interface I < S > { void Foo < T > ( S y , List < T > . Enumerator x ) ; } class D < T > : [|I < T >|] { } ", @"using System ; using System . Collections . Generic ; interface I < S > { void Foo < T > ( S y , List < T > . Enumerator x ) ; } class D < T > : I < T > { public void Foo < T1 > ( T y , List < T1 > . Enumerator x ) { throw new NotImplementedException ( ) ; } } "); } @@ -1591,7 +1984,7 @@ public async Task TestTypeParameterReplacementWithOuterType() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestFloatConstant() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Foo ( float x = 1E10F ) ; } class C : [|I|] { } ", @"using System ; interface I { void Foo ( float x = 1E10F ) ; } class C : I { public void Foo ( float x = 1E+10F ) { throw new NotImplementedException ( ) ; } } "); } @@ -1600,7 +1993,7 @@ public async Task TestFloatConstant() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestKeywordForTypeParameterName() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Foo < @class > ( ) ; } class C : [|I|] ", @"using System ; interface I { void Foo < @class > ( ) ; } class C : I { public void Foo < @class > ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -1609,7 +2002,7 @@ public async Task TestKeywordForTypeParameterName() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestExtremeDecimals() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Foo1 ( decimal x = 1E28M ) ; void Foo2 ( decimal x = - 1E28M ) ; } class C : [|I|] { } ", @"using System ; interface I { void Foo1 ( decimal x = 1E28M ) ; void Foo2 ( decimal x = - 1E28M ) ; } class C : I { public void Foo1 ( decimal x = 10000000000000000000000000000M ) { throw new NotImplementedException ( ) ; } public void Foo2 ( decimal x = -10000000000000000000000000000M ) { throw new NotImplementedException ( ) ; } } "); } @@ -1618,7 +2011,7 @@ public async Task TestExtremeDecimals() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestNonZeroScaleDecimals() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Foo ( decimal x = 0.1M ) ; } class C : [|I|] { } ", @"using System ; interface I { void Foo ( decimal x = 0.1M ) ; } class C : I { public void Foo ( decimal x = 0.1M ) { throw new NotImplementedException ( ) ; } } "); } @@ -1627,7 +2020,7 @@ public async Task TestNonZeroScaleDecimals() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnterminatedComment() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; // Implement interface @@ -1651,7 +2044,7 @@ public object GetService(Type serviceType) [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestNewLineBeforeDirective() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; // Implement interface @@ -1676,7 +2069,7 @@ public object GetService(Type serviceType) [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestCommentAfterInterfaceList1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; class C : [|IServiceProvider|] // Implement interface @@ -1697,7 +2090,7 @@ public object GetService(Type serviceType) [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestCommentAfterInterfaceList2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; class C : [|IServiceProvider|] @@ -1721,7 +2114,7 @@ public object GetService(Type serviceType) [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementIDisposable_NoDisposePattern() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; class C : [|IDisposable|]", @"using System; @@ -1740,7 +2133,7 @@ public void Dispose() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementIDisposable_DisposePattern() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; class C : [|IDisposable|]", $@"using System; @@ -1756,7 +2149,7 @@ class C : IDisposable [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementIDisposableExplicitly_NoDisposePattern() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; class C : [|IDisposable|]", @"using System; @@ -1775,7 +2168,7 @@ void IDisposable.Dispose() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementIDisposableExplicitly_DisposePattern() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; class C : [|System.IDisposable|] { @@ -1799,7 +2192,7 @@ class IDisposable [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementIDisposableAbstractly_NoDisposePattern() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; abstract class C : [|IDisposable|]", @"using System; @@ -1815,7 +2208,7 @@ abstract class C : IDisposable [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementIDisposableThroughMember_NoDisposePattern() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; class C : [|IDisposable|] { @@ -1837,7 +2230,7 @@ public void Dispose() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementIDisposableExplicitly_NoNamespaceImportForSystem() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"class C : [|System.IDisposable|]", $@"class C : System.IDisposable {{ @@ -1850,7 +2243,7 @@ public async Task TestImplementIDisposableExplicitly_NoNamespaceImportForSystem( [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementIDisposableViaBaseInterface_NoDisposePattern() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; interface I : IDisposable { @@ -1882,7 +2275,7 @@ public void F() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementIDisposableViaBaseInterface() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; interface I : IDisposable { @@ -1911,7 +2304,7 @@ public void F() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementIDisposableExplicitlyViaBaseInterface() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; interface I : IDisposable { @@ -1940,7 +2333,7 @@ void I.F() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestDontImplementDisposePatternForLocallyDefinedIDisposable() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"namespace System { interface IDisposable @@ -1970,7 +2363,7 @@ void IDisposable.Dispose() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestDontImplementDisposePatternForStructures1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; struct S : [|IDisposable|]", @"using System; @@ -1987,7 +2380,7 @@ public void Dispose() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestDontImplementDisposePatternForStructures2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; struct S : [|IDisposable|]", @"using System; @@ -2005,7 +2398,7 @@ void IDisposable.Dispose() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestEnumNestedInGeneric() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"class C < T > { public enum E { X } } interface I { void Foo < T > ( C < T > . E x = C < T > . E . X ) ; } class D : [|I|] { } ", @"using System ; class C < T > { public enum E { X } } interface I { void Foo < T > ( C < T > . E x = C < T > . E . X ) ; } class D : I { public void Foo < T > ( C < T > . E x = C < T > . E . X ) { throw new NotImplementedException ( ) ; } } "); } @@ -2014,7 +2407,7 @@ public async Task TestEnumNestedInGeneric() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnterminatedString1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; class C : [|IServiceProvider|] @"" ", @"using System ; class C : IServiceProvider @"" "" { public object GetService (Type serviceType) { throw new NotImplementedException ( ) ; } } "); } @@ -2023,7 +2416,7 @@ public async Task TestUnterminatedString1() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnterminatedString2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; class C : [|IServiceProvider|] "" ", @"using System ; class C : IServiceProvider "" "" { public object GetService (Type serviceType) { throw new NotImplementedException ( ) ; } } "); } @@ -2032,7 +2425,7 @@ public async Task TestUnterminatedString2() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnterminatedString3() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; class C : [|IServiceProvider|] @""", @"using System ; class C : IServiceProvider @"""" { public object GetService (Type serviceType) { throw new NotImplementedException ( ) ; } } "); } @@ -2041,7 +2434,7 @@ public async Task TestUnterminatedString3() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnterminatedString4() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; class C : [|IServiceProvider|] """, @"using System ; class C : IServiceProvider """" { public object GetService (Type serviceType) { throw new NotImplementedException ( ) ; } } "); } @@ -2050,7 +2443,7 @@ public async Task TestUnterminatedString4() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestDecimalENotation() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void Foo1(decimal x = 1E-25M); @@ -2100,7 +2493,7 @@ public void Foo4(decimal x = -0.000000000000000000000001M) [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestGenericEnumWithRenamedTypeParameters() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"class C < T > { public enum E { X } } interface I < S > { void Foo < T > ( S y , C < T > . E x = C < T > . E . X ) ; } class D < T > : [|I < T >|] { } ", @"using System ; class C < T > { public enum E { X } } interface I < S > { void Foo < T > ( S y , C < T > . E x = C < T > . E . X ) ; } class D < T > : I < T > { public void Foo < T1 > ( T y , C < T1 > . E x = C < T1 > . E . X ) { throw new NotImplementedException ( ) ; } } "); } @@ -2109,7 +2502,7 @@ public async Task TestGenericEnumWithRenamedTypeParameters() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestDoNotRenameTypeParameterToParameterName() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I < S > { void Foo < T > ( S T1 ) ; } class C < T > : [|I < T >|] { } ", @"using System ; interface I < S > { void Foo < T > ( S T1 ) ; } class C < T > : I < T > { public void Foo < T2 > ( T T1 ) { throw new NotImplementedException ( ) ; } } "); } @@ -2118,7 +2511,7 @@ public async Task TestDoNotRenameTypeParameterToParameterName() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestAttributes() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System . Runtime . InteropServices ; interface I { [ return : MarshalAs ( UnmanagedType . U1 ) ] bool Foo ( [ MarshalAs ( UnmanagedType . U1 ) ] bool x ) ; } class C : [|I|] { } ", @"using System ; using System . Runtime . InteropServices ; interface I { [ return : MarshalAs ( UnmanagedType . U1 ) ] bool Foo ( [ MarshalAs ( UnmanagedType . U1 ) ] bool x ) ; } class C : I { [ return : MarshalAs ( UnmanagedType . U1 ) ] public bool Foo ( [ MarshalAs ( UnmanagedType . U1 ) ] bool x ) { throw new NotImplementedException ( ) ; } } "); } @@ -2127,7 +2520,7 @@ public async Task TestAttributes() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestAttributesExplicit() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System . Runtime . InteropServices ; interface I { [ return : MarshalAs ( UnmanagedType . U1 ) ] bool Foo ( [ MarshalAs ( UnmanagedType . U1 ) ] bool x ) ; } class C : [|I|] { } ", @"using System ; using System . Runtime . InteropServices ; interface I { [ return : MarshalAs ( UnmanagedType . U1 ) ] bool Foo ( [ MarshalAs ( UnmanagedType . U1 ) ] bool x ) ; } class C : I { bool I . Foo ( bool x ) { throw new NotImplementedException ( ) ; } } ", index: 1); @@ -2137,7 +2530,7 @@ public async Task TestAttributesExplicit() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestParameterNameWithTypeName() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; interface IFoo { void Bar ( DateTime DateTime ) ; } class C : [|IFoo|] { } ", @"using System ; interface IFoo { void Bar ( DateTime DateTime ) ; } class C : IFoo { public void Bar ( DateTime DateTime ) { throw new NotImplementedException ( ) ; } } "); } @@ -2146,7 +2539,7 @@ public async Task TestParameterNameWithTypeName() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestUnboundGeneric() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System . Collections . Generic ; using System . Runtime . InteropServices ; interface I { [ return : MarshalAs ( UnmanagedType . CustomMarshaler , MarshalTypeRef = typeof ( List < > ) ) ] void Foo ( ) ; } class C : [|I|] { } ", @"using System ; using System . Collections . Generic ; using System . Runtime . InteropServices ; interface I { [ return : MarshalAs ( UnmanagedType . CustomMarshaler , MarshalTypeRef = typeof ( List < > ) ) ] void Foo ( ) ; } class C : I { [ return : MarshalAs ( UnmanagedType . CustomMarshaler , MarshalTypeRef = typeof ( List < > ) ) ] public void Foo ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -2155,7 +2548,7 @@ public async Task TestUnboundGeneric() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestQualifiedNameImplicitInterface() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"namespace N { public interface I { void M ( ) ; } } class C : [|N . I|] { } ", @"using System ; namespace N { public interface I { void M ( ) ; } } class C : N . I { public void M ( ) { throw new NotImplementedException ( ) ; } } "); } @@ -2164,7 +2557,7 @@ public async Task TestQualifiedNameImplicitInterface() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestQualifiedNameExplicitInterface() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"namespace N { public interface I { void M ( ) ; } } class C : [|N . I|] { } ", @"using System ; using N ; namespace N { public interface I { void M ( ) ; } } class C : N . I { void I . M ( ) { throw new NotImplementedException ( ) ; } } ", index: 1); } @@ -2173,7 +2566,7 @@ public async Task TestQualifiedNameExplicitInterface() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementInterfaceForPartialType() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @" public interface I { void Foo(); } partial class C { } @@ -2197,7 +2590,7 @@ void I.Foo() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementInterfaceForPartialType2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @" public interface I { void Foo(); } partial class C : [|I|] { } @@ -2221,7 +2614,7 @@ partial class C { } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementInterfaceForPartialType3() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @" public interface I { void Foo(); } public interface I2 { void Foo2(); } @@ -2283,7 +2676,7 @@ void IFoo.set_IndexProp(int p1, string Value) } "; - await TestAsync(initial, expected, index: 1); + await TestWithAllCodeStyleOptionsOffAsync(initial, expected, index: 1); } [WorkItem(602475, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/602475")] @@ -2328,7 +2721,7 @@ public void set_P(int x, object Value) } "; - await TestAsync(initial, expected, index: 0); + await TestWithAllCodeStyleOptionsOffAsync(initial, expected, index: 0); } #if false @@ -2348,7 +2741,7 @@ class Foo : [|IComparable|] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementInterfaceForImplicitIDisposable() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @" using System; @@ -2369,7 +2762,7 @@ class Program : IDisposable [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementInterfaceForExplicitIDisposable() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @" using System; @@ -2392,7 +2785,7 @@ class Program : IDisposable [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementInterfaceForIDisposableNonApplicable1() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @" using System; @@ -2419,7 +2812,7 @@ public void Dispose() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementInterfaceForIDisposableNonApplicable2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @" using System; @@ -2450,7 +2843,7 @@ public void Dispose(bool flag) [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementInterfaceForExplicitIDisposableWithSealedClass() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @" using System; @@ -2472,7 +2865,7 @@ sealed class Program : IDisposable [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestNoComAliasNameAttributeOnMethodParameters() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { void M([System.Runtime.InteropServices.ComAliasName(""pAlias"")] int p); } class C : [|I|] { }", @"using System; @@ -2484,7 +2877,7 @@ class C : I { public void M(int p) { throw new NotImplementedException(); } }"); [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestNoComAliasNameAttributeOnMethodReturnType() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System.Runtime.InteropServices; interface I { [return:ComAliasName(""pAlias1"")] long M([ComAliasName(""pAlias2"")] int p); } class C : [|I|] { }", @@ -2498,7 +2891,7 @@ class C : I { public long M(int p) { throw new NotImplementedException(); } }"); [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestNoComAliasNameAttributeOnIndexerParameters() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I { long this[[System.Runtime.InteropServices.ComAliasName(""pAlias"")] int p] { get; } } class C : [|I|] { }", @"using System; @@ -2510,7 +2903,7 @@ class C : I { public long this[int p] { get { throw new NotImplementedException( [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestMissingOpenBrace() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"namespace Scenarios { public interface TestInterface @@ -2545,7 +2938,7 @@ public void M1() public async Task TestDisposePatternWhenAdditionalUsingsAreIntroduced1() { //CSharpFeaturesResources.DisposePattern - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I : System.IDisposable, System.IEquatable where U : T { System.Collections.Generic.List M(System.Collections.Generic.Dictionary> a, T b, U c); @@ -2597,7 +2990,7 @@ public List M(Dictionary [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestDisposePatternWhenAdditionalUsingsAreIntroduced2() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface I : System.IDisposable, System.IEquatable where U : T { System.Collections.Generic.List M(System.Collections.Generic.Dictionary> a, T b, U c); @@ -2687,7 +3080,7 @@ private static string DisposePattern(string disposeVisibility, string className, [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestInaccessibleAttributes() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System; public class Foo : [|Holder.SomeInterface|] @@ -2732,7 +3125,7 @@ private class SomeAttribute : Attribute [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task TestImplementInterfaceThroughStaticMemberInGenericClass() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"using System ; using System . Collections . Generic ; using System . Linq ; using System . Threading . Tasks ; class Issue2785 < T > : [|IList < object >|] { private static List < object > innerList = new List < object > ( ) ; } ", @"using System ; using System . Collections ; using System . Collections . Generic ; using System . Linq ; using System . Threading . Tasks ; class Issue2785 < T > : IList < object > { private static List < object > innerList = new List < object > ( ) ; public object this [ int index ] { get { return ( ( IList < object > ) innerList ) [ index ] ; } set { ( ( IList < object > ) innerList ) [ index ] = value ; } } public int Count { get { return ( ( IList < object > ) innerList ) . Count ; } } public bool IsReadOnly { get { return ( ( IList < object > ) innerList ) . IsReadOnly ; } } public void Add ( object item ) { ( ( IList < object > ) innerList ) . Add ( item ) ; } public void Clear ( ) { ( ( IList < object > ) innerList ) . Clear ( ) ; } public bool Contains ( object item ) { return ( ( IList < object > ) innerList ) . Contains ( item ) ; } public void CopyTo ( object [ ] array , int arrayIndex ) { ( ( IList < object > ) innerList ) . CopyTo ( array , arrayIndex ) ; } public IEnumerator < object > GetEnumerator ( ) { return ( ( IList < object > ) innerList ) . GetEnumerator ( ) ; } public int IndexOf ( object item ) { return ( ( IList < object > ) innerList ) . IndexOf ( item ) ; } public void Insert ( int index , object item ) { ( ( IList < object > ) innerList ) . Insert ( index , item ) ; } public bool Remove ( object item ) { return ( ( IList < object > ) innerList ) . Remove ( item ) ; } public void RemoveAt ( int index ) { ( ( IList < object > ) innerList ) . RemoveAt ( index ) ; } IEnumerator IEnumerable . GetEnumerator ( ) { return ( ( IList < object > ) innerList ) . GetEnumerator ( ) ; } } ", index: 1); @@ -2741,7 +3134,7 @@ public async Task TestImplementInterfaceThroughStaticMemberInGenericClass() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface), Test.Utilities.CompilerTrait(Test.Utilities.CompilerFeature.Tuples)] public async Task LongTuple() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface { (int, string, int, string, int, string, int, string) Method1 ((int, string, int, string, int, string, int, string) y) ; } class Class : [|IInterface|] { (int, string) x; } ", @"using System; interface IInterface { (int, string, int, string, int, string, int, string) Method1 ((int, string, int, string, int, string, int, string) y) ; } class Class : IInterface { (int, string) x; public (int, string, int, string, int, string, int, string) Method1 ((int, string, int, string, int, string, int, string) y) { throw new NotImplementedException ( ) ; } } ", parseOptions: TestOptions.Regular, withScriptOption: true); @@ -2750,7 +3143,7 @@ public async Task LongTuple() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task LongTupleWithNames() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface { (int a, string b, int c, string d, int e, string f, int g, string h) Method1 ((int a, string b, int c, string d, int e, string f, int g, string h) y) ; } class Class : [|IInterface|] { (int, string) x; } ", @"using System; interface IInterface { (int a, string b, int c, string d, int e, string f, int g, string h) Method1 ((int a, string b, int c, string d, int e, string f, int g, string h) y) ; } class Class : IInterface { (int, string) x; public (int a, string b, int c, string d, int e, string f, int g, string h) Method1 ((int a, string b, int c, string d, int e, string f, int g, string h) y) { throw new NotImplementedException ( ) ; } } ", parseOptions: TestOptions.Regular, withScriptOption: true); @@ -2759,7 +3152,7 @@ public async Task LongTupleWithNames() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task GenericWithTuple() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface { (TA, TB) Method1 ((TA, TB) y) ; } class Class : [|IInterface<(int, string), int>|] { (int, string) x; } ", @"using System; interface IInterface { (TA, TB) Method1 ((TA, TB) y) ; } class Class : IInterface<(int, string), int> { (int, string) x; public ((int, string), int) Method1 (((int, string), int) y) { throw new NotImplementedException ( ) ; } } ", parseOptions: TestOptions.Regular, withScriptOption: true); @@ -2768,7 +3161,7 @@ public async Task GenericWithTuple() [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public async Task GenericWithTupleWithNamess() { - await TestAsync( + await TestWithAllCodeStyleOptionsOffAsync( @"interface IInterface { (TA a, TB b) Method1 ((TA a, TB b) y) ; } class Class : [|IInterface<(int, string), int>|] { (int, string) x; } ", @"using System; interface IInterface { (TA a, TB b) Method1 ((TA a, TB b) y) ; } class Class : IInterface<(int, string), int> { (int, string) x; public ((int, string) a, int b) Method1 (((int, string) a, int b) y) { throw new NotImplementedException ( ) ; } } ", parseOptions: TestOptions.Regular, withScriptOption: true); diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests.cs index 53c1607dece32fdb43431d487f3f1a5069191f1c..35b6e24f7714a4b76f706737bdc675632b0ebfe9 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests.cs @@ -2051,7 +2051,7 @@ static void Main() { Program a = null; } -}", null, 0); +}", parseOptions: null, index: 0); await TestMissingAsync(source, GetScriptOptions()); } @@ -2077,7 +2077,7 @@ static void Main() { int x = Console.Read() + System.Console.Read(); } -}", 0); +}", index: 0); } [WorkItem(551040, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/551040")] @@ -2163,7 +2163,7 @@ public static void Main() { int k = Preserve.X.Y; } -}", null, 0); +}", index: 0); } [WorkItem(568043, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/568043")] @@ -3293,7 +3293,7 @@ public async Task TestAppropriateDiagnosticOnMissingQualifier() { await TestDiagnosticSeverityAndCountAsync( @"class C { int SomeProperty { get; set; } void M() { [|this|].SomeProperty = 1; } }", - options: OptionsSet(Tuple.Create(CodeStyleOptions.QualifyPropertyAccess, false, NotificationOption.Warning)), + options: Option(CodeStyleOptions.QualifyPropertyAccess, false, NotificationOption.Warning), diagnosticCount: 1, diagnosticId: IDEDiagnosticIds.RemoveQualificationDiagnosticId, diagnosticSeverity: DiagnosticSeverity.Warning); diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.cs index f73924e1db40fd92da94a007318e1a3e013d9d4b..c035224ff12329000c14794d836a99843cb5d084 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.CodeFixes.SimplifyTypeNames; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Options; using Roslyn.Test.Utilities; using Xunit; @@ -931,8 +932,8 @@ void N() "; var options = OptionsSet( - Tuple.Create(CodeStyleOptions.QualifyPropertyAccess, false, NotificationOption.Suggestion), - Tuple.Create(CodeStyleOptions.QualifyFieldAccess, true, NotificationOption.Suggestion)); + Tuple.Create((IOption)CodeStyleOptions.QualifyPropertyAccess, false, NotificationOption.Suggestion), + Tuple.Create((IOption)CodeStyleOptions.QualifyFieldAccess, true, NotificationOption.Suggestion)); await TestAsync( initialMarkup: input, expectedMarkup: expected, diff --git a/src/EditorFeatures/CSharpTest/EncapsulateField/EncapsulateFieldTestState.cs b/src/EditorFeatures/CSharpTest/EncapsulateField/EncapsulateFieldTestState.cs index 97e522fa2699eaf0f778d334d864b990b4de9b23..fbb11eaf520d9ab5bb6e974af3bc1866f2573d69 100644 --- a/src/EditorFeatures/CSharpTest/EncapsulateField/EncapsulateFieldTestState.cs +++ b/src/EditorFeatures/CSharpTest/EncapsulateField/EncapsulateFieldTestState.cs @@ -3,6 +3,8 @@ using System; using System.Linq; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.EncapsulateField; using Microsoft.CodeAnalysis.Editor.Commands; using Microsoft.CodeAnalysis.Editor.CSharp.EncapsulateField; @@ -45,6 +47,8 @@ public EncapsulateFieldTestState(TestWorkspace workspace) public static async Task CreateAsync(string markup) { var workspace = await TestWorkspace.CreateCSharpAsync(markup, exportProvider: s_exportProvider); + workspace.Options = workspace.Options.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement) + .WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement); return new EncapsulateFieldTestState(workspace); } @@ -75,4 +79,4 @@ public void AssertError() Assert.NotNull(NotificationMessage); } } -} +} \ No newline at end of file diff --git a/src/EditorFeatures/CSharpTest/Interactive/CodeActions/InteractiveIntroduceVariableTests.cs b/src/EditorFeatures/CSharpTest/Interactive/CodeActions/InteractiveIntroduceVariableTests.cs index 4a33663e2f6b63346bce8011dbf8a10461568932..938a69dfb6e1676685e72407a752e94f9c38a4d6 100644 --- a/src/EditorFeatures/CSharpTest/Interactive/CodeActions/InteractiveIntroduceVariableTests.cs +++ b/src/EditorFeatures/CSharpTest/Interactive/CodeActions/InteractiveIntroduceVariableTests.cs @@ -17,7 +17,7 @@ protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspa protected Task TestAsync(string initial, string expected, int index = 0, bool compareTokens = true) { - return TestAsync(initial, expected, Options.Script, index, compareTokens); + return TestAsync(initial, expected, Options.Script, null, index, compareTokens); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsIntroduceVariable)] diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForAccessorsTests.cs b/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForAccessorsTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..c0ec624cdf68f4ccfda3195f442166f2daa0efc7 --- /dev/null +++ b/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForAccessorsTests.cs @@ -0,0 +1,273 @@ +// 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.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.UseExpressionBody; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; +using Microsoft.CodeAnalysis.Options; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseExpressionBody +{ + public class UseExpressionBodyForAccessorsTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest + { + internal override Tuple CreateDiagnosticProviderAndFixer(Workspace workspace) + => new Tuple( + new UseExpressionBodyForAccessorsDiagnosticAnalyzer(), + new UseExpressionBodyForAccessorsCodeFixProvider()); + + private static readonly Dictionary UseExpressionBody = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.FalseWithNoneEnforcement } + }; + + private static readonly Dictionary UseExpressionBodyIncludingPropertiesAndIndexers = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.TrueWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.TrueWithNoneEnforcement } + }; + + private static readonly Dictionary UseBlockBody = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement } + }; + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody1() + { + await TestAsync( +@"class C +{ + int Foo { + get { + [|return|] Bar(); + } + } +}", +@"class C +{ + int Foo { + get => Bar(); + } +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestMissingIfPropertyIsOn() + { + await TestMissingAsync( +@"class C +{ + int Foo { + get { + [|return|] Bar(); + } + } +}", options: UseExpressionBodyIncludingPropertiesAndIndexers); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestOnIndexer1() + { + await TestAsync( +@"class C +{ + int this[int i] { + get { + [|return|] Bar(); + } + } +}", +@"class C +{ + int this[int i] { + get => Bar(); + } +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestMissingIfIndexerIsOn() + { + await TestMissingAsync( +@"class C +{ + int this[int i] { + get { + [|return|] Bar(); + } + } +}", options: UseExpressionBodyIncludingPropertiesAndIndexers); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestOnSetter1() + { + await TestAsync( +@"class C +{ + int Foo { + set { + [|Bar|](); + } + } +}", +@"class C +{ + int Foo { + set => [|Bar|](); + } +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestMissingWithOnlySetter() + { + await TestMissingAsync( +@"class C +{ + int Foo { + set => [|Bar|](); + } +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody3() + { + await TestAsync( +@"class C +{ + int Foo { + get { + [|throw|] new NotImplementedException(); + } + } +}", +@"class C +{ + int Foo { + get => throw new NotImplementedException(); + } +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody4() + { + await TestAsync( +@"class C +{ + int Foo + { + get + { + [|throw|] new NotImplementedException(); // comment + } + } +}", +@"class C +{ + int Foo + { + get => throw new NotImplementedException(); // comment + } +}", compareTokens: false, options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody1() + { + await TestAsync( +@"class C +{ + int Foo { + get [|=>|] Bar(); + } +}", +@"class C +{ + int Foo { + get { + return Bar(); + } + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBodyForSetter1() + { + await TestAsync( +@"class C +{ + int Foo { + set [|=>|] Bar(); + } +}", +@"class C +{ + int Foo { + set { + Bar(); + } + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody3() + { + await TestAsync( +@"class C +{ + int Foo { + get [|=>|] throw new NotImplementedException(); + } +}", +@"class C +{ + int Foo { + get { + throw new NotImplementedException(); + } + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody4() + { + await TestAsync( +@"class C +{ + int Foo + { + get [|=>|] throw new NotImplementedException(); // comment + } +}", +@"class C +{ + int Foo + { + get + { + throw new NotImplementedException(); // comment + } + } +}", compareTokens: false, options: UseBlockBody); + } + } +} \ No newline at end of file diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForConstructorsTests.cs b/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForConstructorsTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..4e94703d7e67d8110344bd6020b946dc10f9d8a1 --- /dev/null +++ b/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForConstructorsTests.cs @@ -0,0 +1,173 @@ +// 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.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.UseExpressionBody; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; +using Microsoft.CodeAnalysis.Options; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseExpressionBody +{ + public class UseExpressionBodyForConstructorsTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest + { + internal override Tuple CreateDiagnosticProviderAndFixer(Workspace workspace) + => new Tuple( + new UseExpressionBodyForConstructorsDiagnosticAnalyzer(), + new UseExpressionBodyForConstructorsCodeFixProvider()); + + private static readonly Dictionary UseExpressionBody = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CodeStyleOptions.TrueWithNoneEnforcement } + }; + + private static readonly Dictionary UseBlockBody = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CodeStyleOptions.FalseWithNoneEnforcement } + }; + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody1() + { + await TestAsync( +@"class C +{ + public C() + { + [|Bar|](); + } +}", +@"class C +{ + public C() => Bar(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody2() + { + await TestAsync( +@"class C +{ + public C() + { + a = [|Bar|](); + } +}", +@"class C +{ + public C() => a = Bar(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody3() + { + await TestAsync( +@"class C +{ + public C() + { + [|throw|] new NotImplementedException(); + } +}", +@"class C +{ + public C() => throw new NotImplementedException(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody4() + { + await TestAsync( +@"class C +{ + public C() + { + [|throw|] new NotImplementedException(); // comment + } +}", +@"class C +{ + public C() => throw new NotImplementedException(); // comment +}", compareTokens: false, options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody1() + { + await TestAsync( +@"class C +{ + public C() [|=>|] Bar(); +}", +@"class C +{ + public C() + { + Bar(); + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody2() + { + await TestAsync( +@"class C +{ + public C() [|=>|] a = Bar(); +}", +@"class C +{ + public C() + { + a = Bar(); + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody3() + { + await TestAsync( +@"class C +{ + public C() [|=>|] throw new NotImplementedException(); +}", +@"class C +{ + public C() + { + throw new NotImplementedException(); + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody4() + { + await TestAsync( +@"class C +{ + public C() [|=>|] throw new NotImplementedException(); // comment +}", +@"class C +{ + public C() + { + throw new NotImplementedException(); // comment + } +}", compareTokens: false, options: UseBlockBody); + } + } +} \ No newline at end of file diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForConversionOperatorsTests.cs b/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForConversionOperatorsTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..c837eca38ff1fd0e76ba534d75999233dbdbf782 --- /dev/null +++ b/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForConversionOperatorsTests.cs @@ -0,0 +1,156 @@ +// 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.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.UseExpressionBody; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; +using Microsoft.CodeAnalysis.Options; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseExpressionBody +{ + public class UseExpressionBodyForConversionOperatorsTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest + { + internal override Tuple CreateDiagnosticProviderAndFixer(Workspace workspace) + => new Tuple( + new UseExpressionBodyForConversionOperatorsDiagnosticAnalyzer(), + new UseExpressionBodyForConversionOperatorsCodeFixProvider()); + + private static readonly Dictionary UseExpressionBody = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.TrueWithNoneEnforcement } + }; + + private static readonly Dictionary UseBlockBody = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.FalseWithNoneEnforcement } + }; + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody1() + { + await TestAsync( +@"class C +{ + public static implicit operator C(int i) + { + [|Bar|](); + } +}", +@"class C +{ + public static implicit operator C(int i) => Bar(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody2() + { + await TestAsync( +@"class C +{ + public static implicit operator C(int i) + { + return [|Bar|](); + } +}", +@"class C +{ + public static implicit operator C(int i) => Bar(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody3() + { + await TestAsync( +@"class C +{ + public static implicit operator C(int i) + { + [|throw|] new NotImplementedException(); + } +}", +@"class C +{ + public static implicit operator C(int i) => throw new NotImplementedException(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody4() + { + await TestAsync( +@"class C +{ + public static implicit operator C(int i) + { + [|throw|] new NotImplementedException(); // comment + } +}", +@"class C +{ + public static implicit operator C(int i) => throw new NotImplementedException(); // comment +}", compareTokens: false, options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody1() + { + await TestAsync( +@"class C +{ + public static implicit operator C(int i) [|=>|] Bar(); +}", +@"class C +{ + public static implicit operator C(int i) + { + return Bar(); + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody3() + { + await TestAsync( +@"class C +{ + public static implicit operator C(int i) [|=>|] throw new NotImplementedException(); +}", +@"class C +{ + public static implicit operator C(int i) + { + throw new NotImplementedException(); + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody4() + { + await TestAsync( +@"class C +{ + public static implicit operator C(int i) [|=>|] throw new NotImplementedException(); // comment +}", +@"class C +{ + public static implicit operator C(int i) + { + throw new NotImplementedException(); // comment + } +}", compareTokens: false, options: UseBlockBody); + } + } +} \ No newline at end of file diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForIndexerTests.cs b/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForIndexerTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..d71cf048fa0c208a4b192f26bb58b5530a18fa5d --- /dev/null +++ b/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForIndexerTests.cs @@ -0,0 +1,204 @@ +// 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.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.UseExpressionBody; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; +using Microsoft.CodeAnalysis.Options; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseExpressionBody +{ + public class UseExpressionBodyForIndexersTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest + { + internal override Tuple CreateDiagnosticProviderAndFixer(Workspace workspace) + => new Tuple( + new UseExpressionBodyForIndexersDiagnosticAnalyzer(), + new UseExpressionBodyForIndexersCodeFixProvider()); + + private static readonly Dictionary UseExpressionBody = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.TrueWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement }, + }; + + private static readonly Dictionary UseBlockBody = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement } + }; + + + private static readonly Dictionary UseBlockBodyExceptAccessor = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithNoneEnforcement } + }; + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody1() + { + await TestAsync( +@"class C +{ + int this[int i] { + get { + [|return|] Bar(); + } + } +}", +@"class C +{ + int this[int i] => Bar(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestMissingWithSetter() + { + await TestMissingAsync( +@"class C +{ + int this[int i] { + get { + [|return|] Bar(); + } + set { } + } +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestMissingOnSetter1() + { + await TestMissingAsync( +@"class C +{ + int this[int i] { + set { + [|Bar|](); + } + } +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody3() + { + await TestAsync( +@"class C +{ + int this[int i] { + get { + [|throw|] new NotImplementedException(); + } + } +}", +@"class C +{ + int this[int i] => throw new NotImplementedException(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody4() + { + await TestAsync( +@"class C +{ + int this[int i] + { + get + { + [|throw|] new NotImplementedException(); // comment + } + } +}", +@"class C +{ + int this[int i] => throw new NotImplementedException(); // comment +}", compareTokens: false, options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody1() + { + await TestAsync( +@"class C +{ + int this[int i] [|=>|] Bar(); +}", +@"class C +{ + int this[int i] { + get { + return Bar(); + } + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBodyIfAccessorWantExpression1() + { + await TestAsync( +@"class C +{ + int this[int i] [|=>|] Bar(); +}", +@"class C +{ + int this[int i] { + get => Bar(); + } +}", options: UseBlockBodyExceptAccessor); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody3() + { + await TestAsync( +@"class C +{ + int this[int i] [|=>|] throw new NotImplementedException(); +}", +@"class C +{ + int this[int i] { + get { + throw new NotImplementedException(); + } + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody4() + { + await TestAsync( +@"class C +{ + int this[int i] [|=>|] throw new NotImplementedException(); // comment +}", +@"class C +{ + int this[int i] + { + get + { + throw new NotImplementedException(); // comment + } + } +}", compareTokens: false, options: UseBlockBody); + } + } +} \ No newline at end of file diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForMethodsTests.cs b/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForMethodsTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..6e43fd2100d47f170a5725af3de8408d8caaee3e --- /dev/null +++ b/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForMethodsTests.cs @@ -0,0 +1,284 @@ +// 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.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.UseExpressionBody; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; +using Microsoft.CodeAnalysis.Options; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseExpressionBody +{ + public class UseExpressionBodyForMethodsTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest + { + internal override Tuple CreateDiagnosticProviderAndFixer(Workspace workspace) + => new Tuple( + new UseExpressionBodyForMethodsDiagnosticAnalyzer(), + new UseExpressionBodyForMethodsCodeFixProvider()); + + private static readonly Dictionary UseExpressionBody = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.TrueWithNoneEnforcement } + }; + + private static readonly Dictionary UseBlockBody = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.FalseWithNoneEnforcement } + }; + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody1() + { + await TestAsync( +@"class C +{ + void Foo() + { + [|Bar|](); + } +}", +@"class C +{ + void Foo() => Bar(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody2() + { + await TestAsync( +@"class C +{ + int Foo() + { + return [|Bar|](); + } +}", +@"class C +{ + int Foo() => Bar(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody3() + { + await TestAsync( +@"class C +{ + int Foo() + { + [|throw|] new NotImplementedException(); + } +}", +@"class C +{ + int Foo() => throw new NotImplementedException(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody4() + { + await TestAsync( +@"class C +{ + int Foo() + { + [|throw|] new NotImplementedException(); // comment + } +}", +@"class C +{ + int Foo() => throw new NotImplementedException(); // comment +}", compareTokens: false, options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody1() + { + await TestAsync( +@"class C +{ + void Foo() [|=>|] Bar(); +}", +@"class C +{ + void Foo() + { + Bar(); + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody2() + { + await TestAsync( +@"class C +{ + int Foo() [|=>|] Bar(); +}", +@"class C +{ + int Foo() + { + return Bar(); + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody3() + { + await TestAsync( +@"class C +{ + int Foo() [|=>|] throw new NotImplementedException(); +}", +@"class C +{ + int Foo() + { + throw new NotImplementedException(); + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody4() + { + await TestAsync( +@"class C +{ + int Foo() [|=>|] throw new NotImplementedException(); // comment +}", +@"class C +{ + int Foo() + { + throw new NotImplementedException(); // comment + } +}", compareTokens: false, options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestComments1() + { + await TestAsync( +@"class C +{ + void Foo() + { + // Comment + [|Bar|](); + } +}", +@"class C +{ + void Foo() => + // Comment + Bar(); +}", options: UseExpressionBody, compareTokens: false); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestComments2() + { + await TestAsync( +@"class C +{ + void Foo() + { + // Comment + return [|Bar|](); + } +}", +@"class C +{ + void Foo() => + // Comment + Bar(); +}", options: UseExpressionBody, compareTokens: false); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestComments3() + { + await TestAsync( +@"class C +{ + void Foo() + { + // Comment + throw [|Bar|](); + } +}", +@"class C +{ + void Foo() => + // Comment + throw Bar(); +}", options: UseExpressionBody, compareTokens: false); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestComments4() + { + await TestAsync( +@"class C +{ + void Foo() + { + [|Bar|](); // Comment + } +}", +@"class C +{ + void Foo() => Bar(); // Comment +}", options: UseExpressionBody, compareTokens: false); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestComments5() + { + await TestAsync( +@"class C +{ + void Foo() + { + return [|Bar|](); // Comment + } +}", +@"class C +{ + void Foo() => Bar(); // Comment +}", options: UseExpressionBody, compareTokens: false); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestComments6() + { + await TestAsync( +@"class C +{ + void Foo() + { + throw [|Bar|](); // Comment + } +}", +@"class C +{ + void Foo() => throw Bar(); // Comment +}", options: UseExpressionBody, compareTokens: false); + } + } +} \ No newline at end of file diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForOperatorsTests.cs b/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForOperatorsTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..65cfdfda69bbc7f32c64c816ce70b8b0f09295b0 --- /dev/null +++ b/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForOperatorsTests.cs @@ -0,0 +1,156 @@ +// 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.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.UseExpressionBody; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; +using Microsoft.CodeAnalysis.Options; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseExpressionBody +{ + public class UseExpressionBodyForOperatorsTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest + { + internal override Tuple CreateDiagnosticProviderAndFixer(Workspace workspace) + => new Tuple( + new UseExpressionBodyForOperatorsDiagnosticAnalyzer(), + new UseExpressionBodyForOperatorsCodeFixProvider()); + + private static readonly Dictionary UseExpressionBody = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.TrueWithNoneEnforcement } + }; + + private static readonly Dictionary UseBlockBody = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.FalseWithNoneEnforcement } + }; + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody1() + { + await TestAsync( +@"class C +{ + public static C operator +(C c1, C c2) + { + [|Bar|](); + } +}", +@"class C +{ + public static C operator +(C c1, C c2) => Bar(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody2() + { + await TestAsync( +@"class C +{ + public static C operator +(C c1, C c2) + { + return [|Bar|](); + } +}", +@"class C +{ + public static C operator +(C c1, C c2) => Bar(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody3() + { + await TestAsync( +@"class C +{ + public static C operator +(C c1, C c2) + { + [|throw|] new NotImplementedException(); + } +}", +@"class C +{ + public static C operator +(C c1, C c2) => throw new NotImplementedException(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody4() + { + await TestAsync( +@"class C +{ + public static C operator +(C c1, C c2) + { + [|throw|] new NotImplementedException(); // comment + } +}", +@"class C +{ + public static C operator +(C c1, C c2) => throw new NotImplementedException(); // comment +}", compareTokens: false, options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody1() + { + await TestAsync( +@"class C +{ + public static C operator +(C c1, C c2) [|=>|] Bar(); +}", +@"class C +{ + public static C operator +(C c1, C c2) + { + return Bar(); + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody3() + { + await TestAsync( +@"class C +{ + public static C operator +(C c1, C c2) [|=>|] throw new NotImplementedException(); +}", +@"class C +{ + public static C operator +(C c1, C c2) + { + throw new NotImplementedException(); + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody4() + { + await TestAsync( +@"class C +{ + public static C operator +(C c1, C c2) [|=>|] throw new NotImplementedException(); // comment +}", +@"class C +{ + public static C operator +(C c1, C c2) + { + throw new NotImplementedException(); // comment + } +}", compareTokens: false, options: UseBlockBody); + } + } +} \ No newline at end of file diff --git a/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForPropertiesTests.cs b/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForPropertiesTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..55a852a9634fc52b86e00eb9a33cf74881aa3ee6 --- /dev/null +++ b/src/EditorFeatures/CSharpTest/UseExpressionBody/UseExpressionBodyForPropertiesTests.cs @@ -0,0 +1,218 @@ +// 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.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.UseExpressionBody; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; +using Microsoft.CodeAnalysis.Options; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseExpressionBody +{ + public class UseExpressionBodyForPropertiesTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest + { + internal override Tuple CreateDiagnosticProviderAndFixer(Workspace workspace) + => new Tuple( + new UseExpressionBodyForPropertiesDiagnosticAnalyzer(), + new UseExpressionBodyForPropertiesCodeFixProvider()); + + private static readonly Dictionary UseExpressionBody = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.TrueWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement }, + }; + + private static readonly Dictionary UseBlockBody = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement } + }; + + private static readonly Dictionary UseBlockBodyExceptAccessor = + new Dictionary + { + { CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithNoneEnforcement } + }; + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody1() + { + await TestAsync( +@"class C +{ + int Foo { + get { + [|return|] Bar(); + } + } +}", +@"class C +{ + int Foo => Bar(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestMissingWithSetter() + { + await TestMissingAsync( +@"class C +{ + int Foo { + get { + [|return|] Bar(); + } + set { } + } +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestMissingWithAttribute() + { + await TestMissingAsync( +@"class C +{ + int Foo { + [A] + get { + [|return|] Bar(); + } + } +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestMissingOnSetter1() + { + await TestMissingAsync( +@"class C +{ + int Foo { + set { + [|Bar|](); + } + } +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody3() + { + await TestAsync( +@"class C +{ + int Foo { + get { + [|throw|] new NotImplementedException(); + } + } +}", +@"class C +{ + int Foo => throw new NotImplementedException(); +}", options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseExpressionBody4() + { + await TestAsync( +@"class C +{ + int Foo + { + get + { + [|throw|] new NotImplementedException(); // comment + } + } +}", +@"class C +{ + int Foo => throw new NotImplementedException(); // comment +}", compareTokens: false, options: UseExpressionBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody1() + { + await TestAsync( +@"class C +{ + int Foo [|=>|] Bar(); +}", +@"class C +{ + int Foo { + get { + return Bar(); + } + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBodyIfAccessorWantExpression1() + { + await TestAsync( +@"class C +{ + int Foo [|=>|] Bar(); +}", +@"class C +{ + int Foo { + get => Bar(); + } +}", options: UseBlockBodyExceptAccessor); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody3() + { + await TestAsync( +@"class C +{ + int Foo [|=>|] throw new NotImplementedException(); +}", +@"class C +{ + int Foo { + get { + throw new NotImplementedException(); + } + } +}", options: UseBlockBody); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)] + public async Task TestUseBlockBody4() + { + await TestAsync( +@"class C +{ + int Foo [|=>|] throw new NotImplementedException(); // comment +}", +@"class C +{ + int Foo + { + get + { + throw new NotImplementedException(); // comment + } + } +}", compareTokens: false, options: UseBlockBody); + } + } +} \ No newline at end of file diff --git a/src/EditorFeatures/Test/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs b/src/EditorFeatures/Test/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs index f3d78d87a431731030b5ae6206c6b26bc35d9be2..cbe2dcaea026afb26b385923bc6727972aef89ed 100644 --- a/src/EditorFeatures/Test/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs +++ b/src/EditorFeatures/Test/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs @@ -9,6 +9,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes.Suppression; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Editor.Implementation.Preview; using Microsoft.CodeAnalysis.Editor.UnitTests.Extensions; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; @@ -310,36 +311,37 @@ public abstract class AbstractCodeActionOrUserDiagnosticTest object fixProviderData = null, CodeActionPriority? priority = null) { - await TestAsync(initialMarkup, expectedMarkup, null, index, compareTokens, options, fixAllActionEquivalenceKey, fixProviderData, priority: priority); - await TestAsync(initialMarkup, expectedMarkup, GetScriptOptions(), index, compareTokens, options, fixAllActionEquivalenceKey, fixProviderData, priority: priority); + await TestAsync(initialMarkup, expectedMarkup, null, null, index, compareTokens, options, fixAllActionEquivalenceKey, fixProviderData, priority: priority); + await TestAsync(initialMarkup, expectedMarkup, GetScriptOptions(), null, index, compareTokens, options, fixAllActionEquivalenceKey, fixProviderData, priority: priority); } internal async Task TestAsync( string initialMarkup, string expectedMarkup, ParseOptions parseOptions, + CompilationOptions compilationOptions = null, int index = 0, bool compareTokens = true, IDictionary options = null, string fixAllActionEquivalenceKey = null, object fixProviderData = null, - bool withScriptOption = false, - CodeActionPriority? priority = null) + CodeActionPriority? priority = null, + bool withScriptOption = false) { - await TestAsync(initialMarkup, expectedMarkup, parseOptions, null, index, compareTokens, options, fixAllActionEquivalenceKey, fixProviderData, priority); + await TestAsync(initialMarkup, expectedMarkup, parseOptions, compilationOptions, index, compareTokens, options, fixAllActionEquivalenceKey, fixProviderData, priority); if (withScriptOption) { - await TestAsync(initialMarkup, expectedMarkup, parseOptions.WithKind(SourceCodeKind.Script), null, index, compareTokens, options, fixAllActionEquivalenceKey, fixProviderData, priority); + await TestAsync(initialMarkup, expectedMarkup, parseOptions.WithKind(SourceCodeKind.Script), compilationOptions, index, compareTokens, options, fixAllActionEquivalenceKey, fixProviderData, priority); } } - internal async Task TestAsync( + private async Task TestAsync( string initialMarkup, string expectedMarkup, ParseOptions parseOptions, CompilationOptions compilationOptions, - int index = 0, bool compareTokens = true, - IDictionary options = null, - string fixAllActionEquivalenceKey = null, - object fixProviderData = null, - CodeActionPriority? priority = null) + int index, bool compareTokens, + IDictionary options, + string fixAllActionEquivalenceKey, + object fixProviderData, + CodeActionPriority? priority) { string expected; IDictionary> spanMap; @@ -530,12 +532,13 @@ protected static IList FlattenActions(IEnumerable codeAc return codeActions?.SelectMany(a => a.HasCodeActions ? a.GetCodeActions().ToArray() : new[] { a }).ToList(); } - protected IDictionary Option(PerLanguageOption> option, bool value, CodeStyle.NotificationOption notification) - { - return OptionsSet(Tuple.Create(option, value, notification)); - } + protected IDictionary Option(IOption option, CodeStyleOption notification) + => Option(option, notification.Value, notification.Notification); + + protected IDictionary Option(IOption option, bool value, NotificationOption notification) + => OptionsSet(Tuple.Create(option, value, notification)); - protected IDictionary OptionsSet(params Tuple>, bool, CodeStyle.NotificationOption>[] optionsToSet) + protected IDictionary OptionsSet(params Tuple[] optionsToSet) { var options = new Dictionary(); foreach (var triple in optionsToSet) @@ -543,10 +546,11 @@ protected static IList FlattenActions(IEnumerable codeAc var option = triple.Item1; var value = triple.Item2; var notification = triple.Item3; - options.Add(new OptionKey(option, GetLanguage()), new CodeStyle.CodeStyleOption(value, notification)); + var optionKey = new OptionKey(option, option.IsPerLanguage ? GetLanguage() : null); + options.Add(optionKey, new CodeStyleOption(value, notification)); } return options; } } -} +} \ No newline at end of file diff --git a/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.CSharp.cs b/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.CSharp.cs index afe742136c6ad14337350be26e5351527144239b..e9c4d18c0e81872eeb95a7bd940aabfbebea3ef0 100644 --- a/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.CSharp.cs +++ b/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.CSharp.cs @@ -8,14 +8,17 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; +using Microsoft.CodeAnalysis.CodeStyle; using CS = Microsoft.CodeAnalysis.CSharp; using VB = Microsoft.CodeAnalysis.VisualBasic; @@ -639,10 +642,10 @@ public async Task AddUnsafeAutoProperty() } [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)] - public async Task AddIndexer() + public async Task AddIndexer1() { var input = "class [|C|] { }"; - var expected = "class C { public string this[int i] { get { $$ } } }"; + var expected = "class C { public string this[int i] => String.Empty; }"; await TestAddPropertyAsync(input, expected, type: typeof(string), parameters: Parameters(Parameter(typeof(int), "i")), @@ -650,6 +653,22 @@ public async Task AddIndexer() isIndexer: true); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)] + public async Task AddIndexer2() + { + var input = "class [|C|] { }"; + var expected = "class C { public string this[int i] { get { $$ } } }"; + await TestAddPropertyAsync(input, expected, + type: typeof(string), + parameters: Parameters(Parameter(typeof(int), "i")), + getStatements: "return String.Empty;", + isIndexer: true, + options: new Dictionary { + { CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement }, + { CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.FalseWithNoneEnforcement }, + }); + } + [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)] public async Task AddParameterfulProperty() { diff --git a/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.cs b/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.cs index 6de66b2e4fc0753b7b82814faab3b7a4b9be92bb..c68418c6ab9b6f704de8718126c12d6f656c7f24 100644 --- a/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.cs +++ b/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.VisualBasic; @@ -373,7 +374,8 @@ public partial class CodeGenerationTests IList> parameters = null, bool isIndexer = false, CodeGenerationOptions codeGenerationOptions = default(CodeGenerationOptions), - bool compareTokens = true) + bool compareTokens = true, + IDictionary options = null) { // This assumes that tests will not use place holders for get/set statements at the same time if (getStatements != null) @@ -388,6 +390,14 @@ public partial class CodeGenerationTests using (var context = await TestContext.CreateAsync(initial, expected, compareTokens)) { + if (options != null) + { + foreach (var kvp in options) + { + context.Workspace.Options = context.Workspace.Options.WithChangedOption(kvp.Key, kvp.Value); + } + } + var typeSymbol = GetTypeSymbol(type)(context.SemanticModel); var getParameterSymbols = GetParameterSymbols(parameters, context); var setParameterSymbols = getParameterSymbols == null ? null : new List(getParameterSymbols) { Parameter(type, "value")(context.SemanticModel) }; @@ -788,7 +798,7 @@ internal class TestContext : IDisposable public Document Result; - private readonly TestWorkspace _workspace; + public readonly TestWorkspace Workspace; private readonly string _language; private readonly bool _compareTokens; private readonly bool _ignoreResult; @@ -807,8 +817,8 @@ internal class TestContext : IDisposable this.IsVisualBasic = _language == LanguageNames.VisualBasic; _compareTokens = compareTokens; _ignoreResult = ignoreResult; - _workspace = workspace; - this.Document = _workspace.CurrentSolution.Projects.Single().Documents.Single(); + Workspace = workspace; + this.Document = Workspace.CurrentSolution.Projects.Single().Documents.Single(); this.SemanticModel = semanticModel; this.SyntaxTree = SemanticModel.SyntaxTree; this.Service = Document.Project.LanguageServices.GetService(); @@ -824,23 +834,23 @@ public static async Task CreateAsync(string initial, string expecte return new TestContext(initial, expected, compareTokens, ignoreResult, language, workspace, semanticModel); } - public Solution Solution { get { return _workspace.CurrentSolution; } } + public Solution Solution { get { return Workspace.CurrentSolution; } } public SyntaxNode GetDestinationNode() { - var destSpan = _workspace.Documents.Single().SelectedSpans.Single(); + var destSpan = Workspace.Documents.Single().SelectedSpans.Single(); return SemanticModel.SyntaxTree.GetRoot().FindNode(destSpan, getInnermostNodeForTie: true); } public INamespaceOrTypeSymbol GetDestination() { - var destSpan = _workspace.Documents.Single().SelectedSpans.Single(); + var destSpan = Workspace.Documents.Single().SelectedSpans.Single(); return GetSelectedSymbol(destSpan, this.SemanticModel); } public IEnumerable GetAnnotatedDeclaredSymbols(string key, SemanticModel semanticModel) { - var annotatedSpans = _workspace.Documents.Single().AnnotatedSpans[key]; + var annotatedSpans = Workspace.Documents.Single().AnnotatedSpans[key]; foreach (var span in annotatedSpans) { yield return GetSelectedSymbol(span, semanticModel); @@ -861,7 +871,7 @@ public T GetSelectedSymbol(TextSpan selection, SemanticModel semanticModel) public T GetSelectedSyntax(bool fullSpanCoverage = false) where T : SyntaxNode { - var destSpan = _workspace.Documents.Single().SelectedSpans.Single(); + var destSpan = Workspace.Documents.Single().SelectedSpans.Single(); var token = SemanticModel.SyntaxTree.GetRoot().FindToken(destSpan.Start); return token.Parent.AncestorsAndSelf().OfType().FirstOrDefault(t => !fullSpanCoverage || t.Span.End >= destSpan.End); } @@ -913,7 +923,7 @@ public void Dispose() } finally { - _workspace.Dispose(); + Workspace.Dispose(); } } diff --git a/src/EditorFeatures/Test/Completion/AbstractCompletionProviderTests.cs b/src/EditorFeatures/Test/Completion/AbstractCompletionProviderTests.cs index 0397937c0b5c71c18d71c6332964d713a30d0097..9039b61fbebb558a9abb487efdd654312409b4b7 100644 --- a/src/EditorFeatures/Test/Completion/AbstractCompletionProviderTests.cs +++ b/src/EditorFeatures/Test/Completion/AbstractCompletionProviderTests.cs @@ -300,6 +300,7 @@ protected virtual async Task VerifyCustomCommitProviderWorkerAsync(string codeBe private async Task VerifyCustomCommitProviderCheckResultsAsync(Document document, string codeBeforeCommit, int position, string itemToCommit, string expectedCodeAfterCommit, char? commitChar) { var workspace = await WorkspaceFixture.GetWorkspaceAsync(); + SetWorkspaceOptions(workspace); var textBuffer = workspace.Documents.Single().TextBuffer; var service = GetCompletionService(workspace); @@ -319,6 +320,10 @@ private async Task VerifyCustomCommitProviderCheckResultsAsync(Document document } } + protected virtual void SetWorkspaceOptions(TestWorkspace workspace) + { + } + internal async Task VerifyCustomCommitWorkerAsync( CompletionServiceWithProviders service, Document document, diff --git a/src/EditorFeatures/Test/Workspaces/CSharpTestWorkspaceFixture.cs b/src/EditorFeatures/Test/Workspaces/CSharpTestWorkspaceFixture.cs index 3cb50554c1b80d59ff284f75209005eb371acef0..1a30f28e8ec18e112214bc2cedf91809ad64de68 100644 --- a/src/EditorFeatures/Test/Workspaces/CSharpTestWorkspaceFixture.cs +++ b/src/EditorFeatures/Test/Workspaces/CSharpTestWorkspaceFixture.cs @@ -1,13 +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; -using System.Linq; using System.Threading.Tasks; -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Symbols; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces { @@ -20,4 +14,4 @@ protected override Task CreateWorkspaceAsync() new CSharpParseOptions[] { new CSharpParseOptions(kind: SourceCodeKind.Regular), }); } } -} +} \ No newline at end of file diff --git a/src/EditorFeatures/TestUtilities/Traits.cs b/src/EditorFeatures/TestUtilities/Traits.cs index 39a13799cdb341012b4effc4257f27b4403ab106..c981ee91e903b99e90754749a340e8d612e5b713 100644 --- a/src/EditorFeatures/TestUtilities/Traits.cs +++ b/src/EditorFeatures/TestUtilities/Traits.cs @@ -83,6 +83,7 @@ public static class Features public const string CodeActionsSpellcheck = "CodeActions.Spellcheck"; public const string CodeActionsSuppression = "CodeActions.Suppression"; public const string CodeActionsUseAutoProperty = "CodeActions.UseAutoProperty"; + public const string CodeActionsUseExpressionBody = "CodeActions.UseExpressionBody"; public const string CodeActionsUseImplicitType = "CodeActions.UseImplicitType"; public const string CodeActionsUseExplicitType = "CodeActions.UseExplicitType"; public const string CodeActionsUseFrameworkType = "CodeActions.UseFrameworkType"; diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests.vb b/src/EditorFeatures/VisualBasicTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests.vb index 08d93bd17f506d3d1bf6ded89d75e7d2928a05eb..13777f514f099bbd0c512e387250cf42c872f20b 100644 --- a/src/EditorFeatures/VisualBasicTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests.vb @@ -839,9 +839,10 @@ End Structure") Public Async Function TestAliasedType() As Task Dim source = - NewLines("Class Program \n Sub Foo() \n Dim x As New [|Global.Program|] \n End Sub \n End Class") - Await TestAsync(source, - NewLines("Class Program \n Sub Foo() \n Dim x As New Program \n End Sub \n End Class"), Nothing, 0) + NewLines("Class Program \n Sub Foo() \n Dim x As New [|Global.Program|] \n End Sub \n End Class") + Await TestAsync( + source, + NewLines("Class Program \n Sub Foo() \n Dim x As New Program \n End Sub \n End Class"), parseOptions:=Nothing, index:=0) Await TestMissingAsync(source, GetScriptOptions()) End Function @@ -1735,7 +1736,7 @@ NewLines("Class C \n Dim x = 7 \n Sub M() \n x = Nothing \n End Sub \n End Class Public Async Function TestAppropriateDiagnosticOnMissingQualifier() As Task Await TestDiagnosticSeverityAndCountAsync( "Class C : Property SomeProperty As Integer : Sub M() : [|Me|].SomeProperty = 1 : End Sub : End Class", - options:=OptionsSet(Tuple.Create(CodeStyleOptions.QualifyPropertyAccess, False, NotificationOption.Error)), + options:=OptionsSet(Tuple.Create(DirectCast(CodeStyleOptions.QualifyPropertyAccess, IOption), False, NotificationOption.Error)), diagnosticCount:=1, diagnosticId:=IDEDiagnosticIds.RemoveQualificationDiagnosticId, diagnosticSeverity:=DiagnosticSeverity.Error) diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.vb b/src/EditorFeatures/VisualBasicTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.vb index 18167d720cc4689069465f1b9db651bd968177e8..8fee539365ca897e67ddc37f833316d56248cd11 100644 --- a/src/EditorFeatures/VisualBasicTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Diagnostics/SimplifyTypeNames/SimplifyTypeNamesTests_FixAllTests.vb @@ -3,6 +3,7 @@ Option Strict Off Imports Microsoft.CodeAnalysis.CodeStyle Imports Microsoft.CodeAnalysis.Diagnostics +Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.SimplifyTypeNames @@ -789,8 +790,8 @@ End Class]]> .ToString() Dim options = OptionsSet( - Tuple.Create(CodeStyleOptions.QualifyPropertyAccess, False, NotificationOption.Suggestion), - Tuple.Create(CodeStyleOptions.QualifyFieldAccess, True, NotificationOption.Suggestion)) + Tuple.Create(DirectCast(CodeStyleOptions.QualifyPropertyAccess, IOption), False, NotificationOption.Suggestion), + Tuple.Create(DirectCast(CodeStyleOptions.QualifyFieldAccess, IOption), True, NotificationOption.Suggestion)) Await TestAsync( initialMarkup:=input, expectedMarkup:=expected, diff --git a/src/Features/CSharp/Portable/CSharpFeatures.csproj b/src/Features/CSharp/Portable/CSharpFeatures.csproj index db84243aec98009ebbe93eb784f9185a41c67f02..90cd2404424afd174073f23c54bfb0a8772c6781 100644 --- a/src/Features/CSharp/Portable/CSharpFeatures.csproj +++ b/src/Features/CSharp/Portable/CSharpFeatures.csproj @@ -58,6 +58,19 @@ InternalUtilities\LambdaUtilities.cs + + + + + + + + + + + + + @@ -362,6 +375,10 @@ + + + + diff --git a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.cs b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.cs index 1a6544c6f7a9670d71d4752e0c5de83dc49c6504..98582280b1947aac9dee302916ee2694c33ed756 100644 --- a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.cs +++ b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.cs @@ -631,18 +631,37 @@ protected override async Task CreateGeneratedCodeAsync(OperationS var root = newDocument.Root; var methodDefinition = root.GetAnnotatedNodes(this.MethodDefinitionAnnotation).First(); - var newMethodDefinition = - methodDefinition.ReplaceToken( - methodDefinition.Body.OpenBraceToken, - methodDefinition.Body.OpenBraceToken.WithAppendedTrailingTrivia( - SpecializedCollections.SingletonEnumerable(SyntaxFactory.CarriageReturnLineFeed))); + var newMethodDefinition = TweakNewLinesInMethod(methodDefinition); - newDocument = await newDocument.WithSyntaxRootAsync(root.ReplaceNode(methodDefinition, newMethodDefinition), cancellationToken).ConfigureAwait(false); + newDocument = await newDocument.WithSyntaxRootAsync( + root.ReplaceNode(methodDefinition, newMethodDefinition), cancellationToken).ConfigureAwait(false); } return await base.CreateGeneratedCodeAsync(status, newDocument, cancellationToken).ConfigureAwait(false); } + private static MethodDeclarationSyntax TweakNewLinesInMethod(MethodDeclarationSyntax methodDefinition) + { + if (methodDefinition.Body != null) + { + return methodDefinition.ReplaceToken( + methodDefinition.Body.OpenBraceToken, + methodDefinition.Body.OpenBraceToken.WithAppendedTrailingTrivia( + SpecializedCollections.SingletonEnumerable(SyntaxFactory.CarriageReturnLineFeed))); + } + else if (methodDefinition.ExpressionBody != null) + { + return methodDefinition.ReplaceToken( + methodDefinition.ExpressionBody.ArrowToken, + methodDefinition.ExpressionBody.ArrowToken.WithPrependedLeadingTrivia( + SpecializedCollections.SingletonEnumerable(SyntaxFactory.CarriageReturnLineFeed))); + } + else + { + return methodDefinition; + } + } + protected StatementSyntax GetStatementContainingInvocationToExtractedMethodWorker() { var callSignature = CreateCallSignature(); diff --git a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.TriviaResult.cs b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.TriviaResult.cs index 16ed0e0c3e4749a21b4dded18634d6e5ebed1277..303d8caabbfaf5d7a4f8f9cabe93d429a51fb902 100644 --- a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.TriviaResult.cs +++ b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.TriviaResult.cs @@ -72,9 +72,13 @@ protected override TriviaResolver GetTriviaResolver(SyntaxNode method) case TriviaLocation.AfterEndOfSpan: return callsite.GetLastToken(includeZeroWidth: true).GetNextToken(includeZeroWidth: true); case TriviaLocation.AfterBeginningOfSpan: - return method.Body.OpenBraceToken.GetNextToken(includeZeroWidth: true); + return method.Body != null + ? method.Body.OpenBraceToken.GetNextToken(includeZeroWidth: true) + : method.ExpressionBody.ArrowToken.GetNextToken(includeZeroWidth: true); case TriviaLocation.BeforeEndOfSpan: - return method.Body.CloseBraceToken.GetPreviousToken(includeZeroWidth: true); + return method.Body != null + ? method.Body.CloseBraceToken.GetPreviousToken(includeZeroWidth: true) + : method.SemicolonToken; } return Contract.FailWithReturn("can't happen"); @@ -91,12 +95,25 @@ protected override TriviaResolver GetTriviaResolver(SyntaxNode method) // but not others can be dealt with here. // method has no statement in them. so basically two trivia list now pointing to same thing. "{" and "}" - if (tokenPair.PreviousToken == method.Body.OpenBraceToken && - tokenPair.NextToken == method.Body.CloseBraceToken) + if (method.Body != null) { - return (location == TriviaLocation.AfterBeginningOfSpan) ? - SpecializedCollections.SingletonEnumerable(SyntaxFactory.ElasticMarker) : - SpecializedCollections.EmptyEnumerable(); + if (tokenPair.PreviousToken == method.Body.OpenBraceToken && + tokenPair.NextToken == method.Body.CloseBraceToken) + { + return (location == TriviaLocation.AfterBeginningOfSpan) + ? SpecializedCollections.SingletonEnumerable(SyntaxFactory.ElasticMarker) + : SpecializedCollections.EmptyEnumerable(); + } + } + else + { + if (tokenPair.PreviousToken == method.ExpressionBody.ArrowToken && + tokenPair.NextToken.GetPreviousToken() == method.SemicolonToken) + { + return (location == TriviaLocation.AfterBeginningOfSpan) + ? SpecializedCollections.SingletonEnumerable(SyntaxFactory.ElasticMarker) + : SpecializedCollections.EmptyEnumerable(); + } } var previousTriviaPair = triviaMap.ContainsKey(tokenPair.PreviousToken) ? triviaMap[tokenPair.PreviousToken] : default(LeadingTrailingTriviaPair); diff --git a/src/Features/CSharp/Portable/UseExpressionBody/AbstractUseExpressionBodyCodeFixProvider.FixAllProvider.cs b/src/Features/CSharp/Portable/UseExpressionBody/AbstractUseExpressionBodyCodeFixProvider.FixAllProvider.cs new file mode 100644 index 0000000000000000000000000000000000000000..8b4a38bd2951489e2a0e01300a4f9f2baa8b3a63 --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/AbstractUseExpressionBodyCodeFixProvider.FixAllProvider.cs @@ -0,0 +1,27 @@ +// 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.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeFixes.FixAllOccurrences; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + internal partial class AbstractUseExpressionBodyCodeFixProvider : CodeFixProvider + where TDeclaration : SyntaxNode + { + private class UseExpressionBodyFixAllProvider : DocumentBasedFixAllProvider + { + private readonly AbstractUseExpressionBodyCodeFixProvider _provider; + + public UseExpressionBodyFixAllProvider(AbstractUseExpressionBodyCodeFixProvider provider) + { + _provider = provider; + } + + protected override Task FixDocumentAsync(Document document, ImmutableArray diagnostics, CancellationToken cancellationToken) + => _provider.FixAllAsync(document, diagnostics, cancellationToken); + } + } +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/AbstractUseExpressionBodyCodeFixProvider.cs b/src/Features/CSharp/Portable/UseExpressionBody/AbstractUseExpressionBodyCodeFixProvider.cs new file mode 100644 index 0000000000000000000000000000000000000000..dac74745fa808a6e681f0f7384078479889b5173 --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/AbstractUseExpressionBodyCodeFixProvider.cs @@ -0,0 +1,201 @@ +// 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.Collections.Immutable; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Editing; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + internal abstract partial class AbstractUseExpressionBodyCodeFixProvider : CodeFixProvider + where TDeclaration : SyntaxNode + { + private readonly Option> _option; + private readonly string _useExpressionBodyTitle; + private readonly string _useBlockBodyTitle; + + public sealed override ImmutableArray FixableDiagnosticIds { get; } + + protected AbstractUseExpressionBodyCodeFixProvider( + string diagnosticId, + Option> option, + string useExpressionBodyTitle, + string useBlockBodyTitle) + { + FixableDiagnosticIds = ImmutableArray.Create(diagnosticId); + _option = option; + _useExpressionBodyTitle = useExpressionBodyTitle; + _useBlockBodyTitle = useBlockBodyTitle; + } + + public sealed override FixAllProvider GetFixAllProvider() => new UseExpressionBodyFixAllProvider(this); + + public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) + { + var diagnostic = context.Diagnostics.First(); + var option = context.Document.Project.Solution.Workspace.Options.GetOption(_option); + var title = option.Value + ? _useExpressionBodyTitle + : _useBlockBodyTitle; + + context.RegisterCodeFix( + new MyCodeAction(title, c => FixAsync(context.Document, diagnostic, c)), + diagnostic); + + return SpecializedTasks.EmptyTask; + } + + private Task FixAsync( + Document document, Diagnostic diagnostic, CancellationToken cancellationToken) + { + return FixAllAsync(document, ImmutableArray.Create(diagnostic), cancellationToken); + } + + private async Task FixAllAsync( + Document document, ImmutableArray diagnostics, CancellationToken cancellationToken) + { + var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + + var editor = new SyntaxEditor(root, document.Project.Solution.Workspace); + var options = document.Project.Solution.Workspace.Options; + var preferExpressionBody = document.Project.Solution.Workspace.Options.GetOption(_option).Value; + + foreach (var diagnostic in diagnostics) + { + cancellationToken.ThrowIfCancellationRequested(); + AddEdits(root, editor, diagnostic, options, preferExpressionBody, cancellationToken); + } + + var newRoot = editor.GetChangedRoot(); + return document.WithSyntaxRoot(newRoot); + } + + private void AddEdits( + SyntaxNode root, SyntaxEditor editor, Diagnostic diagnostic, + OptionSet options, bool preferExpressionBody, CancellationToken cancellationToken) + { + var declarationLocation = diagnostic.AdditionalLocations[0]; + var declaration = (TDeclaration)declarationLocation.FindNode(cancellationToken); + + var updatedDeclaration = this.Update(declaration, preferExpressionBody, options) + .WithAdditionalAnnotations(Formatter.Annotation); + + editor.ReplaceNode(declaration, updatedDeclaration); + } + + private TDeclaration Update(TDeclaration declaration, bool preferExpressionBody, OptionSet options) + { + if (preferExpressionBody) + { + return WithSemicolonToken( + WithExpressionBody( + WithBody(declaration, null), + GetBody(declaration).TryConvertToExpressionBody()), + GetFirstStatementSemicolon(GetBody(declaration))); + } + else + { + return WithSemicolonToken( + WithExpressionBody( + WithGenerateBody(declaration, options), + null), + default(SyntaxToken)); + } + } + + protected abstract bool CreateReturnStatementForExpression(TDeclaration declaration); + + protected abstract SyntaxToken GetSemicolonToken(TDeclaration declaration); + protected abstract ArrowExpressionClauseSyntax GetExpressionBody(TDeclaration declaration); + protected abstract BlockSyntax GetBody(TDeclaration declaration); + + protected abstract TDeclaration WithSemicolonToken(TDeclaration declaration, SyntaxToken token); + protected abstract TDeclaration WithExpressionBody(TDeclaration declaration, ArrowExpressionClauseSyntax expressionBody); + protected abstract TDeclaration WithBody(TDeclaration declaration, BlockSyntax body); + + protected virtual TDeclaration WithGenerateBody( + TDeclaration declaration, OptionSet options) + { + var expressionBody = GetExpressionBody(declaration); + var semicolonToken = GetSemicolonToken(declaration); + var block = expressionBody.ConvertToBlock( + GetSemicolonToken(declaration), + CreateReturnStatementForExpression(declaration)); + + return WithBody(declaration, block); + } + + private SyntaxToken GetFirstStatementSemicolon(BlockSyntax body) + { + var firstStatement = body.Statements[0]; + if (firstStatement.IsKind(SyntaxKind.ExpressionStatement)) + { + return ((ExpressionStatementSyntax)firstStatement).SemicolonToken; + } + else if (firstStatement.IsKind(SyntaxKind.ReturnStatement)) + { + return ((ReturnStatementSyntax)firstStatement).SemicolonToken; + } + else if (firstStatement.IsKind(SyntaxKind.ThrowStatement)) + { + return ((ThrowStatementSyntax)firstStatement).SemicolonToken; + } + else + { + return SyntaxFactory.Token(SyntaxKind.SemicolonToken); + } + } + + protected TDeclaration WithAccessorList( + TDeclaration declaration, OptionSet options) + { + var expressionBody = GetExpressionBody(declaration); + var semicolonToken = GetSemicolonToken(declaration); + + var preferExpressionBodiedAccessors = options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value; + + AccessorDeclarationSyntax accessor; + if (preferExpressionBodiedAccessors) + { + accessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) + .WithExpressionBody(expressionBody) + .WithSemicolonToken(semicolonToken); + } + else + { + var block = expressionBody.ConvertToBlock( + GetSemicolonToken(declaration), + CreateReturnStatementForExpression(declaration)); + accessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration, block); + } + + return WithAccessorList(declaration, SyntaxFactory.AccessorList( + SyntaxFactory.SingletonList(accessor))); + } + + protected virtual TDeclaration WithAccessorList(TDeclaration declaration, AccessorListSyntax accessorListSyntax) + { + throw new NotImplementedException(); + } + + private class MyCodeAction : CodeAction.DocumentChangeAction + { + public MyCodeAction(string title, Func> createChangedDocument) + : base(title, createChangedDocument) + { + } + } + } +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/AbstractUseExpressionBodyDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UseExpressionBody/AbstractUseExpressionBodyDiagnosticAnalyzer.cs new file mode 100644 index 0000000000000000000000000000000000000000..343967e974ca6d936dcb2c2e2b71aba6fc5409fd --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/AbstractUseExpressionBodyDiagnosticAnalyzer.cs @@ -0,0 +1,106 @@ +// 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 Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + internal abstract class AbstractUseExpressionBodyDiagnosticAnalyzer : + AbstractCodeStyleDiagnosticAnalyzer, IBuiltInAnalyzer + where TDeclaration : SyntaxNode + { + private readonly ImmutableArray _syntaxKinds; + private readonly Option> _option; + private readonly LocalizableString _expressionBodyTitle; + private readonly LocalizableString _blockBodyTitle; + + public bool OpenFileOnly(Workspace workspace) => true; + + protected AbstractUseExpressionBodyDiagnosticAnalyzer( + string diagnosticId, + LocalizableString expressionBodyTitle, + LocalizableString blockBodyTitle, + ImmutableArray syntaxKinds, + Option> option) + : base(diagnosticId, expressionBodyTitle) + { + _syntaxKinds = syntaxKinds; + _option = option; + _expressionBodyTitle = expressionBodyTitle; + _blockBodyTitle = blockBodyTitle; + } + + public DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticDocumentAnalysis; + + public override void Initialize(AnalysisContext context) + => context.RegisterSyntaxNodeAction(AnalyzeSyntax, _syntaxKinds); + + private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) + { + var diagnostic = AnalyzeSyntax(context.Options.GetOptionSet(), (TDeclaration)context.Node); + if (diagnostic != null) + { + context.ReportDiagnostic(diagnostic); + } + } + + internal virtual Diagnostic AnalyzeSyntax(OptionSet optionSet, TDeclaration declaration) + { + var preferExpressionBodiedOption = optionSet.GetOption(_option); + + var expressionBody = GetExpressionBody(declaration); + + if (preferExpressionBodiedOption.Value) + { + if (expressionBody == null) + { + // They want expression bodies and they don't have one. See if we can + // convert this to have an expression body. + expressionBody = GetBody(declaration).TryConvertToExpressionBody(); + if (expressionBody != null) + { + var additionalLocations = ImmutableArray.Create(declaration.GetLocation()); + return Diagnostic.Create( + CreateDescriptor(this.DescriptorId, _expressionBodyTitle, preferExpressionBodiedOption.Notification.Value), + GetBody(declaration).Statements[0].GetLocation(), + additionalLocations: additionalLocations); + } + } + } + else + { + // They don't want expression bodies but they have one. Offer to conver this to a normal block + if (expressionBody != null) + { + var additionalLocations = ImmutableArray.Create(declaration.GetLocation()); + return Diagnostic.Create( + CreateDescriptor(this.DescriptorId, _blockBodyTitle, preferExpressionBodiedOption.Notification.Value), + expressionBody.GetLocation(), + additionalLocations: additionalLocations); + } + } + + return null; + } + + protected static BlockSyntax GetBodyFromSingleGetAccessor(AccessorListSyntax accessorList) + { + if (accessorList != null && + accessorList.Accessors.Count == 1 && + accessorList.Accessors[0].AttributeLists.Count == 0 && + accessorList.Accessors[0].IsKind(SyntaxKind.GetAccessorDeclaration)) + { + return accessorList.Accessors[0].Body; + } + + return null; + } + + protected abstract BlockSyntax GetBody(TDeclaration declaration); + protected abstract ArrowExpressionClauseSyntax GetExpressionBody(TDeclaration declaration); + } +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/Accessors/UseExpressionBodyForAccessorsCodeFixProvider.cs b/src/Features/CSharp/Portable/UseExpressionBody/Accessors/UseExpressionBodyForAccessorsCodeFixProvider.cs new file mode 100644 index 0000000000000000000000000000000000000000..773fe62a663dd707b5cd2cc37d4c7321b1f27a2e --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/Accessors/UseExpressionBodyForAccessorsCodeFixProvider.cs @@ -0,0 +1,43 @@ +// 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.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + [ExportCodeFixProvider(LanguageNames.CSharp), Shared] + internal class UseExpressionBodyForAccessorsCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider + { + public UseExpressionBodyForAccessorsCodeFixProvider() + : base(IDEDiagnosticIds.UseExpressionBodyForAccessorsDiagnosticId, + CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, + FeaturesResources.Use_expression_body_for_accessors, + FeaturesResources.Use_block_body_for_accessors) + { + } + + protected override SyntaxToken GetSemicolonToken(AccessorDeclarationSyntax declaration) + => declaration.SemicolonToken; + + protected override ArrowExpressionClauseSyntax GetExpressionBody(AccessorDeclarationSyntax declaration) + => declaration.ExpressionBody; + + protected override BlockSyntax GetBody(AccessorDeclarationSyntax declaration) + => declaration.Body; + + protected override AccessorDeclarationSyntax WithSemicolonToken(AccessorDeclarationSyntax declaration, SyntaxToken token) + => declaration.WithSemicolonToken(token); + + protected override AccessorDeclarationSyntax WithExpressionBody(AccessorDeclarationSyntax declaration, ArrowExpressionClauseSyntax expressionBody) + => declaration.WithExpressionBody(expressionBody); + + protected override AccessorDeclarationSyntax WithBody(AccessorDeclarationSyntax declaration, BlockSyntax body) + => declaration.WithBody(body); + + protected override bool CreateReturnStatementForExpression(AccessorDeclarationSyntax declaration) + => declaration.IsKind(SyntaxKind.GetAccessorDeclaration); + } +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/Accessors/UseExpressionBodyForAccessorsDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UseExpressionBody/Accessors/UseExpressionBodyForAccessorsDiagnosticAnalyzer.cs new file mode 100644 index 0000000000000000000000000000000000000000..100849bb1832a4768379d630de88ade98ae44d02 --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/Accessors/UseExpressionBodyForAccessorsDiagnosticAnalyzer.cs @@ -0,0 +1,61 @@ +// 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 Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + internal class UseExpressionBodyForAccessorsDiagnosticAnalyzer : + AbstractUseExpressionBodyDiagnosticAnalyzer, IBuiltInAnalyzer + { + private readonly UseExpressionBodyForPropertiesDiagnosticAnalyzer propertyAnalyzer = new UseExpressionBodyForPropertiesDiagnosticAnalyzer(); + private readonly UseExpressionBodyForIndexersDiagnosticAnalyzer indexerAnalyzer = new UseExpressionBodyForIndexersDiagnosticAnalyzer(); + + public UseExpressionBodyForAccessorsDiagnosticAnalyzer() + : base(IDEDiagnosticIds.UseExpressionBodyForAccessorsDiagnosticId, + new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_accessors), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_accessors), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + ImmutableArray.Create(SyntaxKind.GetAccessorDeclaration, SyntaxKind.SetAccessorDeclaration), + CSharpCodeStyleOptions.PreferExpressionBodiedAccessors) + { + } + + protected override BlockSyntax GetBody(AccessorDeclarationSyntax declaration) + => declaration.Body; + + protected override ArrowExpressionClauseSyntax GetExpressionBody(AccessorDeclarationSyntax declaration) + => declaration.ExpressionBody; + + internal override Diagnostic AnalyzeSyntax(OptionSet optionSet, AccessorDeclarationSyntax accessor) + { + // We don't want to double report. So don't report a diagnostic if the property/indexer + // analyzer is going to report a diagnostic here. + var grandParent = accessor.Parent.Parent; + + if (grandParent.IsKind(SyntaxKind.PropertyDeclaration)) + { + var propertyDeclaration = (PropertyDeclarationSyntax)grandParent; + var diagnostic = propertyAnalyzer.AnalyzeSyntax(optionSet, propertyDeclaration); + if (diagnostic != null) + { + return null; + } + } + else if (grandParent.IsKind(SyntaxKind.IndexerDeclaration)) + { + var indexerDeclaration = (IndexerDeclarationSyntax)grandParent; + var diagnostic = indexerAnalyzer.AnalyzeSyntax(optionSet, indexerDeclaration); + if (diagnostic != null) + { + return null; + } + } + + return base.AnalyzeSyntax(optionSet, accessor); + } + } +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/Constructors/UseExpressionBodyForConstructorsCodeFixProvider.cs b/src/Features/CSharp/Portable/UseExpressionBody/Constructors/UseExpressionBodyForConstructorsCodeFixProvider.cs new file mode 100644 index 0000000000000000000000000000000000000000..e6a68134537c83135231794889fc7965ff15aac7 --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/Constructors/UseExpressionBodyForConstructorsCodeFixProvider.cs @@ -0,0 +1,42 @@ +// 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.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + [ExportCodeFixProvider(LanguageNames.CSharp), Shared] + internal class UseExpressionBodyForConstructorsCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider + { + public UseExpressionBodyForConstructorsCodeFixProvider() + : base(IDEDiagnosticIds.UseExpressionBodyForConstructorsDiagnosticId, + CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, + FeaturesResources.Use_expression_body_for_constructors, + FeaturesResources.Use_block_body_for_constructors) + { + } + + protected override SyntaxToken GetSemicolonToken(ConstructorDeclarationSyntax declaration) + => declaration.SemicolonToken; + + protected override ArrowExpressionClauseSyntax GetExpressionBody(ConstructorDeclarationSyntax declaration) + => declaration.ExpressionBody; + + protected override BlockSyntax GetBody(ConstructorDeclarationSyntax declaration) + => declaration.Body; + + protected override ConstructorDeclarationSyntax WithSemicolonToken(ConstructorDeclarationSyntax declaration, SyntaxToken token) + => declaration.WithSemicolonToken(token); + + protected override ConstructorDeclarationSyntax WithExpressionBody(ConstructorDeclarationSyntax declaration, ArrowExpressionClauseSyntax expressionBody) + => declaration.WithExpressionBody(expressionBody); + + protected override ConstructorDeclarationSyntax WithBody(ConstructorDeclarationSyntax declaration, BlockSyntax body) + => declaration.WithBody(body); + + protected override bool CreateReturnStatementForExpression(ConstructorDeclarationSyntax declaration) => false; + } +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/Constructors/UseExpressionBodyForConstructorsDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UseExpressionBody/Constructors/UseExpressionBodyForConstructorsDiagnosticAnalyzer.cs new file mode 100644 index 0000000000000000000000000000000000000000..2e3ef9fe685385e586d058ddc8addba19d754a11 --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/Constructors/UseExpressionBodyForConstructorsDiagnosticAnalyzer.cs @@ -0,0 +1,29 @@ +// 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 Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + internal class UseExpressionBodyForConstructorsDiagnosticAnalyzer : + AbstractUseExpressionBodyDiagnosticAnalyzer, IBuiltInAnalyzer + { + public UseExpressionBodyForConstructorsDiagnosticAnalyzer() + : base(IDEDiagnosticIds.UseExpressionBodyForConstructorsDiagnosticId, + new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_constructors), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_constructors), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + ImmutableArray.Create(SyntaxKind.ConstructorDeclaration), + CSharpCodeStyleOptions.PreferExpressionBodiedConstructors) + { + } + + protected override BlockSyntax GetBody(ConstructorDeclarationSyntax declaration) + => declaration.Body; + + protected override ArrowExpressionClauseSyntax GetExpressionBody(ConstructorDeclarationSyntax declaration) + => declaration.ExpressionBody; + } +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/Indexers/UseExpressionBodyForIndexersCodeFixProvider.cs b/src/Features/CSharp/Portable/UseExpressionBody/Indexers/UseExpressionBodyForIndexersCodeFixProvider.cs new file mode 100644 index 0000000000000000000000000000000000000000..12ffa0f1002952e323126d8552d93ee11f54fb02 --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/Indexers/UseExpressionBodyForIndexersCodeFixProvider.cs @@ -0,0 +1,60 @@ +// 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.Composition; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + [ExportCodeFixProvider(LanguageNames.CSharp), Shared] + internal class UseExpressionBodyForIndexersCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider + { + public UseExpressionBodyForIndexersCodeFixProvider() + : base(IDEDiagnosticIds.UseExpressionBodyForIndexersDiagnosticId, + CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, + FeaturesResources.Use_expression_body_for_indexers, + FeaturesResources.Use_block_body_for_indexers) + { + } + + protected override SyntaxToken GetSemicolonToken(IndexerDeclarationSyntax declaration) + => declaration.SemicolonToken; + + protected override ArrowExpressionClauseSyntax GetExpressionBody(IndexerDeclarationSyntax declaration) + => declaration.ExpressionBody; + + protected override BlockSyntax GetBody(IndexerDeclarationSyntax declaration) + => declaration.AccessorList.Accessors[0].Body; + + protected override IndexerDeclarationSyntax WithSemicolonToken(IndexerDeclarationSyntax declaration, SyntaxToken token) + => declaration.WithSemicolonToken(token); + + protected override IndexerDeclarationSyntax WithExpressionBody(IndexerDeclarationSyntax declaration, ArrowExpressionClauseSyntax expressionBody) + => declaration.WithExpressionBody(expressionBody); + + protected override IndexerDeclarationSyntax WithAccessorList(IndexerDeclarationSyntax declaration, AccessorListSyntax accessorList) + => declaration.WithAccessorList(accessorList); + + protected override IndexerDeclarationSyntax WithBody(IndexerDeclarationSyntax declaration, BlockSyntax body) + { + if (body == null) + { + return declaration.WithAccessorList(null); + } + + throw new InvalidOperationException(); + } + + protected override IndexerDeclarationSyntax WithGenerateBody( + IndexerDeclarationSyntax declaration, OptionSet options) + { + return WithAccessorList(declaration, options); + } + + protected override bool CreateReturnStatementForExpression(IndexerDeclarationSyntax declaration) => true; + } +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/Indexers/UseExpressionBodyForIndexersDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UseExpressionBody/Indexers/UseExpressionBodyForIndexersDiagnosticAnalyzer.cs new file mode 100644 index 0000000000000000000000000000000000000000..5111710a8a56d06a3c996fb520f06ab6167859e6 --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/Indexers/UseExpressionBodyForIndexersDiagnosticAnalyzer.cs @@ -0,0 +1,29 @@ +// 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 Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + internal class UseExpressionBodyForIndexersDiagnosticAnalyzer : + AbstractUseExpressionBodyDiagnosticAnalyzer, IBuiltInAnalyzer + { + public UseExpressionBodyForIndexersDiagnosticAnalyzer() + : base(IDEDiagnosticIds.UseExpressionBodyForIndexersDiagnosticId, + new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_indexers), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_indexers), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + ImmutableArray.Create(SyntaxKind.IndexerDeclaration), + CSharpCodeStyleOptions.PreferExpressionBodiedIndexers) + { + } + + protected override BlockSyntax GetBody(IndexerDeclarationSyntax declaration) + => GetBodyFromSingleGetAccessor(declaration.AccessorList); + + protected override ArrowExpressionClauseSyntax GetExpressionBody(IndexerDeclarationSyntax declaration) + => declaration.ExpressionBody; + } +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/Methods/UseExpressionBodyForMethodsCodeFixProvider.cs b/src/Features/CSharp/Portable/UseExpressionBody/Methods/UseExpressionBodyForMethodsCodeFixProvider.cs new file mode 100644 index 0000000000000000000000000000000000000000..34383d537ce6ddf9c65637024ad02fb3f6b1b27a --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/Methods/UseExpressionBodyForMethodsCodeFixProvider.cs @@ -0,0 +1,45 @@ +// 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.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + [ExportCodeFixProvider(LanguageNames.CSharp), Shared] + internal class UseExpressionBodyForMethodsCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider + { + public UseExpressionBodyForMethodsCodeFixProvider() + : base(IDEDiagnosticIds.UseExpressionBodyForMethodsDiagnosticId, + CSharpCodeStyleOptions.PreferExpressionBodiedMethods, + FeaturesResources.Use_expression_body_for_methods, + FeaturesResources.Use_block_body_for_methods) + { + } + + protected override SyntaxToken GetSemicolonToken(MethodDeclarationSyntax declaration) + => declaration.SemicolonToken; + + protected override ArrowExpressionClauseSyntax GetExpressionBody(MethodDeclarationSyntax declaration) + => declaration.ExpressionBody; + + protected override BlockSyntax GetBody(MethodDeclarationSyntax declaration) + => declaration.Body; + + protected override MethodDeclarationSyntax WithSemicolonToken(MethodDeclarationSyntax declaration, SyntaxToken token) + => declaration.WithSemicolonToken(token); + + protected override MethodDeclarationSyntax WithExpressionBody(MethodDeclarationSyntax declaration, ArrowExpressionClauseSyntax expressionBody) + => declaration.WithExpressionBody(expressionBody); + + protected override MethodDeclarationSyntax WithBody(MethodDeclarationSyntax declaration, BlockSyntax body) + => declaration.WithBody(body); + + protected override bool CreateReturnStatementForExpression(MethodDeclarationSyntax declaration) + => !declaration.ReturnType.IsVoid(); + } + +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/Methods/UseExpressionBodyForMethodsDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UseExpressionBody/Methods/UseExpressionBodyForMethodsDiagnosticAnalyzer.cs new file mode 100644 index 0000000000000000000000000000000000000000..169b5b021d7850582e034ee0cf837b712c269335 --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/Methods/UseExpressionBodyForMethodsDiagnosticAnalyzer.cs @@ -0,0 +1,29 @@ +// 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 Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + internal class UseExpressionBodyForMethodsDiagnosticAnalyzer : + AbstractUseExpressionBodyDiagnosticAnalyzer, IBuiltInAnalyzer + { + public UseExpressionBodyForMethodsDiagnosticAnalyzer() + : base(IDEDiagnosticIds.UseExpressionBodyForMethodsDiagnosticId, + new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_methods), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_methods), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + ImmutableArray.Create(SyntaxKind.MethodDeclaration), + CSharpCodeStyleOptions.PreferExpressionBodiedMethods) + { + } + + protected override BlockSyntax GetBody(MethodDeclarationSyntax declaration) + => declaration.Body; + + protected override ArrowExpressionClauseSyntax GetExpressionBody(MethodDeclarationSyntax declaration) + => declaration.ExpressionBody; + } +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/Operators/UseExpressionBodyForConversionOperatorsCodeFixProvider.cs b/src/Features/CSharp/Portable/UseExpressionBody/Operators/UseExpressionBodyForConversionOperatorsCodeFixProvider.cs new file mode 100644 index 0000000000000000000000000000000000000000..5ce5e92d575c600aca7a8f77f256dff5abbc8cc9 --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/Operators/UseExpressionBodyForConversionOperatorsCodeFixProvider.cs @@ -0,0 +1,44 @@ +// 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.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + [ExportCodeFixProvider(LanguageNames.CSharp), Shared] + internal class UseExpressionBodyForConversionOperatorsCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider + { + public UseExpressionBodyForConversionOperatorsCodeFixProvider() + : base(IDEDiagnosticIds.UseExpressionBodyForConversionOperatorsDiagnosticId, + CSharpCodeStyleOptions.PreferExpressionBodiedOperators, + FeaturesResources.Use_expression_body_for_operators, + FeaturesResources.Use_block_body_for_operators) + { + } + + protected override SyntaxToken GetSemicolonToken(ConversionOperatorDeclarationSyntax declaration) + => declaration.SemicolonToken; + + protected override ArrowExpressionClauseSyntax GetExpressionBody(ConversionOperatorDeclarationSyntax declaration) + => declaration.ExpressionBody; + + protected override BlockSyntax GetBody(ConversionOperatorDeclarationSyntax declaration) + => declaration.Body; + + protected override ConversionOperatorDeclarationSyntax WithSemicolonToken(ConversionOperatorDeclarationSyntax declaration, SyntaxToken token) + => declaration.WithSemicolonToken(token); + + protected override ConversionOperatorDeclarationSyntax WithExpressionBody(ConversionOperatorDeclarationSyntax declaration, ArrowExpressionClauseSyntax expressionBody) + => declaration.WithExpressionBody(expressionBody); + + protected override ConversionOperatorDeclarationSyntax WithBody(ConversionOperatorDeclarationSyntax declaration, BlockSyntax body) + => declaration.WithBody(body); + + protected override bool CreateReturnStatementForExpression(ConversionOperatorDeclarationSyntax declaration) + => true; + } + +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/Operators/UseExpressionBodyForConversionOperatorsDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UseExpressionBody/Operators/UseExpressionBodyForConversionOperatorsDiagnosticAnalyzer.cs new file mode 100644 index 0000000000000000000000000000000000000000..2d92b383ad4ea89a0d5aca7355f9b1e5a3921d85 --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/Operators/UseExpressionBodyForConversionOperatorsDiagnosticAnalyzer.cs @@ -0,0 +1,29 @@ +// 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 Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + internal class UseExpressionBodyForConversionOperatorsDiagnosticAnalyzer : + AbstractUseExpressionBodyDiagnosticAnalyzer, IBuiltInAnalyzer + { + public UseExpressionBodyForConversionOperatorsDiagnosticAnalyzer() + : base(IDEDiagnosticIds.UseExpressionBodyForConversionOperatorsDiagnosticId, + new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_operators), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_operators), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + ImmutableArray.Create(SyntaxKind.ConversionOperatorDeclaration), + CSharpCodeStyleOptions.PreferExpressionBodiedOperators) + { + } + + protected override BlockSyntax GetBody(ConversionOperatorDeclarationSyntax declaration) + => declaration.Body; + + protected override ArrowExpressionClauseSyntax GetExpressionBody(ConversionOperatorDeclarationSyntax declaration) + => declaration.ExpressionBody; + } +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/Operators/UseExpressionBodyForOperatorsCodeFixProvider.cs b/src/Features/CSharp/Portable/UseExpressionBody/Operators/UseExpressionBodyForOperatorsCodeFixProvider.cs new file mode 100644 index 0000000000000000000000000000000000000000..752365bcda82c1d8b659322cd09185b9260692ea --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/Operators/UseExpressionBodyForOperatorsCodeFixProvider.cs @@ -0,0 +1,44 @@ +// 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.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + [ExportCodeFixProvider(LanguageNames.CSharp), Shared] + internal class UseExpressionBodyForOperatorsCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider + { + public UseExpressionBodyForOperatorsCodeFixProvider() + : base(IDEDiagnosticIds.UseExpressionBodyForOperatorsDiagnosticId, + CSharpCodeStyleOptions.PreferExpressionBodiedOperators, + FeaturesResources.Use_expression_body_for_operators, + FeaturesResources.Use_block_body_for_operators) + { + } + + protected override SyntaxToken GetSemicolonToken(OperatorDeclarationSyntax declaration) + => declaration.SemicolonToken; + + protected override ArrowExpressionClauseSyntax GetExpressionBody(OperatorDeclarationSyntax declaration) + => declaration.ExpressionBody; + + protected override BlockSyntax GetBody(OperatorDeclarationSyntax declaration) + => declaration.Body; + + protected override OperatorDeclarationSyntax WithSemicolonToken(OperatorDeclarationSyntax declaration, SyntaxToken token) + => declaration.WithSemicolonToken(token); + + protected override OperatorDeclarationSyntax WithExpressionBody(OperatorDeclarationSyntax declaration, ArrowExpressionClauseSyntax expressionBody) + => declaration.WithExpressionBody(expressionBody); + + protected override OperatorDeclarationSyntax WithBody(OperatorDeclarationSyntax declaration, BlockSyntax body) + => declaration.WithBody(body); + + protected override bool CreateReturnStatementForExpression(OperatorDeclarationSyntax declaration) + => true; + } + +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/Operators/UseExpressionBodyForOperatorsDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UseExpressionBody/Operators/UseExpressionBodyForOperatorsDiagnosticAnalyzer.cs new file mode 100644 index 0000000000000000000000000000000000000000..992cc4a2b7e70215455ac9db020f0afc6310046c --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/Operators/UseExpressionBodyForOperatorsDiagnosticAnalyzer.cs @@ -0,0 +1,29 @@ +// 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 Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + internal class UseExpressionBodyForOperatorsDiagnosticAnalyzer : + AbstractUseExpressionBodyDiagnosticAnalyzer, IBuiltInAnalyzer + { + public UseExpressionBodyForOperatorsDiagnosticAnalyzer() + : base(IDEDiagnosticIds.UseExpressionBodyForOperatorsDiagnosticId, + new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_operators), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_operators), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + ImmutableArray.Create(SyntaxKind.OperatorDeclaration), + CSharpCodeStyleOptions.PreferExpressionBodiedOperators) + { + } + + protected override BlockSyntax GetBody(OperatorDeclarationSyntax declaration) + => declaration.Body; + + protected override ArrowExpressionClauseSyntax GetExpressionBody(OperatorDeclarationSyntax declaration) + => declaration.ExpressionBody; + } +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/Properties/UseExpressionBodyForPropertiesCodeFixProvider.cs b/src/Features/CSharp/Portable/UseExpressionBody/Properties/UseExpressionBodyForPropertiesCodeFixProvider.cs new file mode 100644 index 0000000000000000000000000000000000000000..71b3de3a8078ec542dc19df4a1f6a528767d3f04 --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/Properties/UseExpressionBodyForPropertiesCodeFixProvider.cs @@ -0,0 +1,62 @@ +// 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.Composition; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + + [ExportCodeFixProvider(LanguageNames.CSharp), Shared] + internal class UseExpressionBodyForPropertiesCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider + { + public UseExpressionBodyForPropertiesCodeFixProvider() + : base(IDEDiagnosticIds.UseExpressionBodyForPropertiesDiagnosticId, + CSharpCodeStyleOptions.PreferExpressionBodiedProperties, + FeaturesResources.Use_expression_body_for_properties, + FeaturesResources.Use_block_body_for_properties) + { + } + + protected override SyntaxToken GetSemicolonToken(PropertyDeclarationSyntax declaration) + => declaration.SemicolonToken; + + protected override ArrowExpressionClauseSyntax GetExpressionBody(PropertyDeclarationSyntax declaration) + => declaration.ExpressionBody; + + protected override BlockSyntax GetBody(PropertyDeclarationSyntax declaration) + => declaration.AccessorList.Accessors[0].Body; + + protected override PropertyDeclarationSyntax WithSemicolonToken(PropertyDeclarationSyntax declaration, SyntaxToken token) + => declaration.WithSemicolonToken(token); + + protected override PropertyDeclarationSyntax WithExpressionBody(PropertyDeclarationSyntax declaration, ArrowExpressionClauseSyntax expressionBody) + => declaration.WithExpressionBody(expressionBody); + + protected override PropertyDeclarationSyntax WithAccessorList(PropertyDeclarationSyntax declaration, AccessorListSyntax accessorListSyntax) + => declaration.WithAccessorList(accessorListSyntax); + + protected override PropertyDeclarationSyntax WithBody(PropertyDeclarationSyntax declaration, BlockSyntax body) + { + if (body == null) + { + return declaration.WithAccessorList(null); + } + + throw new InvalidOperationException(); + } + + protected override PropertyDeclarationSyntax WithGenerateBody( + PropertyDeclarationSyntax declaration, OptionSet options) + { + return WithAccessorList(declaration, options); + } + + protected override bool CreateReturnStatementForExpression(PropertyDeclarationSyntax declaration) => true; + } +} \ No newline at end of file diff --git a/src/Features/CSharp/Portable/UseExpressionBody/Properties/UseExpressionBodyForPropertiesDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UseExpressionBody/Properties/UseExpressionBodyForPropertiesDiagnosticAnalyzer.cs new file mode 100644 index 0000000000000000000000000000000000000000..3cccfcf2eb7334f43917fd3715dbf26aabc77b04 --- /dev/null +++ b/src/Features/CSharp/Portable/UseExpressionBody/Properties/UseExpressionBodyForPropertiesDiagnosticAnalyzer.cs @@ -0,0 +1,29 @@ +// 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 Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + internal class UseExpressionBodyForPropertiesDiagnosticAnalyzer : + AbstractUseExpressionBodyDiagnosticAnalyzer, IBuiltInAnalyzer + { + public UseExpressionBodyForPropertiesDiagnosticAnalyzer() + : base(IDEDiagnosticIds.UseExpressionBodyForPropertiesDiagnosticId, + new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_properties), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_properties), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + ImmutableArray.Create(SyntaxKind.PropertyDeclaration), + CSharpCodeStyleOptions.PreferExpressionBodiedProperties) + { + } + + protected override BlockSyntax GetBody(PropertyDeclarationSyntax declaration) + => GetBodyFromSingleGetAccessor(declaration.AccessorList); + + protected override ArrowExpressionClauseSyntax GetExpressionBody(PropertyDeclarationSyntax declaration) + => declaration.ExpressionBody; + } +} \ No newline at end of file diff --git a/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleDiagnosticAnalyzer.cs b/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleDiagnosticAnalyzer.cs index ea0cd34c6116c417effc1e8979b6cd751f72c382..6b0d47b85635a45a16bca4939522c37a460e2191 100644 --- a/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleDiagnosticAnalyzer.cs @@ -52,10 +52,16 @@ internal abstract class AbstractCodeStyleDiagnosticAnalyzer : DiagnosticAnalyzer public override ImmutableArray SupportedDiagnostics { get; } protected DiagnosticDescriptor CreateDescriptor(string id, DiagnosticSeverity severity, params string[] customTags) + => CreateDescriptor(id, _localizableTitle, severity, customTags); + + protected DiagnosticDescriptor CreateDescriptor(string id, LocalizableString title, DiagnosticSeverity severity, params string[] customTags) + => CreateDescriptor(id, title, title, severity, customTags); + + protected DiagnosticDescriptor CreateDescriptor(string id, LocalizableString title, LocalizableString message, DiagnosticSeverity severity, params string[] customTags) => new DiagnosticDescriptor( id, - _localizableTitle, - _localizableMessage, + title, + message, DiagnosticCategory.Style, severity, isEnabledByDefault: true, diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/IDEDiagnosticIds.cs b/src/Features/Core/Portable/Diagnostics/Analyzers/IDEDiagnosticIds.cs index f0e2bca2c4b8ffa54c27a173d689f8dc57e4286b..7ffe7824f2c19ccd6cdaa483a1eb84a9a3a7ab85 100644 --- a/src/Features/Core/Portable/Diagnostics/Analyzers/IDEDiagnosticIds.cs +++ b/src/Features/Core/Portable/Diagnostics/Analyzers/IDEDiagnosticIds.cs @@ -23,6 +23,14 @@ internal static class IDEDiagnosticIds public const string UseObjectInitializerDiagnosticId = "IDE0017"; public const string InlineDeclarationDiagnosticId = "IDE0018"; + public const string UseExpressionBodyForConstructorsDiagnosticId = "IDE0020"; + public const string UseExpressionBodyForMethodsDiagnosticId = "IDE0021"; + public const string UseExpressionBodyForConversionOperatorsDiagnosticId = "IDE0022"; + public const string UseExpressionBodyForOperatorsDiagnosticId = "IDE0023"; + public const string UseExpressionBodyForPropertiesDiagnosticId = "IDE0024"; + public const string UseExpressionBodyForIndexersDiagnosticId = "IDE0025"; + public const string UseExpressionBodyForAccessorsDiagnosticId = "IDE0026"; + // Analyzer error Ids public const string AnalyzerChangedId = "IDE1001"; public const string AnalyzerDependencyConflictId = "IDE1002"; diff --git a/src/Features/Core/Portable/Features.csproj b/src/Features/Core/Portable/Features.csproj index 864f91ba3aaeadae80c52e601568bbddabd90d45..dbdc1c1d92d480bf447da84aaeef93c2a7495b9c 100644 --- a/src/Features/Core/Portable/Features.csproj +++ b/src/Features/Core/Portable/Features.csproj @@ -94,6 +94,11 @@ Shared\Utilities\DesktopShim.cs + + True + True + FeaturesResources.resx + @@ -372,11 +377,6 @@ - - True - True - FeaturesResources.resx - diff --git a/src/Features/Core/Portable/FeaturesResources.Designer.cs b/src/Features/Core/Portable/FeaturesResources.Designer.cs index 830e36c7f18e4bc161db6cb57652db21de243e82..b50c10781bc37ee830f27292ac679cca3b2b257e 100644 --- a/src/Features/Core/Portable/FeaturesResources.Designer.cs +++ b/src/Features/Core/Portable/FeaturesResources.Designer.cs @@ -2920,6 +2920,114 @@ internal class FeaturesResources { } } + /// + /// Looks up a localized string similar to Use block body for accessors. + /// + internal static string Use_block_body_for_accessors { + get { + return ResourceManager.GetString("Use_block_body_for_accessors", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use block body for constructors. + /// + internal static string Use_block_body_for_constructors { + get { + return ResourceManager.GetString("Use_block_body_for_constructors", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use block body for indexers. + /// + internal static string Use_block_body_for_indexers { + get { + return ResourceManager.GetString("Use_block_body_for_indexers", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use block body for methods. + /// + internal static string Use_block_body_for_methods { + get { + return ResourceManager.GetString("Use_block_body_for_methods", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use block body for operators. + /// + internal static string Use_block_body_for_operators { + get { + return ResourceManager.GetString("Use_block_body_for_operators", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use block body for properties. + /// + internal static string Use_block_body_for_properties { + get { + return ResourceManager.GetString("Use_block_body_for_properties", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use expression body for accessors. + /// + internal static string Use_expression_body_for_accessors { + get { + return ResourceManager.GetString("Use_expression_body_for_accessors", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use expression body for constructors. + /// + internal static string Use_expression_body_for_constructors { + get { + return ResourceManager.GetString("Use_expression_body_for_constructors", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use expression body for indexers. + /// + internal static string Use_expression_body_for_indexers { + get { + return ResourceManager.GetString("Use_expression_body_for_indexers", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use expression body for methods. + /// + internal static string Use_expression_body_for_methods { + get { + return ResourceManager.GetString("Use_expression_body_for_methods", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use expression body for operators. + /// + internal static string Use_expression_body_for_operators { + get { + return ResourceManager.GetString("Use_expression_body_for_operators", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use expression body for properties. + /// + internal static string Use_expression_body_for_properties { + get { + return ResourceManager.GetString("Use_expression_body_for_properties", resourceCulture); + } + } + /// /// Looks up a localized string similar to Use framework type. /// diff --git a/src/Features/Core/Portable/FeaturesResources.resx b/src/Features/Core/Portable/FeaturesResources.resx index 952e65e26604903b3154f38f2a37654e28f5baa5..e355226ed928f6f84aa439ce14e92880ecfa45b4 100644 --- a/src/Features/Core/Portable/FeaturesResources.resx +++ b/src/Features/Core/Portable/FeaturesResources.resx @@ -1082,6 +1082,42 @@ This version used in: {2} Inline variable declaration + + Use expression body for methods + + + Use block body for methods + + + Use block body for accessors + + + Use block body for constructors + + + Use block body for indexers + + + Use block body for operators + + + Use block body for properties + + + Use expression body for accessors + + + Use expression body for constructors + + + Use expression body for indexers + + + Use expression body for operators + + + Use expression body for properties + Spell check '{0}' diff --git a/src/VisualStudio/CSharp/Impl/CSharpVSResources.Designer.cs b/src/VisualStudio/CSharp/Impl/CSharpVSResources.Designer.cs index 87b707c419b3b20e713952e8b1439ae14aab9367..fc6ab45302e7bf556fc95547b06cde48d3ba8124 100644 --- a/src/VisualStudio/CSharp/Impl/CSharpVSResources.Designer.cs +++ b/src/VisualStudio/CSharp/Impl/CSharpVSResources.Designer.cs @@ -861,6 +861,15 @@ internal class CSharpVSResources { } } + /// + /// Looks up a localized string similar to Prefer block body. + /// + internal static string Prefer_block_body { + get { + return ResourceManager.GetString("Prefer_block_body", resourceCulture); + } + } + /// /// Looks up a localized string similar to Prefer conditional delegate call. /// @@ -879,6 +888,15 @@ internal class CSharpVSResources { } } + /// + /// Looks up a localized string similar to Prefer expression body. + /// + internal static string Prefer_expression_body { + get { + return ResourceManager.GetString("Prefer_expression_body", resourceCulture); + } + } + /// /// Looks up a localized string similar to Prefer 'this.'. /// diff --git a/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx b/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx index a3b8dbaa9eeae8f66a469732cd27ead5c9b0b670..2e645d7e0709c7974a396f51e36b19f59f43efe0 100644 --- a/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx +++ b/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx @@ -489,4 +489,10 @@ Prefer conditional delegate call + + Prefer block body + + + Prefer expression body + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs b/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs index 60983ee4ed0326d71bb66b6bffc9240ff6df2983..f29e089f7b152cdb91515253f87cdd9ef5664d01 100644 --- a/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs +++ b/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs @@ -319,6 +319,170 @@ public Customer(string value) //] } } +"; + + private static readonly string s_preferExpressionBodyForMethods = @" +using System; + +//[ +class Customer +{ + private int Age; + + public int GetAge() => this.Age; +} +//] +"; + + private static readonly string s_preferBlockBodyForMethods = @" +using System; + +//[ +class Customer +{ + private int Age; + + public int GetAge() + { + return this.Age; + } +} +//] +"; + + private static readonly string s_preferExpressionBodyForConstructors = @" +using System; + +//[ +class Customer +{ + private int Age; + + public Customer(int age) => Age = age; +} +//] +"; + + private static readonly string s_preferBlockBodyForConstructors = @" +using System; + +//[ +class Customer +{ + private int Age; + + public Customer(int age) + { + Age = age; + } +} +//] +"; + + private static readonly string s_preferExpressionBodyForOperators = @" +using System; + +struct ComplexNumber +{ +//[ + public static ComplexNumber operator +(ComplexNumber c1, ComplexNumber c2) + => new ComplexNumber(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary); +//] +} +"; + + private static readonly string s_preferBlockBodyForOperators = @" +using System; + +struct ComplexNumber +{ +//[ + public static ComplexNumber operator +(ComplexNumber c1, ComplexNumber c2) + { + return new ComplexNumber(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary); + } +//] +} +"; + + private static readonly string s_preferExpressionBodyForProperties = @" +using System; + +//[ +class Customer +{ + private int _age; + public int Age => _age; +} +//] +"; + + private static readonly string s_preferBlockBodyForProperties = @" +using System; + +//[ +class Customer +{ + private int _age; + public int Age { get { return _age; } } +} +//] +"; + + private static readonly string s_preferExpressionBodyForAccessors = @" +using System; + +//[ +class Customer +{ + private int _age; + public int Age + { + get => _age; + set => _age = value; + } +} +//] +"; + + private static readonly string s_preferBlockBodyForAccessors = @" +using System; + +//[ +class Customer +{ + private int _age; + public int Age + { + get { return _age; } + set { _age = value; } + } +} +//] +"; + + private static readonly string s_preferExpressionBodyForIndexers= @" +using System; + +//[ +class List +{ + private T[] _values; + public T this[int i] => _values[i]; +} +//] +"; + + private static readonly string s_preferBlockBodyForIndexers = @" +using System; + +//[ +class List +{ + private T[] _values; + public T this[int i] { get { return _values[i]; } } +} +//] "; #endregion @@ -332,6 +496,7 @@ internal StyleViewModel(OptionSet optionSet, IServiceProvider serviceProvider) : var predefinedTypesGroupTitle = CSharpVSResources.predefined_type_preferences_colon; var varGroupTitle = CSharpVSResources.var_preferences_colon; var nullCheckingGroupTitle = CSharpVSResources.null_checking_colon; + var codeBlockPreferencesGroupTitle = ServicesVSResources.Code_block_preferences_colon; var expressionPreferencesGroupTitle = ServicesVSResources.Expression_preferences_colon; var variablePreferencesGroupTitle = ServicesVSResources.Variable_preferences_colon; @@ -353,6 +518,12 @@ internal StyleViewModel(OptionSet optionSet, IServiceProvider serviceProvider) : new CodeStylePreference(CSharpVSResources.Prefer_explicit_type, isChecked: false), }; + var codeBlockPreferences = new List + { + new CodeStylePreference(CSharpVSResources.Prefer_expression_body, isChecked: true), + new CodeStylePreference(CSharpVSResources.Prefer_block_body, isChecked: false), + }; + CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.QualifyFieldAccess, CSharpVSResources.Qualify_field_access_with_this, s_fieldDeclarationPreviewTrue, s_fieldDeclarationPreviewFalse, this, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences)); CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.QualifyPropertyAccess, CSharpVSResources.Qualify_property_access_with_this, s_propertyDeclarationPreviewTrue, s_propertyDeclarationPreviewFalse, this, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences)); CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.QualifyMethodAccess, CSharpVSResources.Qualify_method_access_with_this, s_methodDeclarationPreviewTrue, s_methodDeclarationPreviewFalse, this, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences)); @@ -361,13 +532,26 @@ internal StyleViewModel(OptionSet optionSet, IServiceProvider serviceProvider) : CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration, ServicesVSResources.For_locals_parameters_and_members, s_intrinsicPreviewDeclarationTrue, s_intrinsicPreviewDeclarationFalse, this, optionSet, predefinedTypesGroupTitle, predefinedTypesPreferences)); CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, ServicesVSResources.For_member_access_expressions, s_intrinsicPreviewMemberAccessTrue, s_intrinsicPreviewMemberAccessFalse, this, optionSet, predefinedTypesGroupTitle, predefinedTypesPreferences)); + // Use var CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, CSharpVSResources.For_built_in_types, s_varForIntrinsicsPreviewTrue, s_varForIntrinsicsPreviewFalse, this, optionSet, varGroupTitle, typeStylePreferences)); CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, CSharpVSResources.When_variable_type_is_apparent, s_varWhereApparentPreviewTrue, s_varWhereApparentPreviewFalse, this, optionSet, varGroupTitle, typeStylePreferences)); CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, CSharpVSResources.Elsewhere, s_varWherePossiblePreviewTrue, s_varWherePossiblePreviewFalse, this, optionSet, varGroupTitle, typeStylePreferences)); + // Code block + CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, ServicesVSResources.For_methods, s_preferExpressionBodyForMethods, s_preferBlockBodyForMethods, this, optionSet, codeBlockPreferencesGroupTitle, codeBlockPreferences)); + CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, ServicesVSResources.For_constructors, s_preferExpressionBodyForConstructors, s_preferBlockBodyForConstructors, this, optionSet, codeBlockPreferencesGroupTitle, codeBlockPreferences)); + CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, ServicesVSResources.For_operators, s_preferExpressionBodyForOperators, s_preferBlockBodyForOperators, this, optionSet, codeBlockPreferencesGroupTitle, codeBlockPreferences)); + CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, ServicesVSResources.For_properties, s_preferExpressionBodyForProperties, s_preferBlockBodyForProperties, this, optionSet, codeBlockPreferencesGroupTitle, codeBlockPreferences)); + CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, ServicesVSResources.For_indexers, s_preferExpressionBodyForIndexers, s_preferBlockBodyForIndexers, this, optionSet, codeBlockPreferencesGroupTitle, codeBlockPreferences)); + CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, ServicesVSResources.For_accessors, s_preferExpressionBodyForAccessors, s_preferBlockBodyForAccessors, this, optionSet, codeBlockPreferencesGroupTitle, codeBlockPreferences)); + + // Expressions CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferObjectInitializer, ServicesVSResources.Prefer_object_initializer, s_preferObjectInitializer, s_preferObjectInitializer, this, optionSet, expressionPreferencesGroupTitle)); + + // Variables CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferInlinedVariableDeclaration, ServicesVSResources.Prefer_inlined_variable_declaration, s_preferInlinedVariableDeclaration, s_preferInlinedVariableDeclaration, this, optionSet, variablePreferencesGroupTitle)); + // Null checking CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferThrowExpression, CSharpVSResources.Prefer_throw_expression, s_preferThrowExpression, s_preferThrowExpression, this, optionSet, nullCheckingGroupTitle)); CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferConditionalDelegateCall, CSharpVSResources.Prefer_conditional_delegate_call, s_preferConditionalDelegateCall, s_preferConditionalDelegateCall, this, optionSet, nullCheckingGroupTitle)); } diff --git a/src/VisualStudio/Core/Def/ServicesVSResources.Designer.cs b/src/VisualStudio/Core/Def/ServicesVSResources.Designer.cs index aea1d35be251a1400e9b9cb31a76f4e74d32b7b2..a1506b8c51a874ec3abc8dce895a8f2dfa5f0390 100644 --- a/src/VisualStudio/Core/Def/ServicesVSResources.Designer.cs +++ b/src/VisualStudio/Core/Def/ServicesVSResources.Designer.cs @@ -361,6 +361,15 @@ internal class ServicesVSResources { } } + /// + /// Looks up a localized string similar to Code block preferences:. + /// + internal static string Code_block_preferences_colon { + get { + return ResourceManager.GetString("Code_block_preferences_colon", resourceCulture); + } + } + /// /// Looks up a localized string similar to Computing remove suppressions fix.... /// @@ -732,6 +741,33 @@ internal class ServicesVSResources { } } + /// + /// Looks up a localized string similar to For accessors. + /// + internal static string For_accessors { + get { + return ResourceManager.GetString("For_accessors", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to For constructors. + /// + internal static string For_constructors { + get { + return ResourceManager.GetString("For_constructors", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to For indexers. + /// + internal static string For_indexers { + get { + return ResourceManager.GetString("For_indexers", resourceCulture); + } + } + /// /// Looks up a localized string similar to For locals, parameters and members. /// @@ -750,6 +786,33 @@ internal class ServicesVSResources { } } + /// + /// Looks up a localized string similar to For methods. + /// + internal static string For_methods { + get { + return ResourceManager.GetString("For_methods", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to For operators. + /// + internal static string For_operators { + get { + return ResourceManager.GetString("For_operators", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to For properties. + /// + internal static string For_properties { + get { + return ResourceManager.GetString("For_properties", resourceCulture); + } + } + /// /// Looks up a localized string similar to from Bing. /// diff --git a/src/VisualStudio/Core/Def/ServicesVSResources.resx b/src/VisualStudio/Core/Def/ServicesVSResources.resx index c8b561f00710edb3488cd013856e0debf5f10ede..114d9ceef702691a8d6b97c819540a5dce47b577 100644 --- a/src/VisualStudio/Core/Def/ServicesVSResources.resx +++ b/src/VisualStudio/Core/Def/ServicesVSResources.resx @@ -762,4 +762,25 @@ Additional information: {1} Prefer inlined variable declaration + + For methods + + + Code block preferences: + + + For accessors + + + For constructors + + + For indexers + + + For operators + + + For properties + \ No newline at end of file diff --git a/src/VisualStudio/Core/Test/CodeModel/AbstractCodeElementTests`1.vb b/src/VisualStudio/Core/Test/CodeModel/AbstractCodeElementTests`1.vb index c75b877d71d90dce6e449d0670c4edaa62e28ca0..60571555085d0f314c7348a39f19ab0108426dfb 100644 --- a/src/VisualStudio/Core/Test/CodeModel/AbstractCodeElementTests`1.vb +++ b/src/VisualStudio/Core/Test/CodeModel/AbstractCodeElementTests`1.vb @@ -3,6 +3,7 @@ Imports System.Runtime.InteropServices Imports System.Threading.Tasks Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions +Imports Microsoft.CodeAnalysis.Options Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel Partial Public MustInherit Class AbstractCodeElementTests(Of TCodeElement As Class) @@ -40,8 +41,16 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel End Using End Function - Protected Overloads Async Function TestElementUpdate(code As XElement, expectedCode As XElement, updater As Action(Of TCodeElement)) As Task + Protected Overloads Async Function TestElementUpdate( + code As XElement, expectedCode As XElement, updater As Action(Of TCodeElement), + Optional options As IDictionary(Of OptionKey, Object) = Nothing) As Task Using state = Await CreateCodeModelTestStateAsync(GetWorkspaceDefinition(code)) + If options IsNot Nothing Then + For Each kvp In options + state.Workspace.Options = state.Workspace.Options.WithChangedOption(kvp.Key, kvp.Value) + Next + End If + Dim codeElement = GetCodeElement(state) Assert.NotNull(codeElement) @@ -744,13 +753,16 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel End Sub) End Function - Protected Overrides Async Function TestAddProperty(code As XElement, expectedCode As XElement, data As PropertyData) As Task + Protected Overrides Async Function TestAddProperty( + code As XElement, expectedCode As XElement, data As PropertyData, + Optional options As IDictionary(Of OptionKey, Object) = Nothing) As Task Await TestElementUpdate(code, expectedCode, Sub(codeElement) Dim prop = AddProperty(codeElement, data) Assert.NotNull(prop) Assert.True(data.GetterName = prop.Name OrElse data.PutterName = prop.Name) - End Sub) + End Sub, + options) End Function Protected Overrides Async Function TestAddVariable(code As XElement, expectedCode As XElement, data As VariableData) As Task diff --git a/src/VisualStudio/Core/Test/CodeModel/AbstractCodeModelObjectTests.vb b/src/VisualStudio/Core/Test/CodeModel/AbstractCodeModelObjectTests.vb index 4125fabf71f203fb0160cf8b26cca49869389184..9d7e2a387dee5e8e527a4f7a1c7a53122005fc1e 100644 --- a/src/VisualStudio/Core/Test/CodeModel/AbstractCodeModelObjectTests.vb +++ b/src/VisualStudio/Core/Test/CodeModel/AbstractCodeModelObjectTests.vb @@ -1,6 +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. Imports System.Threading.Tasks +Imports Microsoft.CodeAnalysis.Options Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel Partial Public MustInherit Class AbstractCodeModelObjectTests(Of TCodeModelObject As Class) @@ -59,7 +60,8 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel Throw New NotImplementedException End Function - Protected Overridable Function TestAddProperty(code As XElement, expectedCode As XElement, data As PropertyData) As Task + Protected Overridable Function TestAddProperty(code As XElement, expectedCode As XElement, data As PropertyData, + Optional options As IDictionary(Of OptionKey, Object) = Nothing) As Task Throw New NotImplementedException End Function diff --git a/src/VisualStudio/Core/Test/CodeModel/CSharp/CodeClassTests.vb b/src/VisualStudio/Core/Test/CodeModel/CSharp/CodeClassTests.vb index 54dfaf00d8f56179e1692349c77174ebe3e0ec71..9a810d609af315b2e69c5403403c00eccdd1e654 100644 --- a/src/VisualStudio/Core/Test/CodeModel/CSharp/CodeClassTests.vb +++ b/src/VisualStudio/Core/Test/CodeModel/CSharp/CodeClassTests.vb @@ -3,8 +3,11 @@ Imports System.Threading Imports System.Threading.Tasks Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Text Imports Roslyn.Test.Utilities +Imports Microsoft.CodeAnalysis.CodeStyle +Imports Microsoft.CodeAnalysis.CSharp.CodeStyle Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel.CSharp Public Class CodeClassTests @@ -2154,6 +2157,32 @@ class C$$ Dim expected = class C +{ + string Name + { + get => default(string); + set + { + } + } +} + + + Await TestAddProperty(code, expected, New PropertyData With {.GetterName = "Name", .PutterName = "Name", .Type = EnvDTE.vsCMTypeRef.vsCMTypeRefString}) + End Function + + + Public Async Function TestAddProperty_NoCodeStyle1() As Task + Dim code = + +class C$$ +{ +} + + + Dim expected = + +class C { string Name { @@ -2169,7 +2198,13 @@ class C } - Await TestAddProperty(code, expected, New PropertyData With {.GetterName = "Name", .PutterName = "Name", .Type = EnvDTE.vsCMTypeRef.vsCMTypeRefString}) + Await TestAddProperty( + code, expected, + New PropertyData With {.GetterName = "Name", .PutterName = "Name", .Type = EnvDTE.vsCMTypeRef.vsCMTypeRefString}, + New Dictionary(Of OptionKey, Object) From { + {CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement}, + {CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement} + }) End Function @@ -2184,6 +2219,26 @@ class C$$ Dim expected = class C +{ + string Name => default(string); +} + + + Await TestAddProperty(code, expected, New PropertyData With {.GetterName = "Name", .PutterName = Nothing, .Type = EnvDTE.vsCMTypeRef.vsCMTypeRefString}) + End Function + + + Public Async Function TestAddProperty_NoCodeStyle2() As Task + Dim code = + +class C$$ +{ +} + + + Dim expected = + +class C { string Name { @@ -2195,7 +2250,12 @@ class C } - Await TestAddProperty(code, expected, New PropertyData With {.GetterName = "Name", .PutterName = Nothing, .Type = EnvDTE.vsCMTypeRef.vsCMTypeRefString}) + Await TestAddProperty( + code, expected, New PropertyData With {.GetterName = "Name", .PutterName = Nothing, .Type = EnvDTE.vsCMTypeRef.vsCMTypeRefString}, + New Dictionary(Of OptionKey, Object) From { + {CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement}, + {CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement} + }) End Function diff --git a/src/VisualStudio/Core/Test/CodeModel/CodeModelTestState.vb b/src/VisualStudio/Core/Test/CodeModel/CodeModelTestState.vb index f835dd2085d8669f6d8bf1869d5e742d211d0514..fd93b51226979079512509d52ac0fa77a25d4bf5 100644 --- a/src/VisualStudio/Core/Test/CodeModel/CodeModelTestState.vb +++ b/src/VisualStudio/Core/Test/CodeModel/CodeModelTestState.vb @@ -8,7 +8,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel Friend Class CodeModelTestState Implements IDisposable - Private ReadOnly _workspace As TestWorkspace + Public ReadOnly Workspace As TestWorkspace Private ReadOnly _visualStudioWorkspace As VisualStudioWorkspace Private ReadOnly _rootCodeModel As ComHandle(Of EnvDTE.CodeModel, RootCodeModel) Private ReadOnly _fileCodeModel As ComHandle(Of EnvDTE80.FileCodeModel2, FileCodeModel) @@ -30,19 +30,13 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel Throw New ArgumentNullException(NameOf(codeModelService)) End If - _workspace = workspace + Me.Workspace = workspace _visualStudioWorkspace = visualStudioWorkspace _rootCodeModel = rootCodeModel _fileCodeModel = fileCodeModel _codeModelService = codeModelService End Sub - Public ReadOnly Property Workspace As TestWorkspace - Get - Return _workspace - End Get - End Property - Public ReadOnly Property VisualStudioWorkspace As VisualStudioWorkspace Get Return _visualStudioWorkspace @@ -89,7 +83,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel If Not Me._disposedValue Then If disposing Then - _workspace.Dispose() + Workspace.Dispose() End If End If diff --git a/src/VisualStudio/Core/Test/ServicesVisualStudioTest.vbproj b/src/VisualStudio/Core/Test/ServicesVisualStudioTest.vbproj index f10c49a8f932b79eb1be49b0a0f8bf905402f272..0467001bf2cdc42fe7b61fdffe91acd04c22b7d4 100644 --- a/src/VisualStudio/Core/Test/ServicesVisualStudioTest.vbproj +++ b/src/VisualStudio/Core/Test/ServicesVisualStudioTest.vbproj @@ -38,6 +38,10 @@ {2e87fa96-50bb-4607-8676-46521599f998} Workspaces.Desktop + + {21b239d0-d144-430f-a394-c066d58ee267} + CSharpWorkspace + {57ca988d-f010-4bf2-9a2e-07d6dcd2ff2c} BasicWorkspace diff --git a/src/Workspaces/CSharp/Portable/CSharpWorkspace.csproj b/src/Workspaces/CSharp/Portable/CSharpWorkspace.csproj index 15b4d2afe76bd8a27b56fb1de3e1ac66987e5235..dc476245c57fecbbbed1f76ddb6683244ce6efc3 100644 --- a/src/Workspaces/CSharp/Portable/CSharpWorkspace.csproj +++ b/src/Workspaces/CSharp/Portable/CSharpWorkspace.csproj @@ -49,6 +49,7 @@ + @@ -96,6 +97,8 @@ + + @@ -244,4 +247,4 @@ - + \ No newline at end of file diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs index 6fe8d1021c807f1a9a02bca386e823529f31de17..10a4fdd67dbdf3090646d8a2a0a4e9e442f30be2 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs @@ -21,7 +21,8 @@ namespace Microsoft.CodeAnalysis.CSharp.CodeGeneration internal partial class CSharpCodeGenerationService : AbstractCodeGenerationService { public CSharpCodeGenerationService(HostLanguageServices languageServices) - : base(languageServices.GetService()) + : base(languageServices.GetService(), + languageServices.WorkspaceServices.Workspace) { } @@ -142,7 +143,8 @@ protected override TDeclarationNode AddMethod(TDeclarationNode { if (method.IsConstructor()) { - return Cast(ConstructorGenerator.AddConstructorTo(typeDeclaration, method, options, availableIndices)); + return Cast(ConstructorGenerator.AddConstructorTo( + typeDeclaration, method, Workspace, options, availableIndices)); } if (method.IsDestructor()) @@ -152,15 +154,18 @@ protected override TDeclarationNode AddMethod(TDeclarationNode if (method.MethodKind == MethodKind.Conversion) { - return Cast(ConversionGenerator.AddConversionTo(typeDeclaration, method, options, availableIndices)); + return Cast(ConversionGenerator.AddConversionTo( + typeDeclaration, method, Workspace, options, availableIndices)); } if (method.MethodKind == MethodKind.UserDefinedOperator) { - return Cast(OperatorGenerator.AddOperatorTo(typeDeclaration, method, options, availableIndices)); + return Cast(OperatorGenerator.AddOperatorTo( + typeDeclaration, method, Workspace, options, availableIndices)); } - return Cast(MethodGenerator.AddMethodTo(typeDeclaration, method, options, availableIndices)); + return Cast(MethodGenerator.AddMethodTo( + typeDeclaration, method, Workspace, options, availableIndices)); } if (method.IsConstructor() || @@ -172,11 +177,13 @@ protected override TDeclarationNode AddMethod(TDeclarationNode var compilationUnit = destination as CompilationUnitSyntax; if (compilationUnit != null) { - return Cast(MethodGenerator.AddMethodTo(compilationUnit, method, options, availableIndices)); + return Cast( + MethodGenerator.AddMethodTo(compilationUnit, method, Workspace, options, availableIndices)); } var ns = Cast(destination); - return Cast(MethodGenerator.AddMethodTo(ns, method, options, availableIndices)); + return Cast( + MethodGenerator.AddMethodTo(ns, method, Workspace, options, availableIndices)); } protected override TDeclarationNode AddProperty(TDeclarationNode destination, IPropertySymbol property, CodeGenerationOptions options, IList availableIndices) @@ -227,11 +234,13 @@ protected override TDeclarationNode AddProperty(TDeclarationNo if (destination is TypeDeclarationSyntax) { - return Cast(PropertyGenerator.AddPropertyTo(Cast(destination), property, options, availableIndices)); + return Cast(PropertyGenerator.AddPropertyTo( + Cast(destination), property, Workspace, options, availableIndices)); } else { - return Cast(PropertyGenerator.AddPropertyTo(Cast(destination), property, options, availableIndices)); + return Cast(PropertyGenerator.AddPropertyTo( + Cast(destination), property, Workspace, options, availableIndices)); } } @@ -610,7 +619,8 @@ public override SyntaxNode CreateFieldDeclaration(IFieldSymbol field, CodeGenera if (method.IsConstructor()) { - return ConstructorGenerator.GenerateConstructorDeclaration(method, destination, options); + return ConstructorGenerator.GenerateConstructorDeclaration( + method, destination, Workspace, options); } else if (method.IsDestructor()) { @@ -618,22 +628,22 @@ public override SyntaxNode CreateFieldDeclaration(IFieldSymbol field, CodeGenera } else if (method.IsUserDefinedOperator()) { - return OperatorGenerator.GenerateOperatorDeclaration(method, destination, options); + return OperatorGenerator.GenerateOperatorDeclaration(method, destination, Workspace, options); } else if (method.IsConversion()) { - return ConversionGenerator.GenerateConversionDeclaration(method, destination, options); + return ConversionGenerator.GenerateConversionDeclaration(method, destination, Workspace, options); } else { - return MethodGenerator.GenerateMethodDeclaration(method, destination, options); + return MethodGenerator.GenerateMethodDeclaration(method, destination, Workspace, options); } } public override SyntaxNode CreatePropertyDeclaration( IPropertySymbol property, CodeGenerationDestination destination, CodeGenerationOptions options) { - return PropertyGenerator.GeneratePropertyOrIndexer(property, destination, options); + return PropertyGenerator.GeneratePropertyOrIndexer(property, destination, Workspace, options); } public override SyntaxNode CreateNamedTypeDeclaration( diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/ConstructorGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/ConstructorGenerator.cs index 2821b35d9f410b5b37bd1f5bad92bb983781bb16..92e5a9e8ee36ce0e494d7c1fd90678440102c584 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/ConstructorGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/ConstructorGenerator.cs @@ -1,8 +1,10 @@ // 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.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -21,10 +23,12 @@ private static MemberDeclarationSyntax LastConstructorOrField(SyntaxList availableIndices) { - var constructorDeclaration = GenerateConstructorDeclaration(constructor, GetDestination(destination), options); + var constructorDeclaration = GenerateConstructorDeclaration( + constructor, GetDestination(destination), workspace, options); // Generate after the last constructor, or after the last field, or at the start of the // type. @@ -35,7 +39,8 @@ private static MemberDeclarationSyntax LastConstructorOrField(SyntaxList availableIndices) { - var methodDeclaration = GenerateConversionDeclaration(method, GetDestination(destination), options); + var methodDeclaration = GenerateConversionDeclaration( + method, GetDestination(destination), workspace, options); var members = Insert(destination.Members, methodDeclaration, options, availableIndices, after: LastOperator); @@ -28,9 +32,10 @@ internal static class ConversionGenerator internal static ConversionOperatorDeclarationSyntax GenerateConversionDeclaration( IMethodSymbol method, CodeGenerationDestination destination, + Workspace workspace, CodeGenerationOptions options) { - var declaration = GenerateConversionDeclarationWorker(method, destination, options); + var declaration = GenerateConversionDeclarationWorker(method, destination, workspace, options); return AddCleanupAnnotationsTo(AddAnnotationsTo(method, ConditionallyAddDocumentationCommentTo(declaration, method, options))); } @@ -38,6 +43,7 @@ internal static class ConversionGenerator private static ConversionOperatorDeclarationSyntax GenerateConversionDeclarationWorker( IMethodSymbol method, CodeGenerationDestination destination, + Workspace workspace, CodeGenerationOptions options) { var hasNoBody = !options.GenerateMethodBodies || method.IsExtern; @@ -53,7 +59,7 @@ internal static class ConversionGenerator ? SyntaxFactory.Token(SyntaxKind.ImplicitKeyword) : SyntaxFactory.Token(SyntaxKind.ExplicitKeyword); - return SyntaxFactory.ConversionOperatorDeclaration( + var declaration = SyntaxFactory.ConversionOperatorDeclaration( attributeLists: AttributeGenerator.GenerateAttributeLists(method.GetAttributes(), options), modifiers: GenerateModifiers(method), implicitOrExplicitKeyword: keyword, @@ -62,6 +68,31 @@ internal static class ConversionGenerator parameterList: ParameterGenerator.GenerateParameterList(method.Parameters, isExplicit: false, options: options), body: hasNoBody ? null : StatementGenerator.GenerateBlock(method), semicolonToken: hasNoBody ? SyntaxFactory.Token(SyntaxKind.SemicolonToken) : new SyntaxToken()); + + declaration = UseExpressionBodyIfDesired(workspace, declaration); + + return declaration; + } + + private static ConversionOperatorDeclarationSyntax UseExpressionBodyIfDesired( + Workspace workspace, ConversionOperatorDeclarationSyntax declaration) + { + if (declaration.ExpressionBody == null) + { + var preferExpressionBody = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators).Value; + if (preferExpressionBody) + { + var expressionBody = declaration.Body.TryConvertToExpressionBody(); + if (expressionBody != null) + { + return declaration.WithBody(null) + .WithExpressionBody(expressionBody) + .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + } + } + } + + return declaration; } private static SyntaxTokenList GenerateModifiers(IMethodSymbol method) diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs index bba77d7fbfa074a10cf5d27a0256f27ac8b3c3d4..d02f4626d58e89861b99d9fb1958b4c28eb9f7ef 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/MethodGenerator.cs @@ -1,8 +1,10 @@ // 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.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -17,10 +19,12 @@ internal static class MethodGenerator internal static NamespaceDeclarationSyntax AddMethodTo( NamespaceDeclarationSyntax destination, IMethodSymbol method, + Workspace workspace, CodeGenerationOptions options, IList availableIndices) { - var declaration = GenerateMethodDeclaration(method, CodeGenerationDestination.Namespace, options); + var declaration = GenerateMethodDeclaration( + method, CodeGenerationDestination.Namespace, workspace, options); var members = Insert(destination.Members, declaration, options, availableIndices, after: LastMethod); return destination.WithMembers(members.ToSyntaxList()); } @@ -28,10 +32,12 @@ internal static class MethodGenerator internal static CompilationUnitSyntax AddMethodTo( CompilationUnitSyntax destination, IMethodSymbol method, + Workspace workspace, CodeGenerationOptions options, IList availableIndices) { - var declaration = GenerateMethodDeclaration(method, CodeGenerationDestination.CompilationUnit, options); + var declaration = GenerateMethodDeclaration( + method, CodeGenerationDestination.CompilationUnit, workspace, options); var members = Insert(destination.Members, declaration, options, availableIndices, after: LastMethod); return destination.WithMembers(members.ToSyntaxList()); } @@ -39,10 +45,12 @@ internal static class MethodGenerator internal static TypeDeclarationSyntax AddMethodTo( TypeDeclarationSyntax destination, IMethodSymbol method, + Workspace workspace, CodeGenerationOptions options, IList availableIndices) { - var methodDeclaration = GenerateMethodDeclaration(method, GetDestination(destination), options); + var methodDeclaration = GenerateMethodDeclaration( + method, GetDestination(destination), workspace, options); // Create a clone of the original type with the new method inserted. var members = Insert(destination.Members, methodDeclaration, options, availableIndices, after: LastMethod); @@ -51,7 +59,8 @@ internal static class MethodGenerator } public static MethodDeclarationSyntax GenerateMethodDeclaration( - IMethodSymbol method, CodeGenerationDestination destination, CodeGenerationOptions options) + IMethodSymbol method, CodeGenerationDestination destination, + Workspace workspace, CodeGenerationOptions options) { options = options ?? CodeGenerationOptions.Default; @@ -61,14 +70,15 @@ internal static class MethodGenerator return reusableSyntax; } - var declaration = GenerateMethodDeclarationWorker(method, destination, options); + var declaration = GenerateMethodDeclarationWorker(method, destination, workspace, options); return AddAnnotationsTo(method, ConditionallyAddDocumentationCommentTo(declaration, method, options)); } private static MethodDeclarationSyntax GenerateMethodDeclarationWorker( - IMethodSymbol method, CodeGenerationDestination destination, CodeGenerationOptions options) + IMethodSymbol method, CodeGenerationDestination destination, + Workspace workspace, CodeGenerationOptions options) { var hasNoBody = !options.GenerateMethodBodies || destination == CodeGenerationDestination.InterfaceType || @@ -80,7 +90,7 @@ internal static class MethodGenerator ? method.ReturnType.GenerateRefTypeSyntax() : method.ReturnType.GenerateTypeSyntax(); - return AddCleanupAnnotationsTo(SyntaxFactory.MethodDeclaration( + var methodDeclaration = SyntaxFactory.MethodDeclaration( attributeLists: GenerateAttributes(method, options, explicitInterfaceSpecifier != null), modifiers: GenerateModifiers(method, destination, options), returnType: returnType, @@ -91,7 +101,32 @@ internal static class MethodGenerator constraintClauses: GenerateConstraintClauses(method), body: hasNoBody ? null : StatementGenerator.GenerateBlock(method), expressionBody: default(ArrowExpressionClauseSyntax), - semicolonToken: hasNoBody ? SyntaxFactory.Token(SyntaxKind.SemicolonToken) : new SyntaxToken())); + semicolonToken: hasNoBody ? SyntaxFactory.Token(SyntaxKind.SemicolonToken) : new SyntaxToken()); + + methodDeclaration = UseExpressionBodyIfDesired(workspace, methodDeclaration); + + return AddCleanupAnnotationsTo(methodDeclaration); + } + + private static MethodDeclarationSyntax UseExpressionBodyIfDesired( + Workspace workspace, MethodDeclarationSyntax methodDeclaration) + { + if (methodDeclaration.ExpressionBody == null) + { + var preferExpressionBody = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods).Value; + if (preferExpressionBody) + { + var expressionBody = methodDeclaration.Body.TryConvertToExpressionBody(); + if (expressionBody != null) + { + return methodDeclaration.WithBody(null) + .WithExpressionBody(expressionBody) + .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + } + } + } + + return methodDeclaration; } private static SyntaxList GenerateAttributes( diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/OperatorGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/OperatorGenerator.cs index 701d376683b228c576d7e63af48ed54e4648f255..f8a5ee9ddb96beaed3c259302564616796748df6 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/OperatorGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/OperatorGenerator.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -16,10 +17,12 @@ internal static class OperatorGenerator internal static TypeDeclarationSyntax AddOperatorTo( TypeDeclarationSyntax destination, IMethodSymbol method, + Workspace workspace, CodeGenerationOptions options, IList availableIndices) { - var methodDeclaration = GenerateOperatorDeclaration(method, GetDestination(destination), options); + var methodDeclaration = GenerateOperatorDeclaration( + method, GetDestination(destination), workspace, options); var members = Insert(destination.Members, methodDeclaration, options, availableIndices, after: LastOperator); @@ -29,6 +32,7 @@ internal static class OperatorGenerator internal static OperatorDeclarationSyntax GenerateOperatorDeclaration( IMethodSymbol method, CodeGenerationDestination destination, + Workspace workspace, CodeGenerationOptions options) { var reusableSyntax = GetReuseableSyntaxNodeForSymbol(method, options); @@ -38,11 +42,33 @@ internal static class OperatorGenerator } var declaration = GenerateOperatorDeclarationWorker(method, destination, options); + declaration = UseExpressionBodyIfDesired(workspace, declaration); return AddAnnotationsTo(method, ConditionallyAddDocumentationCommentTo(declaration, method, options)); } + private static OperatorDeclarationSyntax UseExpressionBodyIfDesired( + Workspace workspace, OperatorDeclarationSyntax declaration) + { + if (declaration.ExpressionBody == null) + { + var preferExpressionBody = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators).Value; + if (preferExpressionBody) + { + var expressionBody = declaration.Body.TryConvertToExpressionBody(); + if (expressionBody != null) + { + return declaration.WithBody(null) + .WithExpressionBody(expressionBody) + .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + } + } + } + + return declaration; + } + private static OperatorDeclarationSyntax GenerateOperatorDeclarationWorker( IMethodSymbol method, CodeGenerationDestination destination, diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/PropertyGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/PropertyGenerator.cs index 1070c342cf25bf8e1b17d6ce653724e4af7036c2..4d75f607cca7a363f9951cee74d026f36cf6ba71 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/PropertyGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/PropertyGenerator.cs @@ -1,8 +1,10 @@ // 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.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -30,10 +32,12 @@ public static bool CanBeGenerated(IPropertySymbol property) internal static CompilationUnitSyntax AddPropertyTo( CompilationUnitSyntax destination, IPropertySymbol property, + Workspace workspace, CodeGenerationOptions options, IList availableIndices) { - var declaration = GeneratePropertyOrIndexer(property, CodeGenerationDestination.CompilationUnit, options); + var declaration = GeneratePropertyOrIndexer( + property, CodeGenerationDestination.CompilationUnit, workspace, options); var members = Insert(destination.Members, declaration, options, availableIndices, after: LastPropertyOrField, before: FirstMember); @@ -43,10 +47,11 @@ public static bool CanBeGenerated(IPropertySymbol property) internal static TypeDeclarationSyntax AddPropertyTo( TypeDeclarationSyntax destination, IPropertySymbol property, + Workspace workspace, CodeGenerationOptions options, IList availableIndices) { - var declaration = GeneratePropertyOrIndexer(property, GetDestination(destination), options); + var declaration = GeneratePropertyOrIndexer(property, GetDestination(destination), workspace, options); // Create a clone of the original type with the new method inserted. var members = Insert(destination.Members, declaration, options, @@ -60,6 +65,7 @@ public static bool CanBeGenerated(IPropertySymbol property) public static MemberDeclarationSyntax GeneratePropertyOrIndexer( IPropertySymbol property, CodeGenerationDestination destination, + Workspace workspace, CodeGenerationOptions options) { var reusableSyntax = GetReuseableSyntaxNodeForSymbol(property, options); @@ -69,8 +75,8 @@ public static bool CanBeGenerated(IPropertySymbol property) } var declaration = property.IsIndexer - ? GenerateIndexerDeclaration(property, destination, options) - : GeneratePropertyDeclaration(property, destination, options); + ? GenerateIndexerDeclaration(property, destination, workspace, options) + : GeneratePropertyDeclaration(property, destination, workspace, options); return ConditionallyAddDocumentationCommentTo(declaration, property, options); } @@ -78,22 +84,27 @@ public static bool CanBeGenerated(IPropertySymbol property) private static MemberDeclarationSyntax GenerateIndexerDeclaration( IPropertySymbol property, CodeGenerationDestination destination, + Workspace workspace, CodeGenerationOptions options) { var explicitInterfaceSpecifier = GenerateExplicitInterfaceSpecifier(property.ExplicitInterfaceImplementations); - return AddCleanupAnnotationsTo( - AddAnnotationsTo(property, SyntaxFactory.IndexerDeclaration( + var declaration = SyntaxFactory.IndexerDeclaration( attributeLists: AttributeGenerator.GenerateAttributeLists(property.GetAttributes(), options), modifiers: GenerateModifiers(property, destination, options), type: property.Type.GenerateTypeSyntax(), explicitInterfaceSpecifier: explicitInterfaceSpecifier, parameterList: ParameterGenerator.GenerateBracketedParameterList(property.Parameters, explicitInterfaceSpecifier != null, options), - accessorList: GenerateAccessorList(property, destination, options)))); + accessorList: GenerateAccessorList(property, destination, workspace, options)); + declaration = UseExpressionBodyIfDesired(workspace, declaration); + + return AddCleanupAnnotationsTo( + AddAnnotationsTo(property, declaration)); } private static MemberDeclarationSyntax GeneratePropertyDeclaration( - IPropertySymbol property, CodeGenerationDestination destination, CodeGenerationOptions options) + IPropertySymbol property, CodeGenerationDestination destination, + Workspace workspace, CodeGenerationOptions options) { var initializerNode = CodeGenerationPropertyInfo.GetInitializer(property) as ExpressionSyntax; @@ -103,27 +114,122 @@ public static bool CanBeGenerated(IPropertySymbol property) var explicitInterfaceSpecifier = GenerateExplicitInterfaceSpecifier(property.ExplicitInterfaceImplementations); - var accessorList = GenerateAccessorList(property, destination, options); + var accessorList = GenerateAccessorList(property, destination, workspace, options); + + var propertyDeclaration = SyntaxFactory.PropertyDeclaration( + attributeLists: AttributeGenerator.GenerateAttributeLists(property.GetAttributes(), options), + modifiers: GenerateModifiers(property, destination, options), + type: property.Type.GenerateTypeSyntax(), + explicitInterfaceSpecifier: explicitInterfaceSpecifier, + identifier: property.Name.ToIdentifierToken(), + accessorList: accessorList, + expressionBody: default(ArrowExpressionClauseSyntax), + initializer: initializer); + + propertyDeclaration = UseExpressionBodyIfDesired( + workspace, propertyDeclaration); return AddCleanupAnnotationsTo( - AddAnnotationsTo(property, SyntaxFactory.PropertyDeclaration( - attributeLists: AttributeGenerator.GenerateAttributeLists(property.GetAttributes(), options), - modifiers: GenerateModifiers(property, destination, options), - type: property.Type.GenerateTypeSyntax(), - explicitInterfaceSpecifier: explicitInterfaceSpecifier, - identifier: property.Name.ToIdentifierToken(), - accessorList: accessorList, - expressionBody: default(ArrowExpressionClauseSyntax), - initializer: initializer))); + AddAnnotationsTo(property, propertyDeclaration)); + } + + private static ArrowExpressionClauseSyntax TryGetExpressionBody(AccessorListSyntax accessorList) + { + if (accessorList.Accessors.Count == 1) + { + var accessor = accessorList.Accessors[0]; + if (accessor.IsKind(SyntaxKind.GetAccessorDeclaration)) + { + return TryGetExpressionBody(accessor); + } + } + + return null; + } + + private static PropertyDeclarationSyntax UseExpressionBodyIfDesired( + Workspace workspace, PropertyDeclarationSyntax declaration) + { + if (declaration.ExpressionBody == null) + { + var preferExpressionBody = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties).Value; + if (preferExpressionBody) + { + if (declaration.Initializer == null) + { + var expressionBody = TryGetExpressionBody(declaration.AccessorList); + if (expressionBody != null) + { + declaration = declaration.WithAccessorList(null) + .WithExpressionBody(expressionBody) + .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + } + } + } + } + + return declaration; + } + + private static IndexerDeclarationSyntax UseExpressionBodyIfDesired( + Workspace workspace, IndexerDeclarationSyntax declaration) + { + if (declaration.ExpressionBody == null) + { + var preferExpressionBody = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers).Value; + if (preferExpressionBody) + { + var expressionBody = TryGetExpressionBody(declaration.AccessorList); + if (expressionBody != null) + { + declaration = declaration.WithAccessorList(null) + .WithExpressionBody(expressionBody) + .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + } + } + } + + return declaration; + } + + private static AccessorDeclarationSyntax UseExpressionBodyIfDesired( + Workspace workspace, AccessorDeclarationSyntax declaration) + { + if (declaration.ExpressionBody == null) + { + var preferExpressionBody = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value; + if (preferExpressionBody) + { + var expressionBody = declaration.Body.TryConvertToExpressionBody(); + if (expressionBody != null) + { + declaration = declaration.WithBody(null) + .WithExpressionBody(expressionBody) + .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + } + } + } + + return declaration; + } + + private static ArrowExpressionClauseSyntax TryGetExpressionBody(AccessorDeclarationSyntax accessor) + { + // If the accessor has an expression body already, then use that as the expression body + // for the property. + return accessor.ExpressionBody != null + ? accessor.ExpressionBody + : accessor.Body.TryConvertToExpressionBody(); } private static AccessorListSyntax GenerateAccessorList( - IPropertySymbol property, CodeGenerationDestination destination, CodeGenerationOptions options) + IPropertySymbol property, CodeGenerationDestination destination, + Workspace workspace, CodeGenerationOptions options) { var accessors = new List { - GenerateAccessorDeclaration(property, property.GetMethod, SyntaxKind.GetAccessorDeclaration, destination, options), - GenerateAccessorDeclaration(property, property.SetMethod, SyntaxKind.SetAccessorDeclaration, destination, options), + GenerateAccessorDeclaration(property, property.GetMethod, SyntaxKind.GetAccessorDeclaration, destination, workspace, options), + GenerateAccessorDeclaration(property, property.SetMethod, SyntaxKind.SetAccessorDeclaration, destination, workspace, options), }; return accessors[0] == null && accessors[1] == null @@ -136,12 +242,13 @@ public static bool CanBeGenerated(IPropertySymbol property) IMethodSymbol accessor, SyntaxKind kind, CodeGenerationDestination destination, + Workspace workspace, CodeGenerationOptions options) { var hasBody = options.GenerateMethodBodies && HasAccessorBodies(property, destination, accessor); return accessor == null ? null - : GenerateAccessorDeclaration(property, accessor, kind, hasBody, options); + : GenerateAccessorDeclaration(property, accessor, kind, hasBody, workspace, options); } private static AccessorDeclarationSyntax GenerateAccessorDeclaration( @@ -149,12 +256,17 @@ public static bool CanBeGenerated(IPropertySymbol property) IMethodSymbol accessor, SyntaxKind kind, bool hasBody, + Workspace workspace, CodeGenerationOptions options) { - return AddAnnotationsTo(accessor, SyntaxFactory.AccessorDeclaration(kind) - .WithModifiers(GenerateAccessorModifiers(property, accessor, options)) - .WithBody(hasBody ? GenerateBlock(accessor) : null) - .WithSemicolonToken(hasBody ? default(SyntaxToken) : SyntaxFactory.Token(SyntaxKind.SemicolonToken))); + var declaration = SyntaxFactory.AccessorDeclaration(kind) + .WithModifiers(GenerateAccessorModifiers(property, accessor, options)) + .WithBody(hasBody ? GenerateBlock(accessor) : null) + .WithSemicolonToken(hasBody ? default(SyntaxToken) : SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + + declaration = UseExpressionBodyIfDesired(workspace, declaration); + + return AddAnnotationsTo(accessor, declaration); } private static BlockSyntax GenerateBlock(IMethodSymbol accessor) diff --git a/src/Workspaces/CSharp/Portable/CodeStyle/CSharpCodeStyleOptions.cs b/src/Workspaces/CSharp/Portable/CodeStyle/CSharpCodeStyleOptions.cs index 481f84cdf29afd970fdb107fdd5602f8f5787e18..c59f128b44a752b233ac333ffd7d926bd36da3d7 100644 --- a/src/Workspaces/CSharp/Portable/CodeStyle/CSharpCodeStyleOptions.cs +++ b/src/Workspaces/CSharp/Portable/CodeStyle/CSharpCodeStyleOptions.cs @@ -20,7 +20,31 @@ internal static class CSharpCodeStyleOptions public static readonly Option> UseImplicitTypeWherePossible = new Option>(nameof(CodeStyleOptions), nameof(UseImplicitTypeWherePossible), defaultValue: CodeStyleOption.Default, storageLocations: new RoamingProfileStorageLocation("TextEditor.CSharp.Specific.UseImplicitTypeWherePossible")); - public static readonly Option> PreferConditionalDelegateCall = new Option>(nameof(CodeStyleOptions), nameof(PreferConditionalDelegateCall), defaultValue: CodeStyleOptions.trueWithSuggestionEnforcement, + public static readonly Option> PreferConditionalDelegateCall = new Option>(nameof(CodeStyleOptions), nameof(PreferConditionalDelegateCall), defaultValue: CodeStyleOptions.TrueWithSuggestionEnforcement, storageLocations: new RoamingProfileStorageLocation("TextEditor.CSharp.Specific.PreferConditionalDelegateCall")); + + public static readonly Option> PreferExpressionBodiedConstructors = new Option>( + nameof(CodeStyleOptions), nameof(PreferExpressionBodiedConstructors), defaultValue: CodeStyleOptions.FalseWithNoneEnforcement, + storageLocations: new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedConstructors)}")); + + public static readonly Option> PreferExpressionBodiedMethods = new Option>( + nameof(CodeStyleOptions), nameof(PreferExpressionBodiedMethods), defaultValue: CodeStyleOptions.FalseWithNoneEnforcement, + storageLocations: new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedMethods)}")); + + public static readonly Option> PreferExpressionBodiedOperators = new Option>( + nameof(CodeStyleOptions), nameof(PreferExpressionBodiedOperators), defaultValue: CodeStyleOptions.FalseWithNoneEnforcement, + storageLocations: new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedOperators)}")); + + public static readonly Option> PreferExpressionBodiedProperties = new Option>( + nameof(CodeStyleOptions), nameof(PreferExpressionBodiedProperties), defaultValue: CodeStyleOptions.TrueWithNoneEnforcement, + storageLocations: new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedProperties)}")); + + public static readonly Option> PreferExpressionBodiedIndexers = new Option>( + nameof(CodeStyleOptions), nameof(PreferExpressionBodiedIndexers), defaultValue: CodeStyleOptions.TrueWithNoneEnforcement, + storageLocations: new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedIndexers)}")); + + public static readonly Option> PreferExpressionBodiedAccessors = new Option>( + nameof(CodeStyleOptions), nameof(PreferExpressionBodiedAccessors), defaultValue: CodeStyleOptions.TrueWithNoneEnforcement, + storageLocations: new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedAccessors)}")); } -} +} \ No newline at end of file diff --git a/src/Workspaces/CSharp/Portable/Extensions/ArrowExpressionClauseSyntaxExtensions.cs b/src/Workspaces/CSharp/Portable/Extensions/ArrowExpressionClauseSyntaxExtensions.cs new file mode 100644 index 0000000000000000000000000000000000000000..2ef993f1abe380ff7e3beeebb5617f452a2264bd --- /dev/null +++ b/src/Workspaces/CSharp/Portable/Extensions/ArrowExpressionClauseSyntaxExtensions.cs @@ -0,0 +1,40 @@ +// 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.CSharp.Syntax; + +namespace Microsoft.CodeAnalysis.CSharp.Extensions +{ + internal static class ArrowExpressionClauseSyntaxExtensions + { + public static BlockSyntax ConvertToBlock( + this ArrowExpressionClauseSyntax arrowExpression, + SyntaxToken semicolonToken, + bool createReturnStatementForExpression) + { + var statement = ConvertToStatement(arrowExpression.Expression, semicolonToken, createReturnStatementForExpression); + return SyntaxFactory.Block(statement); + } + + private static StatementSyntax ConvertToStatement( + ExpressionSyntax expression, + SyntaxToken semicolonToken, + bool createReturnStatementForExpression) + { + if (expression.IsKind(SyntaxKind.ThrowExpression)) + { + var throwExpression = (ThrowExpressionSyntax)expression; + return SyntaxFactory.ThrowStatement(throwExpression.ThrowKeyword, throwExpression.Expression, semicolonToken); + } + else if (createReturnStatementForExpression) + { + return SyntaxFactory.ReturnStatement(expression) + .WithSemicolonToken(semicolonToken); + } + else + { + return SyntaxFactory.ExpressionStatement(expression) + .WithSemicolonToken(semicolonToken); + } + } + } +} diff --git a/src/Workspaces/CSharp/Portable/Extensions/BlockSyntaxExtensions.cs b/src/Workspaces/CSharp/Portable/Extensions/BlockSyntaxExtensions.cs new file mode 100644 index 0000000000000000000000000000000000000000..b442ddf0d04567e9f693944338e48106fef2db85 --- /dev/null +++ b/src/Workspaces/CSharp/Portable/Extensions/BlockSyntaxExtensions.cs @@ -0,0 +1,55 @@ +// 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 Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.CodeAnalysis.CSharp.Extensions +{ + internal static class BlockSyntaxExtensions + { + public static ArrowExpressionClauseSyntax TryConvertToExpressionBody(this BlockSyntax block) + { + if (block != null && block.Statements.Count == 1) + { + var firstStatement = block.Statements[0]; + var expression = TryGetExpression(firstStatement); + if (expression != null) + { + return SyntaxFactory.ArrowExpressionClause(expression); + } + } + + return null; + } + + private static ExpressionSyntax TryGetExpression(StatementSyntax firstStatement) + { + if (firstStatement.Kind() == SyntaxKind.ExpressionStatement) + { + return ((ExpressionStatementSyntax)firstStatement).Expression; + } + else if (firstStatement.Kind() == SyntaxKind.ReturnStatement) + { + var returnStatement = (ReturnStatementSyntax)firstStatement; + if (returnStatement.Expression != null) + { + // If there are any comments on the return keyword, move them to + // the expression. + return firstStatement.GetLeadingTrivia().Any(t => t.IsSingleOrMultiLineComment()) + ? returnStatement.Expression.WithLeadingTrivia(returnStatement.GetLeadingTrivia()) + : returnStatement.Expression; + } + } + else if (firstStatement.Kind() == SyntaxKind.ThrowStatement) + { + var throwStatement = (ThrowStatementSyntax)firstStatement; + if (throwStatement.Expression != null) + { + return SyntaxFactory.ThrowExpression(throwStatement.ThrowKeyword, throwStatement.Expression); + } + } + + return null; + } + } +} \ No newline at end of file diff --git a/src/Workspaces/CSharp/Portable/Extensions/TypeSyntaxExtensions.cs b/src/Workspaces/CSharp/Portable/Extensions/TypeSyntaxExtensions.cs index 4a2e83754773c512e5424ee84a6f64e0d524356f..6081a8d26236e2d694714cbde840d1eba98900f4 100644 --- a/src/Workspaces/CSharp/Portable/Extensions/TypeSyntaxExtensions.cs +++ b/src/Workspaces/CSharp/Portable/Extensions/TypeSyntaxExtensions.cs @@ -12,6 +12,12 @@ namespace Microsoft.CodeAnalysis.CSharp.Extensions { internal static class TypeSyntaxExtensions { + public static bool IsVoid(this TypeSyntax typeSyntax) + { + return typeSyntax.IsKind(SyntaxKind.PredefinedType) && + ((PredefinedTypeSyntax)typeSyntax).Keyword.IsKind(SyntaxKind.VoidKeyword); + } + public static bool IsPartial(this TypeSyntax typeSyntax) { return typeSyntax is IdentifierNameSyntax && diff --git a/src/Workspaces/Core/Portable/CodeGeneration/AbstractCodeGenerationService.cs b/src/Workspaces/Core/Portable/CodeGeneration/AbstractCodeGenerationService.cs index 1884f2c086aa2274f41731084b47cf2d486e932b..3f1c448c1a83f3a2c6936b7f58b5dc7f15907afd 100644 --- a/src/Workspaces/Core/Portable/CodeGeneration/AbstractCodeGenerationService.cs +++ b/src/Workspaces/Core/Portable/CodeGeneration/AbstractCodeGenerationService.cs @@ -15,11 +15,14 @@ namespace Microsoft.CodeAnalysis.CodeGeneration internal abstract partial class AbstractCodeGenerationService : ICodeGenerationService { private readonly ISymbolDeclarationService _symbolDeclarationService; + protected readonly Workspace Workspace; protected AbstractCodeGenerationService( - ISymbolDeclarationService symbolDeclarationService) + ISymbolDeclarationService symbolDeclarationService, + Workspace workspace) { _symbolDeclarationService = symbolDeclarationService; + Workspace = workspace; } public TDeclarationNode AddEvent(TDeclarationNode destination, IEventSymbol @event, CodeGenerationOptions options, CancellationToken cancellationToken) where TDeclarationNode : SyntaxNode diff --git a/src/Workspaces/Core/Portable/CodeStyle/CodeStyleOptions.cs b/src/Workspaces/Core/Portable/CodeStyle/CodeStyleOptions.cs index fcd0e18b3501ba9cb0647136c0259f4bdb79dc86..c247491e7f62166589ff9711dd11bbb192dee5cb 100644 --- a/src/Workspaces/Core/Portable/CodeStyle/CodeStyleOptions.cs +++ b/src/Workspaces/Core/Portable/CodeStyle/CodeStyleOptions.cs @@ -11,8 +11,9 @@ public class CodeStyleOptions /// One such default(s), is that the feature is turned on, so that codegen consumes it, /// but with none enforcement, so that the user is not prompted about their usage. /// - private static readonly CodeStyleOption trueWithNoneEnforcement = new CodeStyleOption(value: true, notification: NotificationOption.None); - internal static readonly CodeStyleOption trueWithSuggestionEnforcement = new CodeStyleOption(value: true, notification: NotificationOption.Suggestion); + internal static readonly CodeStyleOption TrueWithNoneEnforcement = new CodeStyleOption(value: true, notification: NotificationOption.None); + internal static readonly CodeStyleOption TrueWithSuggestionEnforcement = new CodeStyleOption(value: true, notification: NotificationOption.Suggestion); + internal static readonly CodeStyleOption FalseWithNoneEnforcement = new CodeStyleOption(value: false, notification: NotificationOption.None); /// /// This option says if we should simplify away the . or . in field access expressions. @@ -41,25 +42,25 @@ public class CodeStyleOptions /// /// This option says if we should prefer keyword for Intrinsic Predefined Types in Declarations /// - public static readonly PerLanguageOption> PreferIntrinsicPredefinedTypeKeywordInDeclaration = new PerLanguageOption>(nameof(CodeStyleOptions), nameof(PreferIntrinsicPredefinedTypeKeywordInDeclaration), defaultValue: trueWithNoneEnforcement, + public static readonly PerLanguageOption> PreferIntrinsicPredefinedTypeKeywordInDeclaration = new PerLanguageOption>(nameof(CodeStyleOptions), nameof(PreferIntrinsicPredefinedTypeKeywordInDeclaration), defaultValue: TrueWithNoneEnforcement, storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferIntrinsicPredefinedTypeKeywordInDeclaration")); /// /// This option says if we should prefer keyword for Intrinsic Predefined Types in Member Access Expression /// - public static readonly PerLanguageOption> PreferIntrinsicPredefinedTypeKeywordInMemberAccess = new PerLanguageOption>(nameof(CodeStyleOptions), nameof(PreferIntrinsicPredefinedTypeKeywordInMemberAccess), defaultValue: trueWithNoneEnforcement, + public static readonly PerLanguageOption> PreferIntrinsicPredefinedTypeKeywordInMemberAccess = new PerLanguageOption>(nameof(CodeStyleOptions), nameof(PreferIntrinsicPredefinedTypeKeywordInMemberAccess), defaultValue: TrueWithNoneEnforcement, storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferIntrinsicPredefinedTypeKeywordInMemberAccess")); internal static readonly PerLanguageOption> PreferThrowExpression = new PerLanguageOption>( nameof(CodeStyleOptions), nameof(PreferThrowExpression), - defaultValue: trueWithSuggestionEnforcement, + defaultValue: TrueWithSuggestionEnforcement, storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferThrowExpression")); internal static readonly PerLanguageOption> PreferObjectInitializer = new PerLanguageOption>( nameof(CodeStyleOptions), nameof(PreferObjectInitializer), - defaultValue: trueWithSuggestionEnforcement, + defaultValue: TrueWithSuggestionEnforcement, storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferObjectInitializer")); internal static readonly PerLanguageOption PreferObjectInitializer_FadeOutCode = new PerLanguageOption( @@ -71,7 +72,7 @@ public class CodeStyleOptions internal static readonly PerLanguageOption> PreferInlinedVariableDeclaration = new PerLanguageOption>( nameof(CodeStyleOptions), nameof(PreferInlinedVariableDeclaration), - defaultValue: trueWithSuggestionEnforcement, + defaultValue: TrueWithSuggestionEnforcement, storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferInlinedVariableDeclaration")); } diff --git a/src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicCodeGenerationService.vb b/src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicCodeGenerationService.vb index 5c881aa669aa6bc69868b1fd83488d1ef0dc02f5..03f64732c38945857029ffea819baaee284ec8c8 100644 --- a/src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicCodeGenerationService.vb +++ b/src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicCodeGenerationService.vb @@ -15,7 +15,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Inherits AbstractCodeGenerationService Public Sub New(provider As HostLanguageServices) - MyBase.New(provider.GetService(Of ISymbolDeclarationService)()) + MyBase.New(provider.GetService(Of ISymbolDeclarationService)(), + provider.WorkspaceServices.Workspace) End Sub Public Overloads Overrides Function GetDestination(containerNode As SyntaxNode) As CodeGenerationDestination