提交 69312408 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #14399 from CyrusNajmabadi/expressionBodies

Provide user facing options to control if expression bodied members are preferred or not.
......@@ -310,6 +310,13 @@
<Compile Include="Organizing\OrganizeUsingsTests.cs" />
<Compile Include="Structure\BlockSyntaxStructureTests.cs" />
<Compile Include="Structure\SwitchStatementStructureTests.cs" />
<Compile Include="UseExpressionBody\UseExpressionBodyForIndexerTests.cs" />
<Compile Include="UseExpressionBody\UseExpressionBodyForPropertiesTests.cs" />
<Compile Include="UseExpressionBody\UseExpressionBodyForConstructorsTests.cs" />
<Compile Include="UseExpressionBody\UseExpressionBodyForConversionOperatorsTests.cs" />
<Compile Include="UseExpressionBody\UseExpressionBodyForAccessorsTests.cs" />
<Compile Include="UseExpressionBody\UseExpressionBodyForOperatorsTests.cs" />
<Compile Include="UseExpressionBody\UseExpressionBodyForMethodsTests.cs" />
<Compile Include="UseThrowExpression\UseThrowExpressionTests_FixAllTests.cs" />
<Compile Include="UseThrowExpression\UseThrowExpressionTests.cs" />
<Compile Include="Structure\AbstractCSharpSyntaxNodeStructureTests.cs" />
......
// 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<OptionKey, object> AllOptionsOff =
new Dictionary<OptionKey, object>
{
{ 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<OptionKey, object> options = null,
bool withScriptOption = false)
{
options = options ?? new Dictionary<OptionKey, object>();
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()
</Document>
</Project>
</Workspace>";
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);
}
}
}
......@@ -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()
......
......@@ -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()
{
......
......@@ -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()
{
......
......@@ -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)]
......
......@@ -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);
}
......
......@@ -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()
{
......
......@@ -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()
......
......@@ -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()
......
......@@ -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);
......
......@@ -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()
</Workspace>";
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,
......
......@@ -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<EncapsulateFieldTestState> 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);
}
......
......@@ -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)]
......
// 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<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
=> new Tuple<DiagnosticAnalyzer, CodeFixProvider>(
new UseExpressionBodyForAccessorsDiagnosticAnalyzer(),
new UseExpressionBodyForAccessorsCodeFixProvider());
private static readonly Dictionary<OptionKey, object> UseExpressionBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.FalseWithNoneEnforcement }
};
private static readonly Dictionary<OptionKey, object> UseExpressionBodyIncludingPropertiesAndIndexers =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.TrueWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.TrueWithNoneEnforcement }
};
private static readonly Dictionary<OptionKey, object> UseBlockBody =
new Dictionary<OptionKey, object>
{
{ 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
// 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<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
=> new Tuple<DiagnosticAnalyzer, CodeFixProvider>(
new UseExpressionBodyForConstructorsDiagnosticAnalyzer(),
new UseExpressionBodyForConstructorsCodeFixProvider());
private static readonly Dictionary<OptionKey, object> UseExpressionBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CodeStyleOptions.TrueWithNoneEnforcement }
};
private static readonly Dictionary<OptionKey, object> UseBlockBody =
new Dictionary<OptionKey, object>
{
{ 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
// 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<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
=> new Tuple<DiagnosticAnalyzer, CodeFixProvider>(
new UseExpressionBodyForConversionOperatorsDiagnosticAnalyzer(),
new UseExpressionBodyForConversionOperatorsCodeFixProvider());
private static readonly Dictionary<OptionKey, object> UseExpressionBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.TrueWithNoneEnforcement }
};
private static readonly Dictionary<OptionKey, object> UseBlockBody =
new Dictionary<OptionKey, object>
{
{ 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
// 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<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
=> new Tuple<DiagnosticAnalyzer, CodeFixProvider>(
new UseExpressionBodyForIndexersDiagnosticAnalyzer(),
new UseExpressionBodyForIndexersCodeFixProvider());
private static readonly Dictionary<OptionKey, object> UseExpressionBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.TrueWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement },
};
private static readonly Dictionary<OptionKey, object> UseBlockBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement }
};
private static readonly Dictionary<OptionKey, object> UseBlockBodyExceptAccessor =
new Dictionary<OptionKey, object>
{
{ 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
// 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<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
=> new Tuple<DiagnosticAnalyzer, CodeFixProvider>(
new UseExpressionBodyForMethodsDiagnosticAnalyzer(),
new UseExpressionBodyForMethodsCodeFixProvider());
private static readonly Dictionary<OptionKey, object> UseExpressionBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.TrueWithNoneEnforcement }
};
private static readonly Dictionary<OptionKey, object> UseBlockBody =
new Dictionary<OptionKey, object>
{
{ 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
// 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<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
=> new Tuple<DiagnosticAnalyzer, CodeFixProvider>(
new UseExpressionBodyForOperatorsDiagnosticAnalyzer(),
new UseExpressionBodyForOperatorsCodeFixProvider());
private static readonly Dictionary<OptionKey, object> UseExpressionBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.TrueWithNoneEnforcement }
};
private static readonly Dictionary<OptionKey, object> UseBlockBody =
new Dictionary<OptionKey, object>
{
{ 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
// 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<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
=> new Tuple<DiagnosticAnalyzer, CodeFixProvider>(
new UseExpressionBodyForPropertiesDiagnosticAnalyzer(),
new UseExpressionBodyForPropertiesCodeFixProvider());
private static readonly Dictionary<OptionKey, object> UseExpressionBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.TrueWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement },
};
private static readonly Dictionary<OptionKey, object> UseBlockBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement }
};
private static readonly Dictionary<OptionKey, object> UseBlockBodyExceptAccessor =
new Dictionary<OptionKey, object>
{
{ 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
......@@ -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<OptionKey, object> 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<OptionKey, object> options = null,
string fixAllActionEquivalenceKey = null,
object fixProviderData = null,
CodeActionPriority? priority = null)
int index, bool compareTokens,
IDictionary<OptionKey, object> options,
string fixAllActionEquivalenceKey,
object fixProviderData,
CodeActionPriority? priority)
{
string expected;
IDictionary<string, IList<TextSpan>> spanMap;
......@@ -530,12 +532,13 @@ protected static IList<CodeAction> FlattenActions(IEnumerable<CodeAction> codeAc
return codeActions?.SelectMany(a => a.HasCodeActions ? a.GetCodeActions().ToArray() : new[] { a }).ToList();
}
protected IDictionary<OptionKey, object> Option(PerLanguageOption<CodeStyle.CodeStyleOption<bool>> option, bool value, CodeStyle.NotificationOption notification)
{
return OptionsSet(Tuple.Create(option, value, notification));
}
protected IDictionary<OptionKey, object> Option(IOption option, CodeStyleOption<bool> notification)
=> Option(option, notification.Value, notification.Notification);
protected IDictionary<OptionKey, object> Option(IOption option, bool value, NotificationOption notification)
=> OptionsSet(Tuple.Create(option, value, notification));
protected IDictionary<OptionKey, object> OptionsSet(params Tuple<PerLanguageOption<CodeStyle.CodeStyleOption<bool>>, bool, CodeStyle.NotificationOption>[] optionsToSet)
protected IDictionary<OptionKey, object> OptionsSet(params Tuple<IOption, bool, NotificationOption>[] optionsToSet)
{
var options = new Dictionary<OptionKey, object>();
foreach (var triple in optionsToSet)
......@@ -543,7 +546,8 @@ protected static IList<CodeAction> FlattenActions(IEnumerable<CodeAction> codeAc
var option = triple.Item1;
var value = triple.Item2;
var notification = triple.Item3;
options.Add(new OptionKey(option, GetLanguage()), new CodeStyle.CodeStyleOption<bool>(value, notification));
var optionKey = new OptionKey(option, option.IsPerLanguage ? GetLanguage() : null);
options.Add(optionKey, new CodeStyleOption<bool>(value, notification));
}
return options;
......
......@@ -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<OptionKey, object> {
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.FalseWithNoneEnforcement },
});
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
public async Task AddParameterfulProperty()
{
......
......@@ -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<Func<SemanticModel, IParameterSymbol>> parameters = null,
bool isIndexer = false,
CodeGenerationOptions codeGenerationOptions = default(CodeGenerationOptions),
bool compareTokens = true)
bool compareTokens = true,
IDictionary<OptionKey, object> 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<IParameterSymbol>(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<ICodeGenerationService>();
......@@ -824,23 +834,23 @@ public static async Task<TestContext> 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<INamespaceOrTypeSymbol>(destSpan, this.SemanticModel);
}
public IEnumerable<ISymbol> 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<ISymbol>(span, semanticModel);
......@@ -861,7 +871,7 @@ public T GetSelectedSymbol<T>(TextSpan selection, SemanticModel semanticModel)
public T GetSelectedSyntax<T>(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<T>().FirstOrDefault(t => !fullSpanCoverage || t.Span.End >= destSpan.End);
}
......@@ -913,7 +923,7 @@ public void Dispose()
}
finally
{
_workspace.Dispose();
Workspace.Dispose();
}
}
......
......@@ -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,
......
// 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
{
......
......@@ -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";
......
......@@ -840,8 +840,9 @@ 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)
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)
......
......@@ -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]]>
</Workspace>.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,
......
......@@ -58,6 +58,19 @@
<Compile Include="..\..\..\Compilers\CSharp\Portable\Syntax\LambdaUtilities.cs">
<Link>InternalUtilities\LambdaUtilities.cs</Link>
</Compile>
<Compile Include="UseExpressionBody\Accessors\UseExpressionBodyForAccessorsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Accessors\UseExpressionBodyForAccessorsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Indexers\UseExpressionBodyForIndexersCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Indexers\UseExpressionBodyForIndexersDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Properties\UseExpressionBodyForPropertiesCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Properties\UseExpressionBodyForPropertiesDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Operators\UseExpressionBodyForConversionOperatorsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Operators\UseExpressionBodyForConversionOperatorsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Constructors\UseExpressionBodyForConstructorsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Operators\UseExpressionBodyForOperatorsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Constructors\UseExpressionBodyForConstructorsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Operators\UseExpressionBodyForOperatorsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\AbstractUseExpressionBodyCodeFixProvider.FixAllProvider.cs" />
<Compile Include="AddBraces\CSharpAddBracesCodeFixProvider.cs" />
<Compile Include="AddBraces\CSharpAddBracesDiagnosticAnalyzer.cs" />
<Compile Include="InlineDeclaration\CSharpInlineDeclarationCodeFixProvider.InlineDeclarationFixAllProvider.cs" />
......@@ -362,6 +375,10 @@
<Compile Include="Structure\Providers\SwitchStatementStructureProvider.cs" />
<Compile Include="InlineDeclaration\CSharpInlineDeclarationCodeFixProvider.cs" />
<Compile Include="InlineDeclaration\CSharpInlineDeclarationDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Methods\UseExpressionBodyForMethodsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Methods\UseExpressionBodyForMethodsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\AbstractUseExpressionBodyCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\AbstractUseExpressionBodyDiagnosticAnalyzer.cs" />
<Compile Include="UseObjectInitializer\CSharpUseObjectInitializerCodeFixProvider.cs" />
<Compile Include="UseThrowExpression\CSharpUseThrowExpressionDiagnosticAnalyzer.cs" />
<Compile Include="Structure\CSharpBlockStructureProvider.cs" />
......
......@@ -631,18 +631,37 @@ protected override async Task<GeneratedCode> CreateGeneratedCodeAsync(OperationS
var root = newDocument.Root;
var methodDefinition = root.GetAnnotatedNodes<MethodDeclarationSyntax>(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();
......
......@@ -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<SyntaxToken>("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 (method.Body != null)
{
if (tokenPair.PreviousToken == method.Body.OpenBraceToken &&
tokenPair.NextToken == method.Body.CloseBraceToken)
{
return (location == TriviaLocation.AfterBeginningOfSpan) ?
SpecializedCollections.SingletonEnumerable<SyntaxTrivia>(SyntaxFactory.ElasticMarker) :
SpecializedCollections.EmptyEnumerable<SyntaxTrivia>();
return (location == TriviaLocation.AfterBeginningOfSpan)
? SpecializedCollections.SingletonEnumerable(SyntaxFactory.ElasticMarker)
: SpecializedCollections.EmptyEnumerable<SyntaxTrivia>();
}
}
else
{
if (tokenPair.PreviousToken == method.ExpressionBody.ArrowToken &&
tokenPair.NextToken.GetPreviousToken() == method.SemicolonToken)
{
return (location == TriviaLocation.AfterBeginningOfSpan)
? SpecializedCollections.SingletonEnumerable(SyntaxFactory.ElasticMarker)
: SpecializedCollections.EmptyEnumerable<SyntaxTrivia>();
}
}
var previousTriviaPair = triviaMap.ContainsKey(tokenPair.PreviousToken) ? triviaMap[tokenPair.PreviousToken] : default(LeadingTrailingTriviaPair);
......
// 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<TDeclaration> : CodeFixProvider
where TDeclaration : SyntaxNode
{
private class UseExpressionBodyFixAllProvider : DocumentBasedFixAllProvider
{
private readonly AbstractUseExpressionBodyCodeFixProvider<TDeclaration> _provider;
public UseExpressionBodyFixAllProvider(AbstractUseExpressionBodyCodeFixProvider<TDeclaration> provider)
{
_provider = provider;
}
protected override Task<Document> FixDocumentAsync(Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
=> _provider.FixAllAsync(document, diagnostics, cancellationToken);
}
}
}
\ No newline at end of file
// 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<AccessorDeclarationSyntax>
{
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
// 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<ConstructorDeclarationSyntax>
{
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
......@@ -489,4 +489,10 @@
<data name="Prefer_conditional_delegate_call" xml:space="preserve">
<value>Prefer conditional delegate call</value>
</data>
<data name="Prefer_block_body" xml:space="preserve">
<value>Prefer block body</value>
</data>
<data name="Prefer_expression_body" xml:space="preserve">
<value>Prefer expression body</value>
</data>
</root>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册