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

Merge pull request #17763 from CyrusNajmabadi/expressionBodySingleLine

Add option for 'use expression body for single line'
......@@ -19,12 +19,10 @@ public class EncapsulateFieldTests : AbstractCSharpCodeActionTest
protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspace workspace, TestParameters parameters)
=> new EncapsulateFieldRefactoringProvider();
private static readonly Dictionary<OptionKey, object> AllOptionsOff =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement },
};
private IDictionary<OptionKey, object> AllOptionsOff =>
OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithNoneEnforcement));
internal Task TestAllOptionsOffAsync(
string initialMarkup, string expectedMarkup,
......@@ -168,8 +166,8 @@ void baz()
";
await TestInRegularAndScriptAsync(text, expected,
options: OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, true, NotificationOption.None),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, false, NotificationOption.None)));
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, ExpressionBodyPreference.WhenPossible, NotificationOption.None),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, ExpressionBodyPreference.Never, NotificationOption.None)));
}
[Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)]
......@@ -206,7 +204,7 @@ void baz()
}
";
await TestInRegularAndScriptAsync(text, expected,
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithNoneEnforcement));
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement));
}
[Fact, Trait(Traits.Feature, Traits.Features.EncapsulateField)]
......
......@@ -48,7 +48,7 @@ private static bool NewMethod(bool b)
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractMethod)]
public async Task TestCodeStyle1()
public async Task TestUseExpressionBodyWhenPossible()
{
await TestInRegularAndScriptAsync(
@"class Program
......@@ -69,7 +69,153 @@ static void Main(string[] args)
private static bool NewMethod(bool b) => b != true;
}",
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.TrueWithNoneEnforcement));
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractMethod)]
public async Task TestUseExpressionWhenOnSingleLine_AndIsOnSingleLine()
{
await TestInRegularAndScriptAsync(
@"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, CSharpCodeStyleOptions.WhenOnSingleLineWithNoneEnforcement));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractMethod)]
public async Task TestUseExpressionWhenOnSingleLine_AndIsOnSingleLine2()
{
await TestInRegularAndScriptAsync(
@"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, CSharpCodeStyleOptions.WhenOnSingleLineWithNoneEnforcement));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractMethod)]
public async Task TestUseExpressionWhenOnSingleLine_AndNotIsOnSingleLine()
{
await TestInRegularAndScriptAsync(
@"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)
{
return b !=
true;
}
}",
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.WhenOnSingleLineWithNoneEnforcement));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractMethod)]
public async Task TestUseExpressionWhenOnSingleLine_AndNotIsOnSingleLine2()
{
await TestInRegularAndScriptAsync(
@"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)
{
return b !=/*
*/true;
}
}",
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.WhenOnSingleLineWithNoneEnforcement));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractMethod)]
public async Task TestUseExpressionWhenOnSingleLine_AndNotIsOnSingleLine3()
{
await TestInRegularAndScriptAsync(
@"class Program
{
static void Main(string[] args)
{
bool b = true;
System.Console.WriteLine([|"""" != @""
""|] ? b = true : b = false);
}
}",
@"class Program
{
static void Main(string[] args)
{
bool b = true;
System.Console.WriteLine({|Rename:NewMethod|}() ? b = true : b = false);
}
private static bool NewMethod()
{
return """" != @""
"";
}
}",
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.WhenOnSingleLineWithNoneEnforcement));
}
[WorkItem(540796, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540796")]
......
......@@ -1680,6 +1680,44 @@ public async Task TestCodeStyle10()
}", options: PreferExpressionBodiedProperties);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceMethodWithProperty)]
public async Task TestUseExpressionBodyWhenOnSingleLine_AndIsSingleLine()
{
await TestInRegularAndScriptAsync(
@"class C
{
int [||]GetFoo() { throw e; }
}",
@"class C
{
int Foo => throw e;
}", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.WhenOnSingleLineWithNoneEnforcement));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceMethodWithProperty)]
public async Task TestUseExpressionBodyWhenOnSingleLine_AndIsNotSingleLine()
{
await TestInRegularAndScriptAsync(
@"class C
{
int [||]GetFoo() { throw e +
e; }
}",
@"class C
{
int Foo
{
get
{
throw e +
e;
}
}
}", options: OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.WhenOnSingleLineWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenOnSingleLineWithNoneEnforcement)));
}
private async Task TestWithAllCodeStyleOff(
string initialMarkup, string expectedMarkup,
ParseOptions parseOptions = null, int index = 0,
......@@ -1693,19 +1731,19 @@ public async Task TestCodeStyle10()
}
private IDictionary<OptionKey, object> AllCodeStyleOff =>
OptionsSet(SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement));
OptionsSet(SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithNoneEnforcement));
private IDictionary<OptionKey, object> PreferExpressionBodiedAccessors =>
OptionsSet(SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithSuggestionEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement));
OptionsSet(SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithNoneEnforcement));
private IDictionary<OptionKey, object> PreferExpressionBodiedProperties =>
OptionsSet(SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.TrueWithSuggestionEnforcement));
OptionsSet(SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement));
private IDictionary<OptionKey, object> PreferExpressionBodiedAccessorsAndProperties =>
OptionsSet(SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithSuggestionEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.TrueWithSuggestionEnforcement));
OptionsSet(SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement));
}
}
\ No newline at end of file
......@@ -1326,6 +1326,6 @@ private int GetProp()
}
private IDictionary<OptionKey, object> PreferExpressionBodiedMethods =>
OptionsSet(SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.TrueWithSuggestionEnforcement));
OptionsSet(SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement));
}
}
\ No newline at end of file
......@@ -28,8 +28,9 @@ internal override CompletionProvider CreateCompletionProvider()
protected override void SetWorkspaceOptions(TestWorkspace workspace)
{
workspace.Options = workspace.Options.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement)
.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement);
workspace.Options = workspace.Options
.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement)
.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithNoneEnforcement);
}
#region "CompletionItem tests"
......
......@@ -29,9 +29,10 @@ internal override CompletionProvider CreateCompletionProvider()
protected override void SetWorkspaceOptions(TestWorkspace workspace)
{
workspace.Options = workspace.Options.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithSuggestionEnforcement)
.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.TrueWithSuggestionEnforcement)
.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.TrueWithSuggestionEnforcement);
workspace.Options = workspace.Options
.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement)
.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement)
.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement);
}
[WorkItem(16331, "https://github.com/dotnet/roslyn/issues/16334")]
......
......@@ -115,7 +115,7 @@ class C
{
public static implicit operator C(int v) => throw new NotImplementedException();
}",
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.TrueWithNoneEnforcement));
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement));
}
[WorkItem(774321, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/774321")]
......
......@@ -66,7 +66,7 @@ void Method()
private void Foo() => throw new NotImplementedException();
}",
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.TrueWithNoneEnforcement));
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)]
......
......@@ -47,8 +47,9 @@ public EncapsulateFieldTestState(TestWorkspace workspace)
public static EncapsulateFieldTestState Create(string markup)
{
var workspace = TestWorkspace.CreateCSharp(markup, exportProvider: s_exportProvider);
workspace.Options = workspace.Options.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement)
.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement);
workspace.Options = workspace.Options
.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement)
.WithChangedOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithNoneEnforcement);
return new EncapsulateFieldTestState(workspace);
}
......
......@@ -66,7 +66,7 @@ public C(int v) => this.v = v; void M()
new C(1);
}
}",
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CodeStyleOptions.TrueWithNoneEnforcement));
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement));
}
[Fact, WorkItem(910589, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/910589"), Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
......
......@@ -56,8 +56,57 @@ class Z
{
int a;
public Z(int a) => this . a = a ; }",
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CodeStyleOptions.TrueWithNoneEnforcement));
public Z(int a) => this . a = a ;
}",
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructorFromMembers)]
public async Task TestUseExpressionBodyWhenOnSingleLine_AndIsSingleLine()
{
await TestInRegularAndScriptAsync(
@"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, CSharpCodeStyleOptions.WhenOnSingleLineWithNoneEnforcement));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructorFromMembers)]
public async Task TestUseExpressionBodyWhenOnSingleLine_AndIsNotSingleLine()
{
await TestInRegularAndScriptAsync(
@"using System.Collections.Generic;
class Z
{
[|int a;
int b;|]
}",
@"using System.Collections.Generic;
class Z
{
int a;
int b;
public Z(int a, int b)
{
this . a = a ;
this . b = b ;
}
}",
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CSharpCodeStyleOptions.WhenOnSingleLineWithNoneEnforcement));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructorFromMembers)]
......
......@@ -542,7 +542,7 @@ public override bool Equals(object obj)
public override int GetHashCode() => 165851236 + i.GetHashCode();
}",
index: 1,
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.TrueWithNoneEnforcement));
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateEqualsAndGetHashCode)]
......@@ -1042,7 +1042,7 @@ public override bool Equals(object obj)
chosenSymbols: null,
optionsCallback: options => EnableOption(options, GenerateOperatorsId),
parameters: new TestParameters(
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.TrueWithNoneEnforcement)));
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement)));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateEqualsAndGetHashCode)]
......
......@@ -20,16 +20,14 @@ public partial class ImplementAbstractClassTests : AbstractCSharpDiagnosticProvi
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (null, new CSharpImplementAbstractClassCodeFixProvider());
private static readonly Dictionary<OptionKey, object> AllOptionsOff =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.FalseWithNoneEnforcement },
};
private IDictionary<OptionKey, object> AllOptionsOff =>
OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CSharpCodeStyleOptions.NeverWithNoneEnforcement));
internal Task TestAllOptionsOffAsync(
string initialMarkup, string expectedMarkup,
......@@ -1179,7 +1177,7 @@ class [|T|] : A
class T : A
{
public override void M(int x) => throw new System.NotImplementedException();
}", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.TrueWithNoneEnforcement));
}", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement));
}
[WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")]
......@@ -1203,7 +1201,7 @@ class [|T|] : A
class T : A
{
public override int M => throw new System.NotImplementedException();
}", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.TrueWithNoneEnforcement));
}", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement));
}
[WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")]
......@@ -1234,8 +1232,8 @@ public override int M
}
}
}", options: OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, true, NotificationOption.None),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, false, NotificationOption.None)));
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, ExpressionBodyPreference.WhenPossible, NotificationOption.None),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, ExpressionBodyPreference.Never, NotificationOption.None)));
}
[WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")]
......@@ -1271,8 +1269,8 @@ public override int M
}
}
}", options: OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, true, NotificationOption.None),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, false, NotificationOption.None)));
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, ExpressionBodyPreference.WhenPossible, NotificationOption.None),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, ExpressionBodyPreference.Never, NotificationOption.None)));
}
[WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")]
......@@ -1296,7 +1294,7 @@ class [|T|] : A
class T : A
{
public override int this[int i] => throw new System.NotImplementedException();
}", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.TrueWithNoneEnforcement));
}", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement));
}
[WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")]
......@@ -1327,8 +1325,8 @@ class T : A
}
}
}", options: OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, true, NotificationOption.None),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, false, NotificationOption.None)));
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, ExpressionBodyPreference.WhenPossible, NotificationOption.None),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, ExpressionBodyPreference.Never, NotificationOption.None)));
}
[WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")]
......@@ -1364,8 +1362,8 @@ class T : A
}
}
}", options: OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, true, NotificationOption.None),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, false, NotificationOption.None)));
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, ExpressionBodyPreference.WhenPossible, NotificationOption.None),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, ExpressionBodyPreference.Never, NotificationOption.None)));
}
[WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")]
......@@ -1393,8 +1391,8 @@ public override int M
get => throw new System.NotImplementedException();
}
}", options: OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, false, NotificationOption.None),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, true, NotificationOption.None)));
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, ExpressionBodyPreference.Never, NotificationOption.None),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, ExpressionBodyPreference.WhenPossible, NotificationOption.None)));
}
[WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")]
......@@ -1421,7 +1419,7 @@ public override int M
{
set => throw new System.NotImplementedException();
}
}", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithNoneEnforcement));
}", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement));
}
[WorkItem(581500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581500")]
......@@ -1449,7 +1447,7 @@ public override int M
get => throw new System.NotImplementedException();
set => throw new System.NotImplementedException();
}
}", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithNoneEnforcement));
}", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement));
}
[WorkItem(15387, "https://github.com/dotnet/roslyn/issues/15387")]
......
......@@ -7,7 +7,6 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.ImplementInterface;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.ImplementType;
......@@ -22,38 +21,32 @@ public partial class ImplementInterfaceTests : AbstractCSharpDiagnosticProviderB
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (null, new CSharpImplementInterfaceCodeFixProvider());
private static readonly Dictionary<OptionKey, object> s_allOptionsOff =
new Dictionary<OptionKey, object>
{
{ 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<OptionKey, object> s_allOptionsOn =
new Dictionary<OptionKey, object>
{
{ 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<OptionKey, object> s_accessorOptionsOn =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.FalseWithNoneEnforcement }
};
private IDictionary<OptionKey, object> AllOptionsOff =>
OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CSharpCodeStyleOptions.NeverWithNoneEnforcement));
private IDictionary<OptionKey, object> AllOptionsOn =>
OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement));
private IDictionary<OptionKey, object> AccessorOptionsOn =>
OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CSharpCodeStyleOptions.NeverWithNoneEnforcement));
internal async Task TestWithAllCodeStyleOptionsOffAsync(
string initialMarkup, string expectedMarkup,
......@@ -61,7 +54,7 @@ internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProvider
ParseOptions parseOptions = null)
{
await TestAsync(initialMarkup, expectedMarkup, parseOptions, null,
index, ignoreTrivia, options: s_allOptionsOff);
index, ignoreTrivia, options: AllOptionsOff);
}
internal async Task TestWithAllCodeStyleOptionsOnAsync(
......@@ -70,7 +63,7 @@ internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProvider
ParseOptions parseOptions = null)
{
await TestAsync(initialMarkup, expectedMarkup, parseOptions, null,
index, compareTokens, options: s_allOptionsOn);
index, compareTokens, options: AllOptionsOn);
}
internal async Task TestWithAccessorCodeStyleOptionsOnAsync(
......@@ -79,7 +72,7 @@ internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProvider
ParseOptions parseOptions = null)
{
await TestAsync(initialMarkup, expectedMarkup, parseOptions, null,
index, compareTokens, options: s_accessorOptionsOn);
index, compareTokens, options: AccessorOptionsOn);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)]
......
......@@ -21,27 +21,20 @@ internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProvider
=> (new UseExpressionBodyForAccessorsDiagnosticAnalyzer(),
new UseExpressionBodyForAccessorsCodeFixProvider());
private static readonly Dictionary<OptionKey, object> UseExpressionBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithSuggestionEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.FalseWithSuggestionEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.FalseWithSuggestionEnforcement }
};
private IDictionary<OptionKey, object> UseExpressionBody =>
OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithSuggestionEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CSharpCodeStyleOptions.NeverWithSuggestionEnforcement));
private static readonly Dictionary<OptionKey, object> UseExpressionBodyIncludingPropertiesAndIndexers =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.TrueWithSuggestionEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CodeStyleOptions.TrueWithSuggestionEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.TrueWithSuggestionEnforcement }
};
private IDictionary<OptionKey, object> UseExpressionBodyIncludingPropertiesAndIndexers =>
OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement));
private static readonly Dictionary<OptionKey, object> UseBlockBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithSuggestionEnforcement }
};
private IDictionary<OptionKey, object> UseBlockBody =>
Option(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithSuggestionEnforcement);
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBody1()
......
......@@ -20,17 +20,11 @@ internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProvider
=> (new UseExpressionBodyForConstructorsDiagnosticAnalyzer(),
new UseExpressionBodyForConstructorsCodeFixProvider());
private static readonly Dictionary<OptionKey, object> UseExpressionBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CodeStyleOptions.TrueWithNoneEnforcement }
};
private IDictionary<OptionKey, object> UseExpressionBody =>
Option(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement);
private static readonly Dictionary<OptionKey, object> UseBlockBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CodeStyleOptions.FalseWithNoneEnforcement }
};
private IDictionary<OptionKey, object> UseBlockBody =>
Option(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CSharpCodeStyleOptions.NeverWithNoneEnforcement);
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBody1()
......
......@@ -20,17 +20,11 @@ internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProvider
=> (new UseExpressionBodyForConversionOperatorsDiagnosticAnalyzer(),
new UseExpressionBodyForConversionOperatorsCodeFixProvider());
private static readonly Dictionary<OptionKey, object> UseExpressionBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.TrueWithNoneEnforcement }
};
private IDictionary<OptionKey, object> UseExpressionBody =>
Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement);
private static readonly Dictionary<OptionKey, object> UseBlockBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.FalseWithNoneEnforcement }
};
private IDictionary<OptionKey, object> UseBlockBody =>
Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CSharpCodeStyleOptions.NeverWithNoneEnforcement);
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBody1()
......
......@@ -19,27 +19,20 @@ public class UseExpressionBodyForIndexersTests : AbstractCSharpDiagnosticProvide
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (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 }
};
private IDictionary<OptionKey, object> UseExpressionBody =>
OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement));
private IDictionary<OptionKey, object> UseBlockBody =>
OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement));
private IDictionary<OptionKey, object> UseBlockBodyExceptAccessor =>
OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement));
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBody1()
......
......@@ -19,17 +19,53 @@ public class UseExpressionBodyForMethodsTests : AbstractCSharpDiagnosticProvider
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (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 }
};
private IDictionary<OptionKey, object> UseExpressionBody =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement);
private IDictionary<OptionKey, object> UseBlockBody =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.NeverWithNoneEnforcement);
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public void TestOptionSerialization1()
{
// Verify that bool-options can migrate to ExpressionBodyPreference-options.
var option = new CodeStyleOption<bool>(false, NotificationOption.None);
var serialized = option.ToXElement();
var deserialized = CodeStyleOption<ExpressionBodyPreference>.FromXElement(serialized);
Assert.Equal(ExpressionBodyPreference.Never, deserialized.Value);
option = new CodeStyleOption<bool>(true, NotificationOption.None);
serialized = option.ToXElement();
deserialized = CodeStyleOption<ExpressionBodyPreference>.FromXElement(serialized);
Assert.Equal(ExpressionBodyPreference.WhenPossible, deserialized.Value);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public void TestOptionSerialization2()
{
// Verify that ExpressionBodyPreference-options can migrate to bool-options.
var option = new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None);
var serialized = option.ToXElement();
var deserialized = CodeStyleOption<bool>.FromXElement(serialized);
Assert.Equal(false, deserialized.Value);
option = new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None);
serialized = option.ToXElement();
deserialized = CodeStyleOption<bool>.FromXElement(serialized);
Assert.Equal(true, deserialized.Value);
// This new values can't actually translate back to a bool. So we'll just get the default
// value for this option.
option = new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenOnSingleLine, NotificationOption.None);
serialized = option.ToXElement();
deserialized = CodeStyleOption<bool>.FromXElement(serialized);
Assert.Equal(default(bool), deserialized.Value);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBody1()
......
......@@ -20,17 +20,11 @@ internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProvider
=> (new UseExpressionBodyForOperatorsDiagnosticAnalyzer(),
new UseExpressionBodyForOperatorsCodeFixProvider());
private static readonly Dictionary<OptionKey, object> UseExpressionBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.TrueWithNoneEnforcement }
};
private IDictionary<OptionKey, object> UseExpressionBody =>
Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement);
private static readonly Dictionary<OptionKey, object> UseBlockBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.FalseWithNoneEnforcement }
};
private IDictionary<OptionKey, object> UseBlockBody =>
Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CSharpCodeStyleOptions.NeverWithNoneEnforcement);
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBody1()
......
......@@ -19,26 +19,20 @@ public class UseExpressionBodyForPropertiesTests : AbstractCSharpDiagnosticProvi
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (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 }
};
private IDictionary<OptionKey, object> UseExpressionBody =>
OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement));
private IDictionary<OptionKey, object> UseBlockBody =>
OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement));
private IDictionary<OptionKey, object> UseBlockBodyExceptAccessor =>
OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithNoneEnforcement));
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBody1()
......
......@@ -666,8 +666,8 @@ public async Task AddIndexer2()
getStatements: "return String.Empty;",
isIndexer: true,
options: new Dictionary<OptionKey, object> {
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.FalseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CSharpCodeStyleOptions.NeverWithNoneEnforcement },
});
}
......
......@@ -550,40 +550,40 @@ protected static ImmutableArray<CodeAction> FlattenActions(ImmutableArray<CodeAc
: ImmutableArray.Create(a)).ToImmutableArray();
}
protected (OptionKey, object) SingleOption(Option<bool> option, bool enabled)
protected (OptionKey, object) SingleOption<T>(Option<T> option, T enabled)
=> (new OptionKey(option), enabled);
protected (OptionKey, object) SingleOption<T>(PerLanguageOption<T> option, T value)
=> (new OptionKey(option, this.GetLanguage()), value);
protected (OptionKey, object) SingleOption(Option<CodeStyleOption<bool>> option, bool enabled, NotificationOption notification)
=> SingleOption(option, new CodeStyleOption<bool>(enabled, notification));
protected (OptionKey, object) SingleOption<T>(Option<CodeStyleOption<T>> option, T enabled, NotificationOption notification)
=> SingleOption(option, new CodeStyleOption<T>(enabled, notification));
protected (OptionKey, object) SingleOption(Option<CodeStyleOption<bool>> option, CodeStyleOption<bool> codeStyle)
protected (OptionKey, object) SingleOption<T>(Option<CodeStyleOption<T>> option, CodeStyleOption<T> codeStyle)
=> (new OptionKey(option), codeStyle);
protected (OptionKey, object) SingleOption(PerLanguageOption<CodeStyleOption<bool>> option, bool enabled, NotificationOption notification)
=> SingleOption(option, new CodeStyleOption<bool>(enabled, notification));
protected (OptionKey, object) SingleOption<T>(PerLanguageOption<CodeStyleOption<T>> option, T enabled, NotificationOption notification)
=> SingleOption(option, new CodeStyleOption<T>(enabled, notification));
protected (OptionKey, object) SingleOption(PerLanguageOption<CodeStyleOption<bool>> option, CodeStyleOption<bool> codeStyle)
protected (OptionKey, object) SingleOption<T>(PerLanguageOption<CodeStyleOption<T>> option, CodeStyleOption<T> codeStyle)
=> SingleOption(option, codeStyle, language: GetLanguage());
protected static (OptionKey, object) SingleOption(PerLanguageOption<CodeStyleOption<bool>> option, CodeStyleOption<bool> codeStyle, string language)
protected static (OptionKey, object) SingleOption<T>(PerLanguageOption<CodeStyleOption<T>> option, CodeStyleOption<T> codeStyle, string language)
=> (new OptionKey(option, language), codeStyle);
protected IDictionary<OptionKey, object> Option(Option<CodeStyleOption<bool>> option, bool enabled, NotificationOption notification)
protected IDictionary<OptionKey, object> Option<T>(Option<CodeStyleOption<T>> option, T enabled, NotificationOption notification)
=> OptionsSet(SingleOption(option, enabled, notification));
protected IDictionary<OptionKey, object> Option(Option<CodeStyleOption<bool>> option, CodeStyleOption<bool> codeStyle)
protected IDictionary<OptionKey, object> Option<T>(Option<CodeStyleOption<T>> option, CodeStyleOption<T> codeStyle)
=> OptionsSet(SingleOption(option, codeStyle));
protected IDictionary<OptionKey, object> Option(PerLanguageOption<CodeStyleOption<bool>> option, bool enabled, NotificationOption notification)
protected IDictionary<OptionKey, object> Option<T>(PerLanguageOption<CodeStyleOption<T>> option, T enabled, NotificationOption notification)
=> OptionsSet(SingleOption(option, enabled, notification));
protected IDictionary<OptionKey, object> Option<T>(PerLanguageOption<T> option, T value)
=> OptionsSet(SingleOption(option, value));
protected IDictionary<OptionKey, object> Option(PerLanguageOption<CodeStyleOption<bool>> option, CodeStyleOption<bool> codeStyle)
protected IDictionary<OptionKey, object> Option<T>(PerLanguageOption<CodeStyleOption<T>> option, CodeStyleOption<T> codeStyle)
=> OptionsSet(SingleOption(option, codeStyle));
protected static IDictionary<OptionKey, object> OptionsSet(
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Option Strict Off
Option Strict On
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.CodeFixes.PreferFrameworkType
......@@ -13,8 +13,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.Prefer
Partial Public Class PreferFrameworkTypeTests
Inherits AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest
Private ReadOnly onWithInfo = New CodeStyleOption(Of Boolean)(True, NotificationOption.Suggestion)
Private ReadOnly offWithInfo = New CodeStyleOption(Of Boolean)(False, NotificationOption.Suggestion)
Private ReadOnly onWithInfo As New CodeStyleOption(Of Boolean)(True, NotificationOption.Suggestion)
Private ReadOnly offWithInfo As New CodeStyleOption(Of Boolean)(False, NotificationOption.Suggestion)
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As (DiagnosticAnalyzer, CodeFixProvider)
Return (New VisualBasicPreferFrameworkTypeDiagnosticAnalyzer(),
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Option Strict Off
Option Strict On
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.CodeStyle
......@@ -43,8 +43,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.Simpli
SingleOption(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration, Me.offWithNone, language))
End Function
Private ReadOnly onWithError = New CodeStyleOption(Of Boolean)(True, NotificationOption.Error)
Private ReadOnly offWithNone = New CodeStyleOption(Of Boolean)(False, NotificationOption.None)
Private ReadOnly onWithError As New CodeStyleOption(Of Boolean)(True, NotificationOption.Error)
Private ReadOnly offWithNone As New CodeStyleOption(Of Boolean)(False, NotificationOption.None)
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)>
Public Async Function TestGenericNames() As Task
......@@ -2313,7 +2313,7 @@ End Module
</Code>
Dim parameters As New TestParameters()
Using workspace = CreateWorkspaceFromFile(source, parameters)
Using workspace = CreateWorkspaceFromFile(source.ToString(), parameters)
Dim diagnostics = (Await GetDiagnosticsAsync(workspace, parameters)).Where(Function(d) d.Id = IDEDiagnosticIds.SimplifyMemberAccessDiagnosticId)
Assert.Equal(1, diagnostics.Count)
End Using
......@@ -2329,7 +2329,7 @@ End Module
</Code>
Dim parameters2 As New TestParameters()
Using workspace = CreateWorkspaceFromFile(source, parameters2)
Using workspace = CreateWorkspaceFromFile(source.ToString(), parameters2)
workspace.ApplyOptions(PreferIntrinsicPredefinedTypeEverywhere())
Dim diagnostics = (Await GetDiagnosticsAsync(workspace, parameters2)).Where(Function(d) d.Id = IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId)
Assert.Equal(1, diagnostics.Count)
......@@ -2347,7 +2347,7 @@ End Module
</Code>
Dim parameters3 As New TestParameters()
Using workspace = CreateWorkspaceFromFile(source, parameters3)
Using workspace = CreateWorkspaceFromFile(source.ToString(), parameters3)
Dim diagnostics = (Await GetDiagnosticsAsync(workspace, parameters3)).Where(Function(d) d.Id = IDEDiagnosticIds.RemoveQualificationDiagnosticId)
Assert.Equal(1, diagnostics.Count)
End Using
......
......@@ -5,6 +5,7 @@
using System.Composition;
using System.Linq;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
......@@ -79,8 +80,8 @@ public void RemoveSetMethod(SyntaxEditor editor, SyntaxNode setMethodDeclaration
documentOptions, parseOptions, semanticModel,
generator, getAndSetMethods, propertyName, nameChanged);
var preferExpressionBody = documentOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties).Value;
if (preferExpressionBody)
var expressionBodyPreference = documentOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties).Value;
if (expressionBodyPreference != ExpressionBodyPreference.Never)
{
if (propertyDeclaration.AccessorList?.Accessors.Count == 1 &&
propertyDeclaration.AccessorList?.Accessors[0].Kind() == SyntaxKind.GetAccessorDeclaration)
......@@ -93,7 +94,9 @@ public void RemoveSetMethod(SyntaxEditor editor, SyntaxNode setMethodDeclaration
.WithAccessorList(null);
}
else if (getAccessor.Body != null &&
getAccessor.Body.TryConvertToExpressionBody(parseOptions, out var arrowExpression, out var semicolonToken))
getAccessor.Body.TryConvertToExpressionBody(
parseOptions, expressionBodyPreference,
out var arrowExpression, out var semicolonToken))
{
return propertyDeclaration.WithExpressionBody(arrowExpression)
.WithSemicolonToken(semicolonToken)
......@@ -174,11 +177,12 @@ private SyntaxToken GetPropertyName(SyntaxToken identifier, string propertyName,
DocumentOptionSet documentOptions, ParseOptions parseOptions,
AccessorDeclarationSyntax accessorDeclaration)
{
var preferExpressionBody = documentOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value;
if (accessorDeclaration?.Body != null && preferExpressionBody)
var expressionBodyPreference = documentOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value;
if (accessorDeclaration?.Body != null && expressionBodyPreference != ExpressionBodyPreference.Never)
{
if (accessorDeclaration.Body.TryConvertToExpressionBody(
parseOptions, out var arrowExpression, out var semicolonToken))
parseOptions, expressionBodyPreference,
out var arrowExpression, out var semicolonToken))
{
return accessorDeclaration.WithBody(null)
.WithExpressionBody(arrowExpression)
......@@ -186,7 +190,7 @@ private SyntaxToken GetPropertyName(SyntaxToken identifier, string propertyName,
.WithAdditionalAnnotations(Formatter.Annotation);
}
}
else if (accessorDeclaration?.ExpressionBody != null && !preferExpressionBody)
else if (accessorDeclaration?.ExpressionBody != null && expressionBodyPreference == ExpressionBodyPreference.Never)
{
var block = accessorDeclaration.ExpressionBody.ConvertToBlock(
accessorDeclaration.SemicolonToken,
......
......@@ -5,6 +5,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
......@@ -185,11 +186,11 @@ public override SyntaxNode GetPropertyDeclaration(SyntaxToken token)
DocumentOptionSet documentOptions, ParseOptions parseOptions,
MethodDeclarationSyntax methodDeclaration, bool createReturnStatementForExpression)
{
var preferExpressionBody = documentOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods).Value;
if (methodDeclaration?.Body != null && preferExpressionBody)
var expressionBodyPreference = documentOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods).Value;
if (methodDeclaration?.Body != null && expressionBodyPreference != ExpressionBodyPreference.Never)
{
if (methodDeclaration.Body.TryConvertToExpressionBody(
parseOptions, out var arrowExpression, out var semicolonToken))
parseOptions, expressionBodyPreference, out var arrowExpression, out var semicolonToken))
{
return methodDeclaration.WithBody(null)
.WithExpressionBody(arrowExpression)
......@@ -197,7 +198,7 @@ public override SyntaxNode GetPropertyDeclaration(SyntaxToken token)
.WithAdditionalAnnotations(Formatter.Annotation);
}
}
else if (methodDeclaration?.ExpressionBody != null && !preferExpressionBody)
else if (methodDeclaration?.ExpressionBody != null && expressionBodyPreference == ExpressionBodyPreference.Never)
{
var block = methodDeclaration?.ExpressionBody.ConvertToBlock(
methodDeclaration.SemicolonToken, createReturnStatementForExpression);
......
......@@ -23,7 +23,7 @@ internal abstract partial class AbstractUseExpressionBodyCodeFixProvider<TDeclar
SyntaxEditorBasedCodeFixProvider
where TDeclaration : SyntaxNode
{
private readonly Option<CodeStyleOption<bool>> _option;
private readonly Option<CodeStyleOption<ExpressionBodyPreference>> _option;
private readonly string _useExpressionBodyTitle;
private readonly string _useBlockBodyTitle;
......@@ -31,7 +31,7 @@ internal abstract partial class AbstractUseExpressionBodyCodeFixProvider<TDeclar
protected AbstractUseExpressionBodyCodeFixProvider(
string diagnosticId,
Option<CodeStyleOption<bool>> option,
Option<CodeStyleOption<ExpressionBodyPreference>> option,
string useExpressionBodyTitle,
string useBlockBodyTitle)
{
......@@ -90,7 +90,7 @@ private TDeclaration Update(TDeclaration declaration, OptionSet options)
if (preferExpressionBody)
{
GetBody(declaration).TryConvertToExpressionBody(declaration.SyntaxTree.Options,
out var expressionBody, out var semicolonToken);
ExpressionBodyPreference.WhenPossible, out var expressionBody, out var semicolonToken);
var trailingTrivia = semicolonToken.TrailingTrivia
.Where(t => t.Kind() != SyntaxKind.EndOfLineTrivia)
......@@ -141,10 +141,10 @@ private TDeclaration Update(TDeclaration declaration, OptionSet options)
var expressionBody = GetExpressionBody(declaration);
var semicolonToken = GetSemicolonToken(declaration);
var preferExpressionBodiedAccessors = options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value;
var expressionBodyPreference = options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value;
AccessorDeclarationSyntax accessor;
if (preferExpressionBodiedAccessors)
if (expressionBodyPreference != ExpressionBodyPreference.Never)
{
accessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithExpressionBody(expressionBody)
......
......@@ -3,6 +3,7 @@
using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -15,7 +16,7 @@ internal abstract class AbstractUseExpressionBodyDiagnosticAnalyzer<TDeclaration
where TDeclaration : SyntaxNode
{
private readonly ImmutableArray<SyntaxKind> _syntaxKinds;
private readonly Option<CodeStyleOption<bool>> _option;
private readonly Option<CodeStyleOption<ExpressionBodyPreference>> _option;
private readonly LocalizableString _expressionBodyTitle;
private readonly LocalizableString _blockBodyTitle;
......@@ -26,7 +27,7 @@ internal abstract class AbstractUseExpressionBodyDiagnosticAnalyzer<TDeclaration
LocalizableString expressionBodyTitle,
LocalizableString blockBodyTitle,
ImmutableArray<SyntaxKind> syntaxKinds,
Option<CodeStyleOption<bool>> option)
Option<CodeStyleOption<ExpressionBodyPreference>> option)
: base(diagnosticId, expressionBodyTitle)
{
_syntaxKinds = syntaxKinds;
......@@ -85,32 +86,42 @@ internal virtual Diagnostic AnalyzeSyntax(OptionSet optionSet, TDeclaration decl
{
// They don't have an expression body. See if we can convert into one.
// If so, offer the conversion (with the proper severity depending on their options).
if (!GetBody(declaration).TryConvertToExpressionBody(declaration.SyntaxTree.Options,
out expressionBody, out var semicolonToken))
var options = declaration.SyntaxTree.Options;
var body = GetBody(declaration);
if (body.TryConvertToExpressionBody(options, ExpressionBodyPreference.WhenOnSingleLine, out var expressionWhenOnSingleLine, out var semicolonWhenOnSingleLine))
{
// Not a block that can be converted to an expression.
return null;
// See if it can be converted to an expression and is on a single line. If so,
// we'll show the diagnostic if either 'use expression body' preference is set.
var severity =
preferExpressionBodiedOption.Value == ExpressionBodyPreference.WhenOnSingleLine || preferExpressionBodiedOption.Value == ExpressionBodyPreference.WhenPossible
? preferExpressionBodiedOption.Notification.Value
: DiagnosticSeverity.Hidden;
return GetDiagnostic(declaration, severity);
}
var severity = preferExpressionBodiedOption.Value
? preferExpressionBodiedOption.Notification.Value
: DiagnosticSeverity.Hidden;
var location = severity == DiagnosticSeverity.Hidden
? declaration.GetLocation()
: GetBody(declaration).Statements[0].GetLocation();
if (body.TryConvertToExpressionBody(options, ExpressionBodyPreference.WhenPossible, out var expressionWhenPossible, out var semicolonWhenPossible))
{
// It wasn't an expression that was on a single line. But it was something we
// could convert to an expression body. We'll show the diagnostic only if
// the option to report when possible is set.
var severity =
preferExpressionBodiedOption.Value == ExpressionBodyPreference.WhenPossible
? preferExpressionBodiedOption.Notification.Value
: DiagnosticSeverity.Hidden;
return GetDiagnostic(declaration, severity);
}
var additionalLocations = ImmutableArray.Create(declaration.GetLocation());
return Diagnostic.Create(
CreateDescriptorWithTitle(_expressionBodyTitle, severity, GetCustomTags(severity)),
location, additionalLocations: additionalLocations);
// Can't be converted.
return null;
}
else
{
// They have an expression body. These can always be converted into blocks.
// Offer to convert this to a block, with the appropriate severity based
// on their options.
var severity = preferExpressionBodiedOption.Value
var severity = preferExpressionBodiedOption.Value != ExpressionBodyPreference.Never
? DiagnosticSeverity.Hidden
: preferExpressionBodiedOption.Notification.Value;
......@@ -125,6 +136,18 @@ internal virtual Diagnostic AnalyzeSyntax(OptionSet optionSet, TDeclaration decl
}
}
private Diagnostic GetDiagnostic(TDeclaration declaration, DiagnosticSeverity severity)
{
var location = severity == DiagnosticSeverity.Hidden
? declaration.GetLocation()
: GetBody(declaration).Statements[0].GetLocation();
var additionalLocations = ImmutableArray.Create(declaration.GetLocation());
return Diagnostic.Create(
CreateDescriptorWithTitle(_expressionBodyTitle, severity, GetCustomTags(severity)),
location, additionalLocations: additionalLocations);
}
private static string[] GetCustomTags(DiagnosticSeverity severity)
=> severity == DiagnosticSeverity.Hidden
? new[] { WellKnownDiagnosticTags.NotConfigurable }
......
......@@ -609,6 +609,15 @@ internal class CSharpVSResources {
}
}
/// <summary>
/// Looks up a localized string similar to Never.
/// </summary>
internal static string Never {
get {
return ResourceManager.GetString("Never", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Never add new line on enter.
/// </summary>
......@@ -1221,6 +1230,24 @@ internal class CSharpVSResources {
}
}
/// <summary>
/// Looks up a localized string similar to When on single line.
/// </summary>
internal static string When_on_single_line {
get {
return ResourceManager.GetString("When_on_single_line", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to When possible.
/// </summary>
internal static string When_possible {
get {
return ResourceManager.GetString("When_possible", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to When variable type is apparent.
/// </summary>
......
......@@ -507,4 +507,13 @@
<data name="Automatically_format_when_typing" xml:space="preserve">
<value>Automatically format when typing</value>
</data>
<data name="Never" xml:space="preserve">
<value>Never</value>
</data>
<data name="When_on_single_line" xml:space="preserve">
<value>When on single line</value>
</data>
<data name="When_possible" xml:space="preserve">
<value>When possible</value>
</data>
</root>
\ No newline at end of file
......@@ -771,14 +771,14 @@ private int GetBooleanOption(PerLanguageOption<bool?> key)
return option.Value ? 1 : 0;
}
private string GetXmlOption(Option<CodeStyleOption<bool>> option)
private string GetXmlOption<T>(Option<CodeStyleOption<T>> option)
{
return _workspace.Options.GetOption(option).ToXElement().ToString();
}
private void SetBooleanOption(PerLanguageOption<bool?> key, int value)
{
bool? boolValue = (value < 0) ? (bool?)null : (value > 0);
var boolValue = (value < 0) ? (bool?)null : (value > 0);
_workspace.Options = _workspace.Options.WithChangedOption(key, LanguageNames.CSharp, boolValue);
}
......@@ -787,9 +787,9 @@ private string GetXmlOption(PerLanguageOption<CodeStyleOption<bool>> option)
return _workspace.Options.GetOption(option, LanguageNames.CSharp).ToXElement().ToString();
}
private void SetXmlOption(Option<CodeStyleOption<bool>> option, string value)
private void SetXmlOption<T>(Option<CodeStyleOption<T>> option, string value)
{
var convertedValue = CodeStyleOption<bool>.FromXElement(XElement.Parse(value));
var convertedValue = CodeStyleOption<T>.FromXElement(XElement.Parse(value));
_workspace.Options = _workspace.Options.WithChangedOption(option, convertedValue);
}
......
......@@ -671,49 +671,93 @@ internal StyleViewModel(OptionSet optionSet, IServiceProvider serviceProvider) :
new CodeStylePreference(CSharpVSResources.Prefer_explicit_type, isChecked: false),
};
var codeBlockPreferences = new List<CodeStylePreference>
{
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));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.QualifyEventAccess, CSharpVSResources.Qualify_event_access_with_this, s_eventDeclarationPreviewTrue, s_eventDeclarationPreviewFalse, this, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions.QualifyFieldAccess, CSharpVSResources.Qualify_field_access_with_this, s_fieldDeclarationPreviewTrue, s_fieldDeclarationPreviewFalse, this, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions.QualifyPropertyAccess, CSharpVSResources.Qualify_property_access_with_this, s_propertyDeclarationPreviewTrue, s_propertyDeclarationPreviewFalse, this, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions.QualifyMethodAccess, CSharpVSResources.Qualify_method_access_with_this, s_methodDeclarationPreviewTrue, s_methodDeclarationPreviewFalse, this, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions.QualifyEventAccess, CSharpVSResources.Qualify_event_access_with_this, s_eventDeclarationPreviewTrue, s_eventDeclarationPreviewFalse, this, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences));
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));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration, ServicesVSResources.For_locals_parameters_and_members, s_intrinsicPreviewDeclarationTrue, s_intrinsicPreviewDeclarationFalse, this, optionSet, predefinedTypesGroupTitle, predefinedTypesPreferences));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(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));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, CSharpVSResources.For_built_in_types, s_varForIntrinsicsPreviewTrue, s_varForIntrinsicsPreviewFalse, this, optionSet, varGroupTitle, typeStylePreferences));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, CSharpVSResources.When_variable_type_is_apparent, s_varWhereApparentPreviewTrue, s_varWhereApparentPreviewFalse, this, optionSet, varGroupTitle, typeStylePreferences));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, CSharpVSResources.Elsewhere, s_varWherePossiblePreviewTrue, s_varWherePossiblePreviewFalse, this, optionSet, varGroupTitle, typeStylePreferences));
// Code block
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferBraces, ServicesVSResources.Prefer_braces, s_preferBraces, s_preferBraces, this, optionSet, codeBlockPreferencesGroupTitle));
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));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferBraces, ServicesVSResources.Prefer_braces, s_preferBraces, s_preferBraces, this, optionSet, codeBlockPreferencesGroupTitle));
// Expression preferences
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferObjectInitializer, ServicesVSResources.Prefer_object_initializer, s_preferObjectInitializer, s_preferObjectInitializer, this, optionSet, expressionPreferencesGroupTitle));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferCollectionInitializer, ServicesVSResources.Prefer_collection_initializer, s_preferCollectionInitializer, s_preferCollectionInitializer, this, optionSet, expressionPreferencesGroupTitle));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferPatternMatchingOverIsWithCastCheck, CSharpVSResources.Prefer_pattern_matching_over_is_with_cast_check, s_preferPatternMatchingOverIsWithCastCheck, s_preferPatternMatchingOverIsWithCastCheck, this, optionSet, expressionPreferencesGroupTitle));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferPatternMatchingOverAsWithNullCheck, CSharpVSResources.Prefer_pattern_matching_over_as_with_null_check, s_preferPatternMatchingOverAsWithNullCheck, s_preferPatternMatchingOverAsWithNullCheck, this, optionSet, expressionPreferencesGroupTitle));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferExplicitTupleNames, ServicesVSResources.Prefer_explicit_tuple_name, s_preferExplicitTupleName, s_preferExplicitTupleName, this, optionSet, expressionPreferencesGroupTitle));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions.PreferObjectInitializer, ServicesVSResources.Prefer_object_initializer, s_preferObjectInitializer, s_preferObjectInitializer, this, optionSet, expressionPreferencesGroupTitle));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions.PreferCollectionInitializer, ServicesVSResources.Prefer_collection_initializer, s_preferCollectionInitializer, s_preferCollectionInitializer, this, optionSet, expressionPreferencesGroupTitle));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferPatternMatchingOverIsWithCastCheck, CSharpVSResources.Prefer_pattern_matching_over_is_with_cast_check, s_preferPatternMatchingOverIsWithCastCheck, s_preferPatternMatchingOverIsWithCastCheck, this, optionSet, expressionPreferencesGroupTitle));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferPatternMatchingOverAsWithNullCheck, CSharpVSResources.Prefer_pattern_matching_over_as_with_null_check, s_preferPatternMatchingOverAsWithNullCheck, s_preferPatternMatchingOverAsWithNullCheck, this, optionSet, expressionPreferencesGroupTitle));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions.PreferExplicitTupleNames, ServicesVSResources.Prefer_explicit_tuple_name, s_preferExplicitTupleName, s_preferExplicitTupleName, this, optionSet, expressionPreferencesGroupTitle));
AddExpressionBodyOptions(optionSet, expressionPreferencesGroupTitle);
// Variable preferences
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferInlinedVariableDeclaration, ServicesVSResources.Prefer_inlined_variable_declaration, s_preferInlinedVariableDeclaration, s_preferInlinedVariableDeclaration, this, optionSet, variablePreferencesGroupTitle));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions.PreferInlinedVariableDeclaration, ServicesVSResources.Prefer_inlined_variable_declaration, s_preferInlinedVariableDeclaration, s_preferInlinedVariableDeclaration, this, optionSet, variablePreferencesGroupTitle));
// Null preferences.
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));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferCoalesceExpression, ServicesVSResources.Prefer_coalesce_expression, s_preferCoalesceExpression, s_preferCoalesceExpression, this, optionSet, nullCheckingGroupTitle));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferNullPropagation, ServicesVSResources.Prefer_null_propagation, s_preferNullPropagation, s_preferNullPropagation, this, optionSet, nullCheckingGroupTitle));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions.PreferThrowExpression, CSharpVSResources.Prefer_throw_expression, s_preferThrowExpression, s_preferThrowExpression, this, optionSet, nullCheckingGroupTitle));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferConditionalDelegateCall, CSharpVSResources.Prefer_conditional_delegate_call, s_preferConditionalDelegateCall, s_preferConditionalDelegateCall, this, optionSet, nullCheckingGroupTitle));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions.PreferCoalesceExpression, ServicesVSResources.Prefer_coalesce_expression, s_preferCoalesceExpression, s_preferCoalesceExpression, this, optionSet, nullCheckingGroupTitle));
CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions.PreferNullPropagation, ServicesVSResources.Prefer_null_propagation, s_preferNullPropagation, s_preferNullPropagation, this, optionSet, nullCheckingGroupTitle));
}
private void AddExpressionBodyOptions(OptionSet optionSet, string expressionPreferencesGroupTitle)
{
var expressionBodyPreferences = new List<CodeStylePreference>
{
new CodeStylePreference(CSharpVSResources.Never, isChecked: false),
new CodeStylePreference(CSharpVSResources.When_possible, isChecked: false),
new CodeStylePreference(CSharpVSResources.When_on_single_line, isChecked: false),
};
var enumValues = new[] { ExpressionBodyPreference.Never, ExpressionBodyPreference.WhenPossible, ExpressionBodyPreference.WhenOnSingleLine };
CodeStyleItems.Add(new EnumCodeStyleOptionViewModel<ExpressionBodyPreference>(
CSharpCodeStyleOptions.PreferExpressionBodiedMethods,
ServicesVSResources.Use_expression_body_for_methods,
enumValues,
new[] { s_preferBlockBodyForMethods, s_preferExpressionBodyForMethods, s_preferExpressionBodyForMethods },
this, optionSet, expressionPreferencesGroupTitle, expressionBodyPreferences));
CodeStyleItems.Add(new EnumCodeStyleOptionViewModel<ExpressionBodyPreference>(
CSharpCodeStyleOptions.PreferExpressionBodiedConstructors,
ServicesVSResources.Use_expression_body_for_constructors,
enumValues,
new[] { s_preferBlockBodyForConstructors, s_preferExpressionBodyForConstructors, s_preferExpressionBodyForConstructors },
this, optionSet, expressionPreferencesGroupTitle, expressionBodyPreferences));
CodeStyleItems.Add(new EnumCodeStyleOptionViewModel<ExpressionBodyPreference>(
CSharpCodeStyleOptions.PreferExpressionBodiedOperators,
ServicesVSResources.Use_expression_body_for_operators,
enumValues,
new[] { s_preferBlockBodyForOperators, s_preferExpressionBodyForOperators, s_preferExpressionBodyForOperators },
this, optionSet, expressionPreferencesGroupTitle, expressionBodyPreferences));
CodeStyleItems.Add(new EnumCodeStyleOptionViewModel<ExpressionBodyPreference>(
CSharpCodeStyleOptions.PreferExpressionBodiedProperties,
ServicesVSResources.Use_expression_body_for_properties,
enumValues,
new[] { s_preferBlockBodyForProperties, s_preferExpressionBodyForProperties, s_preferExpressionBodyForProperties },
this, optionSet, expressionPreferencesGroupTitle, expressionBodyPreferences));
CodeStyleItems.Add(new EnumCodeStyleOptionViewModel<ExpressionBodyPreference>(
CSharpCodeStyleOptions.PreferExpressionBodiedIndexers,
ServicesVSResources.Use_expression_body_for_indexers,
enumValues,
new[] { s_preferBlockBodyForIndexers, s_preferExpressionBodyForIndexers, s_preferExpressionBodyForIndexers },
this, optionSet, expressionPreferencesGroupTitle, expressionBodyPreferences));
CodeStyleItems.Add(new EnumCodeStyleOptionViewModel<ExpressionBodyPreference>(
CSharpCodeStyleOptions.PreferExpressionBodiedAccessors,
ServicesVSResources.Use_expression_body_for_accessors,
enumValues,
new[] { s_preferBlockBodyForAccessors, s_preferExpressionBodyForAccessors, s_preferExpressionBodyForAccessors },
this, optionSet, expressionPreferencesGroupTitle, expressionBodyPreferences));
}
}
}
\ No newline at end of file
......@@ -122,24 +122,11 @@ public bool TryFetch(OptionKey optionKey, out object value)
}
else if (optionKey.Option.Type == typeof(CodeStyleOption<bool>))
{
// We store these as strings, so deserialize
if (value is string serializedValue)
{
try
{
value = CodeStyleOption<bool>.FromXElement(XElement.Parse(serializedValue));
}
catch (Exception)
{
value = null;
return false;
}
}
else
{
value = null;
return false;
}
return DeserializeCodeStyleOption<bool>(ref value);
}
else if (optionKey.Option.Type == typeof(CodeStyleOption<ExpressionBodyPreference>))
{
return DeserializeCodeStyleOption<ExpressionBodyPreference>(ref value);
}
else if (optionKey.Option.Type == typeof(NamingStylePreferences))
{
......@@ -190,6 +177,24 @@ public bool TryFetch(OptionKey optionKey, out object value)
return true;
}
private bool DeserializeCodeStyleOption<T>(ref object value)
{
if (value is string serializedValue)
{
try
{
value = CodeStyleOption<T>.FromXElement(XElement.Parse(serializedValue));
return true;
}
catch (Exception)
{
}
}
value = null;
return false;
}
private void RecordObservedValueToWatchForChanges(OptionKey optionKey, string storageKey)
{
// We're about to fetch the value, so make sure that if it changes we'll know about it
......@@ -225,15 +230,10 @@ public bool TryPersist(OptionKey optionKey, object value)
RecordObservedValueToWatchForChanges(optionKey, storageKey);
if (optionKey.Option.Type == typeof(CodeStyleOption<bool>))
if (value is ICodeStyleOption codeStyleOption)
{
// We store these as strings, so serialize
var valueToSerialize = value as CodeStyleOption<bool>;
if (value != null)
{
value = valueToSerialize.ToXElement().ToString();
}
value = codeStyleOption.ToXElement().ToString();
}
else if (optionKey.Option.Type == typeof(NamingStylePreferences))
{
......
......@@ -824,33 +824,6 @@ internal class ServicesVSResources {
}
}
/// <summary>
/// Looks up a localized string similar to For accessors.
/// </summary>
internal static string For_accessors {
get {
return ResourceManager.GetString("For_accessors", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to For constructors.
/// </summary>
internal static string For_constructors {
get {
return ResourceManager.GetString("For_constructors", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to For indexers.
/// </summary>
internal static string For_indexers {
get {
return ResourceManager.GetString("For_indexers", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to For locals, parameters and members.
/// </summary>
......@@ -869,33 +842,6 @@ internal class ServicesVSResources {
}
}
/// <summary>
/// Looks up a localized string similar to For methods.
/// </summary>
internal static string For_methods {
get {
return ResourceManager.GetString("For_methods", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to For operators.
/// </summary>
internal static string For_operators {
get {
return ResourceManager.GetString("For_operators", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to For properties.
/// </summary>
internal static string For_properties {
get {
return ResourceManager.GetString("For_properties", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Generate Type.
/// </summary>
......@@ -2287,6 +2233,60 @@ internal class ServicesVSResources {
}
}
/// <summary>
/// Looks up a localized string similar to Use expression body for accessors.
/// </summary>
internal static string Use_expression_body_for_accessors {
get {
return ResourceManager.GetString("Use_expression_body_for_accessors", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use expression body for constructors.
/// </summary>
internal static string Use_expression_body_for_constructors {
get {
return ResourceManager.GetString("Use_expression_body_for_constructors", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use expression body for indexers.
/// </summary>
internal static string Use_expression_body_for_indexers {
get {
return ResourceManager.GetString("Use_expression_body_for_indexers", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use expression body for methods.
/// </summary>
internal static string Use_expression_body_for_methods {
get {
return ResourceManager.GetString("Use_expression_body_for_methods", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use expression body for operators.
/// </summary>
internal static string Use_expression_body_for_operators {
get {
return ResourceManager.GetString("Use_expression_body_for_operators", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use expression body for properties.
/// </summary>
internal static string Use_expression_body_for_properties {
get {
return ResourceManager.GetString("Use_expression_body_for_properties", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Validating breakpoint location....
/// </summary>
......
......@@ -753,26 +753,26 @@ Additional information: {1}</value>
<data name="Prefer_inlined_variable_declaration" xml:space="preserve">
<value>Prefer inlined variable declaration</value>
</data>
<data name="For_methods" xml:space="preserve">
<value>For methods</value>
<data name="Use_expression_body_for_methods" xml:space="preserve">
<value>Use expression body for methods</value>
</data>
<data name="Code_block_preferences_colon" xml:space="preserve">
<value>Code block preferences:</value>
</data>
<data name="For_accessors" xml:space="preserve">
<value>For accessors</value>
<data name="Use_expression_body_for_accessors" xml:space="preserve">
<value>Use expression body for accessors</value>
</data>
<data name="For_constructors" xml:space="preserve">
<value>For constructors</value>
<data name="Use_expression_body_for_constructors" xml:space="preserve">
<value>Use expression body for constructors</value>
</data>
<data name="For_indexers" xml:space="preserve">
<value>For indexers</value>
<data name="Use_expression_body_for_indexers" xml:space="preserve">
<value>Use expression body for indexers</value>
</data>
<data name="For_operators" xml:space="preserve">
<value>For operators</value>
<data name="Use_expression_body_for_operators" xml:space="preserve">
<value>Use expression body for operators</value>
</data>
<data name="For_properties" xml:space="preserve">
<value>For properties</value>
<data name="Use_expression_body_for_properties" xml:space="preserve">
<value>Use expression body for properties</value>
</data>
<data name="Some_naming_rules_are_incomplete_Please_complete_or_remove_them" xml:space="preserve">
<value>Some naming rules are incomplete. Please complete or remove them.</value>
......
// 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.CodeStyle;
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options
{
/// <summary>
/// This class maps a boolean option into a codestyle option
/// that binds to the codestyle options UI.
/// </summary>
/// <remarks>
/// This exists to support options that are implemented as boolean
/// options in the non UI layers, <see cref="Option{Boolean}"/>.
/// In future, if such options are moved to use <see cref="CodeStyleOption{T}"/>,
/// this class can be completely deleted.
/// </remarks>
internal class BooleanCodeStyleOptionViewModel : AbstractCodeStyleOptionViewModel
{
public BooleanCodeStyleOptionViewModel(
IOption option,
string description,
string truePreview,
string falsePreview,
AbstractOptionPreviewViewModel info,
OptionSet options,
string groupName,
List<CodeStylePreference> preferences = null,
List<NotificationOptionViewModel> notificationPreferences = null)
: base(option, description, truePreview, falsePreview, info, options, groupName, preferences, notificationPreferences)
{
var booleanOption = (bool)options.GetOption(new OptionKey(option, option.IsPerLanguage ? info.Language : null));
_selectedPreference = Preferences.Single(c => c.IsChecked == booleanOption);
NotifyPropertyChanged(nameof(SelectedPreference));
}
public override bool NotificationsAvailable => false;
private CodeStylePreference _selectedPreference;
public override CodeStylePreference SelectedPreference
{
get
{
return _selectedPreference;
}
set
{
if (SetProperty(ref _selectedPreference, value))
{
Info.SetOptionAndUpdatePreview(_selectedPreference.IsChecked, Option, GetPreview());
}
}
}
}
}
......@@ -10,8 +10,7 @@
namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options
{
/// <summary>
/// This class acts as a base for any view model that
/// binds to the codestyle options UI.
/// This class acts as a base for any view model that binds to the codestyle options UI.
/// </summary>
/// <remarks>
/// This supports databinding of:
......@@ -24,20 +23,18 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options
/// </remarks>
internal abstract class AbstractCodeStyleOptionViewModel : AbstractNotifyPropertyChanged
{
private readonly string _truePreview;
private readonly string _falsePreview;
protected AbstractOptionPreviewViewModel Info { get; }
public IOption Option { get; }
public string Description { get; set; }
public double DescriptionMargin { get; set; }
public double DescriptionMargin { get; set; } = 12d;
public string GroupName { get; set; }
public abstract CodeStylePreference SelectedPreference { get; set; }
public List<CodeStylePreference> Preferences { get; set; }
public List<NotificationOptionViewModel> NotificationPreferences { get; set; }
public abstract bool NotificationsAvailable { get; }
public virtual string GetPreview() => SelectedPreference.IsChecked ? _truePreview : _falsePreview;
public abstract CodeStylePreference SelectedPreference { get; set; }
public abstract string GetPreview();
public virtual NotificationOptionViewModel SelectedNotificationPreference
{
get { return NotificationPreferences.First(); }
......@@ -47,23 +44,17 @@ public virtual NotificationOptionViewModel SelectedNotificationPreference
public AbstractCodeStyleOptionViewModel(
IOption option,
string description,
string truePreview,
string falsePreview,
AbstractOptionPreviewViewModel info,
OptionSet options,
string groupName,
List<CodeStylePreference> preferences = null,
List<NotificationOptionViewModel> notificationPreferences = null)
{
_truePreview = truePreview;
_falsePreview = falsePreview;
Info = info;
Option = option;
Description = description;
Preferences = preferences ?? GetDefaultPreferences();
NotificationPreferences = notificationPreferences ?? GetDefaultNotifications();
DescriptionMargin = 12d;
GroupName = groupName;
}
......@@ -86,6 +77,5 @@ private static List<CodeStylePreference> GetDefaultPreferences()
new CodeStylePreference(ServicesVSResources.No, isChecked: false),
};
}
}
}
}
\ No newline at end of file
......@@ -11,15 +11,43 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options
/// This class represents the view model for a <see cref="CodeStyleOption{T}"/>
/// that binds to the codestyle options UI.
/// </summary>
internal class SimpleCodeStyleOptionViewModel : AbstractCodeStyleOptionViewModel
internal class BooleanCodeStyleOptionViewModel : AbstractCodeStyleOptionViewModel
{
private readonly string _truePreview;
private readonly string _falsePreview;
private CodeStylePreference _selectedPreference;
private NotificationOptionViewModel _selectedNotificationPreference;
public BooleanCodeStyleOptionViewModel(
IOption option,
string description,
string truePreview,
string falsePreview,
AbstractOptionPreviewViewModel info,
OptionSet options,
string groupName,
List<CodeStylePreference> preferences = null,
List<NotificationOptionViewModel> notificationPreferences = null)
: base(option, description, info, options, groupName, preferences, notificationPreferences)
{
_truePreview = truePreview;
_falsePreview = falsePreview;
var codeStyleOption = ((CodeStyleOption<bool>)options.GetOption(new OptionKey(option, option.IsPerLanguage ? info.Language : null)));
_selectedPreference = Preferences.Single(c => c.IsChecked == codeStyleOption.Value);
var notificationViewModel = NotificationPreferences.Single(i => i.Notification.Value == codeStyleOption.Notification.Value);
_selectedNotificationPreference = NotificationPreferences.Single(p => p.Notification.Value == notificationViewModel.Notification.Value);
NotifyPropertyChanged(nameof(SelectedPreference));
NotifyPropertyChanged(nameof(SelectedNotificationPreference));
}
public override CodeStylePreference SelectedPreference
{
get
{
return _selectedPreference;
}
get => _selectedPreference;
set
{
if (SetProperty(ref _selectedPreference, value))
......@@ -29,13 +57,9 @@ public override CodeStylePreference SelectedPreference
}
}
private NotificationOptionViewModel _selectedNotificationPreference;
public override NotificationOptionViewModel SelectedNotificationPreference
{
get
{
return _selectedNotificationPreference;
}
get => _selectedNotificationPreference;
set
{
......@@ -46,28 +70,7 @@ public override NotificationOptionViewModel SelectedNotificationPreference
}
}
public override bool NotificationsAvailable => true;
public SimpleCodeStyleOptionViewModel(
IOption option,
string description,
string truePreview,
string falsePreview,
AbstractOptionPreviewViewModel info,
OptionSet options,
string groupName,
List<CodeStylePreference> preferences = null,
List<NotificationOptionViewModel> notificationPreferences = null)
: base(option, description, truePreview, falsePreview, info, options, groupName, preferences, notificationPreferences)
{
var codeStyleOption = ((CodeStyleOption<bool>)options.GetOption(new OptionKey(option, option.IsPerLanguage ? info.Language : null)));
_selectedPreference = Preferences.Single(c => c.IsChecked == codeStyleOption.Value);
var notificationViewModel = NotificationPreferences.Single(i => i.Notification.Value == codeStyleOption.Notification.Value);
_selectedNotificationPreference = NotificationPreferences.Single(p => p.Notification.Value == notificationViewModel.Notification.Value);
NotifyPropertyChanged(nameof(SelectedPreference));
NotifyPropertyChanged(nameof(SelectedNotificationPreference));
}
public override string GetPreview()
=> SelectedPreference.IsChecked ? _truePreview : _falsePreview;
}
}
}
\ 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.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Options;
using Roslyn.Utilities;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options
{
/// <summary>
/// This class represents the view model for a <see cref="CodeStyleOption{T}"/>
/// that binds to the codestyle options UI. Note that the T here is expected to be an enum
/// type.
///
/// Important. The order of the previews and preferences provided should match the order
/// of enum members of T.
/// </summary>
internal class EnumCodeStyleOptionViewModel<T> : AbstractCodeStyleOptionViewModel
where T : struct
{
static EnumCodeStyleOptionViewModel()
{
Contract.ThrowIfFalse(typeof(T).IsEnum);
}
private readonly ImmutableArray<T> _enumValues;
private readonly ImmutableArray<string> _previews;
private CodeStylePreference _selectedPreference;
private NotificationOptionViewModel _selectedNotificationPreference;
public EnumCodeStyleOptionViewModel(
Option<CodeStyleOption<T>> option,
string description,
T[] enumValues,
string[] previews,
AbstractOptionPreviewViewModel info,
OptionSet options,
string groupName,
List<CodeStylePreference> preferences)
: base(option, description, info, options, groupName, preferences)
{
Debug.Assert(preferences.Count == enumValues.Length);
Debug.Assert(previews.Length == enumValues.Length);
var expectedEnumValues = Enum.GetValues(typeof(T));
Debug.Assert(expectedEnumValues.Length == enumValues.Length, "Enum was updated, but UI wasn't.");
_enumValues = enumValues.ToImmutableArray();
_previews = previews.ToImmutableArray();
var codeStyleOption = options.GetOption(option);
var enumIndex = _enumValues.IndexOf(codeStyleOption.Value);
_selectedPreference = Preferences[enumIndex];
var notificationViewModel = NotificationPreferences.Single(i => i.Notification.Value == codeStyleOption.Notification.Value);
_selectedNotificationPreference = NotificationPreferences.Single(p => p.Notification.Value == notificationViewModel.Notification.Value);
NotifyPropertyChanged(nameof(SelectedPreference));
NotifyPropertyChanged(nameof(SelectedNotificationPreference));
}
public override string GetPreview()
{
var index = Preferences.IndexOf(SelectedPreference);
return _previews[index];
}
public override CodeStylePreference SelectedPreference
{
get => _selectedPreference;
set
{
if (SetProperty(ref _selectedPreference, value))
{
var index = Preferences.IndexOf(value);
var enumValue = _enumValues[index];
Info.SetOptionAndUpdatePreview(
new CodeStyleOption<T>(
enumValue, _selectedNotificationPreference.Notification),
Option, GetPreview());
}
}
}
public override NotificationOptionViewModel SelectedNotificationPreference
{
get => _selectedNotificationPreference;
set
{
if (SetProperty(ref _selectedNotificationPreference, value))
{
var index = Preferences.IndexOf(SelectedPreference);
var enumValue = _enumValues[index];
Info.SetOptionAndUpdatePreview(
new CodeStyleOption<T>(
enumValue, _selectedNotificationPreference.Notification),
Option, GetPreview());
}
}
}
}
}
\ No newline at end of file
......@@ -207,12 +207,12 @@
<Compile Include="CodeModel\RootCodeModel.cs" />
<Compile Include="CodeModel\SyntaxNodeKey.cs" />
<Compile Include="CodeModel\TextManagerAdapter.cs" />
<Compile Include="Options\AbstractCodeStyleOptionViewModel.cs" />
<Compile Include="Options\BooleanCodeStyleOptionViewModel.cs" />
<Compile Include="Options\CodeStylePreference.cs" />
<Compile Include="Options\Style\AbstractCodeStyleOptionViewModel.cs" />
<Compile Include="Options\Style\BooleanCodeStyleOptionViewModel.cs" />
<Compile Include="Options\Style\CodeStylePreference.cs" />
<Compile Include="Options\ColumnToTabStopConverter.cs" />
<Compile Include="Options\Converters\MarginConverter.cs" />
<Compile Include="Options\SimpleCodeStyleOptionViewModel.cs" />
<Compile Include="Options\Style\EnumCodeStyleOptionViewModel.cs" />
<Compile Include="Options\AbstractCheckBoxViewModel.cs" />
<Compile Include="Options\CheckBoxWithComboViewModel.cs" />
<Compile Include="Options\GridOptionPreviewControl.xaml.cs">
......
......@@ -2202,8 +2202,8 @@ class C
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}
{CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement},
{CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithNoneEnforcement}
})
End Function
......@@ -2253,8 +2253,8 @@ class C
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}
{CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement},
{CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithNoneEnforcement}
})
End Function
......
......@@ -268,23 +268,23 @@ End Class"
Dim nothingPreferencesGroupTitle = BasicVSResources.nothing_checking_colon
' qualify with Me. group
Me.CodeStyleItems.Add(New SimpleCodeStyleOptionViewModel(CodeStyleOptions.QualifyFieldAccess, BasicVSResources.Qualify_field_access_with_Me, s_fieldDeclarationPreviewTrue, s_fieldDeclarationPreviewFalse, Me, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences))
Me.CodeStyleItems.Add(New SimpleCodeStyleOptionViewModel(CodeStyleOptions.QualifyPropertyAccess, BasicVSResources.Qualify_property_access_with_Me, s_propertyDeclarationPreviewTrue, s_propertyDeclarationPreviewFalse, Me, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences))
Me.CodeStyleItems.Add(New SimpleCodeStyleOptionViewModel(CodeStyleOptions.QualifyMethodAccess, BasicVSResources.Qualify_method_access_with_Me, s_methodDeclarationPreviewTrue, s_methodDeclarationPreviewFalse, Me, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences))
Me.CodeStyleItems.Add(New SimpleCodeStyleOptionViewModel(CodeStyleOptions.QualifyEventAccess, BasicVSResources.Qualify_event_access_with_Me, s_eventDeclarationPreviewTrue, s_eventDeclarationPreviewFalse, Me, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences))
Me.CodeStyleItems.Add(New BooleanCodeStyleOptionViewModel(CodeStyleOptions.QualifyFieldAccess, BasicVSResources.Qualify_field_access_with_Me, s_fieldDeclarationPreviewTrue, s_fieldDeclarationPreviewFalse, Me, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences))
Me.CodeStyleItems.Add(New BooleanCodeStyleOptionViewModel(CodeStyleOptions.QualifyPropertyAccess, BasicVSResources.Qualify_property_access_with_Me, s_propertyDeclarationPreviewTrue, s_propertyDeclarationPreviewFalse, Me, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences))
Me.CodeStyleItems.Add(New BooleanCodeStyleOptionViewModel(CodeStyleOptions.QualifyMethodAccess, BasicVSResources.Qualify_method_access_with_Me, s_methodDeclarationPreviewTrue, s_methodDeclarationPreviewFalse, Me, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences))
Me.CodeStyleItems.Add(New BooleanCodeStyleOptionViewModel(CodeStyleOptions.QualifyEventAccess, BasicVSResources.Qualify_event_access_with_Me, s_eventDeclarationPreviewTrue, s_eventDeclarationPreviewFalse, Me, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences))
' predefined or framework type group
Me.CodeStyleItems.Add(New SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration, ServicesVSResources.For_locals_parameters_and_members, _intrinsicDeclarationPreviewTrue, _intrinsicDeclarationPreviewFalse, Me, optionSet, predefinedTypesGroupTitle, predefinedTypesPreferences))
Me.CodeStyleItems.Add(New SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, ServicesVSResources.For_member_access_expressions, _intrinsicMemberAccessPreviewTrue, _intrinsicMemberAccessPreviewFalse, Me, optionSet, predefinedTypesGroupTitle, predefinedTypesPreferences))
Me.CodeStyleItems.Add(New BooleanCodeStyleOptionViewModel(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration, ServicesVSResources.For_locals_parameters_and_members, _intrinsicDeclarationPreviewTrue, _intrinsicDeclarationPreviewFalse, Me, optionSet, predefinedTypesGroupTitle, predefinedTypesPreferences))
Me.CodeStyleItems.Add(New BooleanCodeStyleOptionViewModel(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, ServicesVSResources.For_member_access_expressions, _intrinsicMemberAccessPreviewTrue, _intrinsicMemberAccessPreviewFalse, Me, optionSet, predefinedTypesGroupTitle, predefinedTypesPreferences))
' expression preferences
Me.CodeStyleItems.Add(New SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferObjectInitializer, ServicesVSResources.Prefer_object_initializer, s_preferObjectInitializer, s_preferObjectInitializer, Me, optionSet, expressionPreferencesGroupTitle))
Me.CodeStyleItems.Add(New SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferCollectionInitializer, ServicesVSResources.Prefer_collection_initializer, s_preferCollectionInitializer, s_preferCollectionInitializer, Me, optionSet, expressionPreferencesGroupTitle))
Me.CodeStyleItems.Add(New SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferExplicitTupleNames, ServicesVSResources.Prefer_explicit_tuple_name, s_preferExplicitTupleName, s_preferExplicitTupleName, Me, optionSet, expressionPreferencesGroupTitle))
Me.CodeStyleItems.Add(New BooleanCodeStyleOptionViewModel(CodeStyleOptions.PreferObjectInitializer, ServicesVSResources.Prefer_object_initializer, s_preferObjectInitializer, s_preferObjectInitializer, Me, optionSet, expressionPreferencesGroupTitle))
Me.CodeStyleItems.Add(New BooleanCodeStyleOptionViewModel(CodeStyleOptions.PreferCollectionInitializer, ServicesVSResources.Prefer_collection_initializer, s_preferCollectionInitializer, s_preferCollectionInitializer, Me, optionSet, expressionPreferencesGroupTitle))
Me.CodeStyleItems.Add(New BooleanCodeStyleOptionViewModel(CodeStyleOptions.PreferExplicitTupleNames, ServicesVSResources.Prefer_explicit_tuple_name, s_preferExplicitTupleName, s_preferExplicitTupleName, Me, optionSet, expressionPreferencesGroupTitle))
' nothing preferences
Me.CodeStyleItems.Add(New SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferCoalesceExpression, ServicesVSResources.Prefer_coalesce_expression, s_preferCoalesceExpression, s_preferCoalesceExpression, Me, optionSet, nothingPreferencesGroupTitle))
Me.CodeStyleItems.Add(New SimpleCodeStyleOptionViewModel(CodeStyleOptions.PreferNullPropagation, ServicesVSResources.Prefer_null_propagation, s_preferNullPropagation, s_preferNullPropagation, Me, optionSet, nothingPreferencesGroupTitle))
Me.CodeStyleItems.Add(New BooleanCodeStyleOptionViewModel(CodeStyleOptions.PreferCoalesceExpression, ServicesVSResources.Prefer_coalesce_expression, s_preferCoalesceExpression, s_preferCoalesceExpression, Me, optionSet, nothingPreferencesGroupTitle))
Me.CodeStyleItems.Add(New BooleanCodeStyleOptionViewModel(CodeStyleOptions.PreferNullPropagation, ServicesVSResources.Prefer_null_propagation, s_preferNullPropagation, s_preferNullPropagation, Me, optionSet, nothingPreferencesGroupTitle))
End Sub
End Class
End Namespace
\ No newline at end of file
......@@ -73,16 +73,13 @@ private static MemberDeclarationSyntax LastConstructorOrField(SyntaxList<MemberD
{
if (declaration.ExpressionBody == null)
{
var preferExpressionBody = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors).Value;
if (preferExpressionBody)
var expressionBodyPreference = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors).Value;
if (declaration.Body.TryConvertToExpressionBody(
options, expressionBodyPreference, out var expressionBody, out var semicolonToken))
{
if (declaration.Body.TryConvertToExpressionBody(
options, out var expressionBody, out var semicolonToken))
{
return declaration.WithBody(null)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
return declaration.WithBody(null)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
}
......
......@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
......@@ -82,16 +83,14 @@ internal static class ConversionGenerator
{
if (declaration.ExpressionBody == null)
{
var preferExpressionBody = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators).Value;
if (preferExpressionBody)
var expressionBodyPreference = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators).Value;
if (declaration.Body.TryConvertToExpressionBody(
options, expressionBodyPreference, out var expressionBody, out var semicolonToken))
{
if (declaration.Body.TryConvertToExpressionBody(
options, out var expressionBody, out var semicolonToken))
{
return declaration.WithBody(null)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
return declaration.WithBody(null)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
}
......
......@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
......@@ -118,16 +119,13 @@ internal static class MethodGenerator
{
if (methodDeclaration.ExpressionBody == null)
{
var preferExpressionBody = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods).Value;
if (preferExpressionBody)
var expressionBodyPreference = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods).Value;
if (methodDeclaration.Body.TryConvertToExpressionBody(
options, expressionBodyPreference, out var expressionBody, out var semicolonToken))
{
if (methodDeclaration.Body.TryConvertToExpressionBody(
options, out var expressionBody, out var semicolonToken))
{
return methodDeclaration.WithBody(null)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
return methodDeclaration.WithBody(null)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
}
......
......@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
......@@ -55,16 +56,13 @@ internal static class OperatorGenerator
{
if (declaration.ExpressionBody == null)
{
var preferExpressionBody = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators).Value;
if (preferExpressionBody)
var expressionBodyPreference = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators).Value;
if (declaration.Body.TryConvertToExpressionBody(
options, expressionBodyPreference, out var expressionBody, out var semicolonToken))
{
if (declaration.Body.TryConvertToExpressionBody(
options, out var expressionBody, out var semicolonToken))
{
return declaration.WithBody(null)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
return declaration.WithBody(null)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
}
......
// 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.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Symbols;
......@@ -145,15 +145,16 @@ private static TypeSyntax GeneratePropertyType(IPropertySymbol property)
}
private static bool TryGetExpressionBody(
AccessorListSyntax accessorList, ParseOptions options,
AccessorListSyntax accessorList, ParseOptions options, ExpressionBodyPreference preference,
out ArrowExpressionClauseSyntax arrowExpression, out SyntaxToken semicolonToken)
{
if (accessorList.Accessors.Count == 1)
if (preference != ExpressionBodyPreference.Never &&
accessorList.Accessors.Count == 1)
{
var accessor = accessorList.Accessors[0];
if (accessor.IsKind(SyntaxKind.GetAccessorDeclaration))
{
return TryGetExpressionBody(accessor, options, out arrowExpression, out semicolonToken);
return TryGetExpressionBody(accessor, options, preference, out arrowExpression, out semicolonToken);
}
}
......@@ -167,18 +168,15 @@ private static TypeSyntax GeneratePropertyType(IPropertySymbol property)
{
if (declaration.ExpressionBody == null)
{
var preferExpressionBody = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties).Value;
if (preferExpressionBody)
var expressionBodyPreference = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties).Value;
if (declaration.Initializer == null)
{
if (declaration.Initializer == null)
if (TryGetExpressionBody(declaration.AccessorList, options,
expressionBodyPreference, out var expressionBody, out var semicolonToken))
{
if (TryGetExpressionBody(declaration.AccessorList, options,
out var expressionBody, out var semicolonToken))
{
declaration = declaration.WithAccessorList(null)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
declaration = declaration.WithAccessorList(null)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
}
}
......@@ -191,16 +189,13 @@ private static TypeSyntax GeneratePropertyType(IPropertySymbol property)
{
if (declaration.ExpressionBody == null)
{
var preferExpressionBody = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers).Value;
if (preferExpressionBody)
var expressionBodyPreference = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers).Value;
if (TryGetExpressionBody(declaration.AccessorList,
options, expressionBodyPreference, out var expressionBody, out var semicolonToken))
{
if (TryGetExpressionBody(declaration.AccessorList,
options, out var expressionBody, out var semicolonToken))
{
declaration = declaration.WithAccessorList(null)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
declaration = declaration.WithAccessorList(null)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
}
......@@ -212,16 +207,13 @@ private static TypeSyntax GeneratePropertyType(IPropertySymbol property)
{
if (declaration.ExpressionBody == null)
{
var preferExpressionBody = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value;
if (preferExpressionBody)
var expressionBodyPreference = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value;
if (declaration.Body.TryConvertToExpressionBody(
options, expressionBodyPreference, out var expressionBody, out var semicolonToken))
{
if (declaration.Body.TryConvertToExpressionBody(
options, out var expressionBody, out var semicolonToken))
{
declaration = declaration.WithBody(null)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
declaration = declaration.WithBody(null)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
}
......@@ -229,7 +221,7 @@ private static TypeSyntax GeneratePropertyType(IPropertySymbol property)
}
private static bool TryGetExpressionBody(
AccessorDeclarationSyntax accessor, ParseOptions options,
AccessorDeclarationSyntax accessor, ParseOptions options, ExpressionBodyPreference preference,
out ArrowExpressionClauseSyntax arrowExpression, out SyntaxToken semicolonToken)
{
// If the accessor has an expression body already, then use that as the expression body
......@@ -242,7 +234,7 @@ private static TypeSyntax GeneratePropertyType(IPropertySymbol property)
}
return accessor.Body.TryConvertToExpressionBody(
options, out arrowExpression, out semicolonToken);
options, preference, out arrowExpression, out semicolonToken);
}
private static AccessorListSyntax GenerateAccessorList(
......
......@@ -3,7 +3,6 @@
using System.Collections.Generic;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Options;
using static Microsoft.CodeAnalysis.CodeStyle.CodeStyleHelpers;
namespace Microsoft.CodeAnalysis.CSharp.CodeStyle
{
......@@ -45,42 +44,78 @@ internal static class CSharpCodeStyleOptions
new EditorConfigStorageLocation("csharp_style_pattern_matching_over_is_with_cast_check"),
new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferPatternMatchingOverIsWithCastCheck)}")});
public static readonly Option<CodeStyleOption<bool>> PreferExpressionBodiedConstructors = new Option<CodeStyleOption<bool>>(
nameof(CodeStyleOptions), nameof(PreferExpressionBodiedConstructors), defaultValue: CodeStyleOptions.FalseWithNoneEnforcement,
public static readonly CodeStyleOption<ExpressionBodyPreference> NeverWithNoneEnforcement =
new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None);
public static readonly CodeStyleOption<ExpressionBodyPreference> NeverWithSuggestionEnforcement =
new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.Suggestion);
public static readonly CodeStyleOption<ExpressionBodyPreference> WhenPossibleWithNoneEnforcement =
new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None);
public static readonly CodeStyleOption<ExpressionBodyPreference> WhenPossibleWithSuggestionEnforcement =
new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.Suggestion);
public static readonly CodeStyleOption<ExpressionBodyPreference> WhenOnSingleLineWithNoneEnforcement =
new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenOnSingleLine, NotificationOption.None);
public static readonly Option<CodeStyleOption<ExpressionBodyPreference>> PreferExpressionBodiedConstructors = new Option<CodeStyleOption<ExpressionBodyPreference>>(
nameof(CodeStyleOptions), nameof(PreferExpressionBodiedConstructors),
defaultValue: NeverWithNoneEnforcement,
storageLocations: new OptionStorageLocation[] {
new EditorConfigStorageLocation("csharp_style_expression_bodied_constructors"),
new EditorConfigStorageLocation("csharp_style_expression_bodied_constructors", s => ParseExpressionBodyPreference(s, ExpressionBodyPreference.Never)),
new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedConstructors)}")});
public static readonly Option<CodeStyleOption<bool>> PreferExpressionBodiedMethods = new Option<CodeStyleOption<bool>>(
nameof(CodeStyleOptions), nameof(PreferExpressionBodiedMethods), defaultValue: CodeStyleOptions.FalseWithNoneEnforcement,
public static readonly Option<CodeStyleOption<ExpressionBodyPreference>> PreferExpressionBodiedMethods = new Option<CodeStyleOption<ExpressionBodyPreference>>(
nameof(CodeStyleOptions), nameof(PreferExpressionBodiedMethods),
defaultValue: NeverWithNoneEnforcement,
storageLocations: new OptionStorageLocation[] {
new EditorConfigStorageLocation("csharp_style_expression_bodied_methods"),
new EditorConfigStorageLocation("csharp_style_expression_bodied_methods", s => ParseExpressionBodyPreference(s, ExpressionBodyPreference.Never)),
new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedMethods)}")});
public static readonly Option<CodeStyleOption<bool>> PreferExpressionBodiedOperators = new Option<CodeStyleOption<bool>>(
nameof(CodeStyleOptions), nameof(PreferExpressionBodiedOperators), defaultValue: CodeStyleOptions.FalseWithNoneEnforcement,
public static readonly Option<CodeStyleOption<ExpressionBodyPreference>> PreferExpressionBodiedOperators = new Option<CodeStyleOption<ExpressionBodyPreference>>(
nameof(CodeStyleOptions), nameof(PreferExpressionBodiedOperators),
defaultValue: NeverWithNoneEnforcement,
storageLocations: new OptionStorageLocation[] {
new EditorConfigStorageLocation("csharp_style_expression_bodied_operators"),
new EditorConfigStorageLocation("csharp_style_expression_bodied_operators", s => ParseExpressionBodyPreference(s, ExpressionBodyPreference.Never)),
new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedOperators)}")});
public static readonly Option<CodeStyleOption<bool>> PreferExpressionBodiedProperties = new Option<CodeStyleOption<bool>>(
nameof(CodeStyleOptions), nameof(PreferExpressionBodiedProperties), defaultValue: CodeStyleOptions.TrueWithNoneEnforcement,
public static readonly Option<CodeStyleOption<ExpressionBodyPreference>> PreferExpressionBodiedProperties = new Option<CodeStyleOption<ExpressionBodyPreference>>(
nameof(CodeStyleOptions), nameof(PreferExpressionBodiedProperties),
defaultValue: WhenPossibleWithNoneEnforcement,
storageLocations: new OptionStorageLocation[] {
new EditorConfigStorageLocation("csharp_style_expression_bodied_properties"),
new EditorConfigStorageLocation("csharp_style_expression_bodied_properties", s => ParseExpressionBodyPreference(s, ExpressionBodyPreference.WhenOnSingleLine)),
new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedProperties)}")});
public static readonly Option<CodeStyleOption<bool>> PreferExpressionBodiedIndexers = new Option<CodeStyleOption<bool>>(
nameof(CodeStyleOptions), nameof(PreferExpressionBodiedIndexers), defaultValue: CodeStyleOptions.TrueWithNoneEnforcement,
public static readonly Option<CodeStyleOption<ExpressionBodyPreference>> PreferExpressionBodiedIndexers = new Option<CodeStyleOption<ExpressionBodyPreference>>(
nameof(CodeStyleOptions), nameof(PreferExpressionBodiedIndexers),
defaultValue: WhenPossibleWithNoneEnforcement,
storageLocations: new OptionStorageLocation[] {
new EditorConfigStorageLocation("csharp_style_expression_bodied_indexers"),
new EditorConfigStorageLocation("csharp_style_expression_bodied_indexers", s => ParseExpressionBodyPreference(s, ExpressionBodyPreference.WhenOnSingleLine)),
new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedIndexers)}")});
public static readonly Option<CodeStyleOption<bool>> PreferExpressionBodiedAccessors = new Option<CodeStyleOption<bool>>(
nameof(CodeStyleOptions), nameof(PreferExpressionBodiedAccessors), defaultValue: CodeStyleOptions.TrueWithNoneEnforcement,
public static readonly Option<CodeStyleOption<ExpressionBodyPreference>> PreferExpressionBodiedAccessors = new Option<CodeStyleOption<ExpressionBodyPreference>>(
nameof(CodeStyleOptions), nameof(PreferExpressionBodiedAccessors),
defaultValue: WhenPossibleWithNoneEnforcement,
storageLocations: new OptionStorageLocation[] {
new EditorConfigStorageLocation("csharp_style_expression_bodied_accessors"),
new EditorConfigStorageLocation("csharp_style_expression_bodied_accessors", s => ParseExpressionBodyPreference(s, ExpressionBodyPreference.WhenOnSingleLine)),
new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedAccessors)}")});
private static object ParseExpressionBodyPreference(string value, ExpressionBodyPreference @default)
{
if (bool.TryParse(value, out var boolValue))
{
return boolValue ? ExpressionBodyPreference.WhenPossible : ExpressionBodyPreference.Never;
}
if (value == "when_on_single_line")
{
return ExpressionBodyPreference.WhenOnSingleLine;
}
return @default;
}
public static readonly Option<CodeStyleOption<bool>> PreferBraces = new Option<CodeStyleOption<bool>>(
nameof(CodeStyleOptions), nameof(PreferBraces), defaultValue: CodeStyleOptions.TrueWithNoneEnforcement,
storageLocations: new OptionStorageLocation[] {
......@@ -95,13 +130,17 @@ public static IEnumerable<Option<CodeStyleOption<bool>>> GetCodeStyleOptions()
yield return PreferConditionalDelegateCall;
yield return PreferPatternMatchingOverAsWithNullCheck;
yield return PreferPatternMatchingOverIsWithCastCheck;
yield return PreferBraces;
}
public static IEnumerable<Option<CodeStyleOption<ExpressionBodyPreference>>> GetExpressionBodyOptions()
{
yield return PreferExpressionBodiedConstructors;
yield return PreferExpressionBodiedMethods;
yield return PreferExpressionBodiedOperators;
yield return PreferExpressionBodiedProperties;
yield return PreferExpressionBodiedIndexers;
yield return PreferExpressionBodiedAccessors;
yield return PreferBraces;
}
}
}
\ No newline at end of file
......@@ -42,6 +42,11 @@ public override void WriteTo(OptionSet options, ObjectWriter writer, Cancellatio
{
WriteOptionTo(options, option, writer, cancellationToken);
}
foreach (var option in CSharpCodeStyleOptions.GetExpressionBodyOptions())
{
WriteOptionTo(options, option, writer, cancellationToken);
}
}
public override OptionSet ReadOptionSetFrom(ObjectReader reader, CancellationToken cancellationToken)
......@@ -55,6 +60,11 @@ public override OptionSet ReadOptionSetFrom(ObjectReader reader, CancellationTok
options = ReadOptionFrom(options, option, reader, cancellationToken);
}
foreach (var option in CSharpCodeStyleOptions.GetExpressionBodyOptions())
{
options = ReadOptionFrom(options, option, reader, cancellationToken);
}
return options;
}
......
// 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.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Extensions
{
......@@ -10,16 +14,19 @@ internal static class BlockSyntaxExtensions
{
public static bool TryConvertToExpressionBody(
this BlockSyntax block, ParseOptions options,
ExpressionBodyPreference preference,
out ArrowExpressionClauseSyntax arrowExpression,
out SyntaxToken semicolonToken)
{
if ((options as CSharpParseOptions)?.LanguageVersion >= LanguageVersion.CSharp7)
if (preference != ExpressionBodyPreference.Never &&
(options as CSharpParseOptions)?.LanguageVersion >= LanguageVersion.CSharp7)
{
if (block != null && block.Statements.Count == 1)
{
var firstStatement = block.Statements[0];
if (TryGetExpression(firstStatement, out var expression, out semicolonToken))
if (TryGetExpression(firstStatement, out var expression, out semicolonToken) &&
MatchesPreference(expression, preference))
{
arrowExpression = SyntaxFactory.ArrowExpressionClause(expression);
......@@ -27,7 +34,7 @@ internal static class BlockSyntaxExtensions
// comments or directives). Preserve them on the semicolon when we
// convert to an expression body.
semicolonToken = semicolonToken.WithAppendedTrailingTrivia(
block.CloseBraceToken.LeadingTrivia.Where(t =>!t.IsWhitespaceOrEndOfLine()));
block.CloseBraceToken.LeadingTrivia.Where(t => !t.IsWhitespaceOrEndOfLine()));
return true;
}
}
......@@ -38,6 +45,18 @@ internal static class BlockSyntaxExtensions
return false;
}
private static bool MatchesPreference(
ExpressionSyntax expression, ExpressionBodyPreference preference)
{
if (preference == ExpressionBodyPreference.WhenPossible)
{
return true;
}
Contract.ThrowIfFalse(preference == ExpressionBodyPreference.WhenOnSingleLine);
return CSharpSyntaxFactsService.Instance.IsOnSingleLine(expression, fullSpan: false);
}
private static bool TryGetExpression(
StatementSyntax firstStatement, out ExpressionSyntax expression, out SyntaxToken semicolonToken)
{
......
......@@ -1589,9 +1589,12 @@ public SyntaxList<SyntaxNode> GetContentsOfInterpolatedString(SyntaxNode interpo
return ((interpolatedString as InterpolatedStringExpressionSyntax)?.Contents).Value;
}
public bool IsStringLiteral(SyntaxToken token)
public override bool IsStringLiteral(SyntaxToken token)
=> token.IsKind(SyntaxKind.StringLiteralToken);
public override bool IsInterpolatedStringTextToken(SyntaxToken token)
=> token.IsKind(SyntaxKind.InterpolatedStringTextToken);
public bool IsStringLiteralExpression(SyntaxNode node)
=> node.Kind() == SyntaxKind.StringLiteralExpression;
......
......@@ -7,10 +7,26 @@
namespace Microsoft.CodeAnalysis.CodeStyle
{
internal interface ICodeStyleOption
{
XElement ToXElement();
}
/// <summary>
/// Represents a code style option and an associated notification option.
/// Represents a code style option and an associated notification option. Supports
/// being instantiated with T as a <see cref="bool"/> or an <code>enum type</code>.
///
/// CodeStyleOption also has some basic support for migration a <see cref="bool"/> option
/// forward to an <code>enum type</code> option. Specifically, if a previously serialized
/// bool-CodeStyleOption is then deserialized into an enum-CodeStyleOption then 'false'
/// values will be migrated to have the 0-value of the enum, and 'true' values will be
/// migrated to have the 1-value of the enum.
///
/// Similarly, enum-type code options will serialize out in a way that is compatible with
/// hosts that expect the value to be a boolean. Specifically, if the enum value is 0 or 1
/// then those values will write back as false/true.
/// </summary>
public class CodeStyleOption<T> : IEquatable<CodeStyleOption<T>>
public class CodeStyleOption<T> : ICodeStyleOption, IEquatable<CodeStyleOption<T>>
{
public static CodeStyleOption<T> Default => new CodeStyleOption<T>(default(T), NotificationOption.None);
......@@ -24,15 +40,51 @@ public CodeStyleOption(T value, NotificationOption notification)
public T Value { get; set; }
private int EnumValueAsInt32 => (int)(object)Value;
public NotificationOption Notification { get; set; }
public XElement ToXElement() =>
new XElement(nameof(CodeStyleOption<T>), // `nameof()` returns just "CodeStyleOption"
new XAttribute(nameof(SerializationVersion), SerializationVersion),
new XAttribute("Type", typeof(T).Name),
new XAttribute(nameof(Value), Value),
new XAttribute("Type", GetTypeNameForSerialization()),
new XAttribute(nameof(Value), GetValueForSerialization()),
new XAttribute(nameof(DiagnosticSeverity), Notification.Value));
private object GetValueForSerialization()
{
if (typeof(T) == typeof(bool))
{
return Value;
}
else if (IsZeroOrOneValueOfEnum())
{
return EnumValueAsInt32 == 1;
}
else
{
return EnumValueAsInt32;
}
}
private string GetTypeNameForSerialization()
{
if (typeof(T) == typeof(bool) || IsZeroOrOneValueOfEnum())
{
return nameof(Boolean);
}
else
{
return nameof(Int32);
}
}
private bool IsZeroOrOneValueOfEnum()
{
var intVal = EnumValueAsInt32;
return intVal == 0 || intVal == 1;
}
public static CodeStyleOption<T> FromXElement(XElement element)
{
var typeAttribute = element.Attribute("Type");
......@@ -52,7 +104,7 @@ public static CodeStyleOption<T> FromXElement(XElement element)
}
var parser = GetParser(typeAttribute.Value);
var value = (T)parser(valueAttribute.Value);
var value = parser(valueAttribute.Value);
var severity = (DiagnosticSeverity)Enum.Parse(typeof(DiagnosticSeverity), severityAttribute.Value);
NotificationOption notificationOption;
......@@ -77,37 +129,55 @@ public static CodeStyleOption<T> FromXElement(XElement element)
return new CodeStyleOption<T>(value, notificationOption);
}
private static Func<string, object> GetParser(string type)
private static Func<string, T> GetParser(string type)
{
switch (type)
{
case nameof(Boolean):
return v => bool.Parse(v);
// Try to map a boolean value. Either map it to true/false if we're a
// CodeStyleOption<bool> or map it to the 0 or 1 value for an enum if we're
// a CodeStyleOption<SomeEnumType>.
return v => Convert(bool.Parse(v));
case nameof(Int32):
return v => Convert(int.Parse(v));
default:
throw new ArgumentException(nameof(type));
}
}
public bool Equals(CodeStyleOption<T> other)
private static T Convert(bool b)
{
return EqualityComparer<T>.Default.Equals(Value, other.Value) &&
Notification == other.Notification;
// If we had a bool and we wanted a bool, then just return this value.
if (typeof(T) == typeof(bool))
{
return (T)(object)b;
}
// Map booleans to the 1/0 value of the enum.
return b ? (T)(object)1 : (T)(object)0;
}
public override bool Equals(object obj)
private static T Convert(int i)
{
var codeStyle = obj as CodeStyleOption<T>;
if (codeStyle == null)
// We got an int, but we wanted a bool. Map 0 to false, 1 to true, and anything else to default.
if (typeof(T) == typeof(bool))
{
return false;
return (T)(object)(i == 1);
}
return ((IEquatable<CodeStyleOption<T>>)this).Equals(codeStyle);
// If had an int and we wanted an enum, then just return this value.
return (T)(object)(i);
}
public bool Equals(CodeStyleOption<T> other)
=> EqualityComparer<T>.Default.Equals(Value, other.Value) &&
Notification == other.Notification;
public override bool Equals(object obj)
=> obj is CodeStyleOption<T> option &&
Equals(option);
public override int GetHashCode()
{
return Hash.Combine(Value.GetHashCode(), Notification.GetHashCode());
}
=> Hash.Combine(Value.GetHashCode(), Notification.GetHashCode());
}
}
}
\ 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.
namespace Microsoft.CodeAnalysis.CodeStyle
{
/// <remarks>
/// Note: the order of this enum is important. We originally only supported two values,
/// and we encoded this as a bool with 'true = WhenPossible' and 'false = never'. To
/// preserve compatibility we map the false value to 0 and the true value to 1. All new
/// values go after these.
/// </remarks>
internal enum ExpressionBodyPreference
{
// Value can not be changed. 'false' was the "never" value back when we used CodeStyleOption<bool>
// and that will map to '0' when derialized.
Never = 0,
// Value can not be changed. 'true' was the 'whenever possible' value back when we used
// CodeStyleOption<bool> and that will map to '1' when deserialized.
WhenPossible = 1,
WhenOnSingleLine = 2,
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.Shared.Extensions;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
......@@ -25,6 +26,9 @@ internal abstract class AbstractSyntaxFactsService
private readonly static ObjectPool<Dictionary<string, string>> s_aliasMapPool =
new ObjectPool<Dictionary<string, string>>(() => new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase));
private readonly static ObjectPool<Stack<(SyntaxNodeOrToken nodeOrToken, bool leading, bool trailing)>> s_stackPool =
new ObjectPool<Stack<(SyntaxNodeOrToken nodeOrToken, bool leading, bool trailing)>>(() => new Stack<(SyntaxNodeOrToken nodeOrToken, bool leading, bool trailing)>());
// Matches the following:
//
// (whitespace* newline)+
......@@ -73,9 +77,7 @@ protected AbstractSyntaxFactsService()
public abstract bool IsPreprocessorDirective(SyntaxTrivia trivia);
protected static List<Dictionary<string, string>> AllocateAliasMapList()
{
return s_aliasMapListPool.Allocate();
}
=> s_aliasMapListPool.Allocate();
protected static void FreeAliasMapList(List<Dictionary<string, string>> list)
{
......@@ -99,10 +101,144 @@ protected static void FreeAliasMap(Dictionary<string, string> aliasMap)
}
protected static Dictionary<string, string> AllocateAliasMap()
=> s_aliasMapPool.Allocate();
public bool IsOnSingleLine(SyntaxNode node, bool fullSpan)
{
// Use an actual Stack so we can write out deeply recursive structures without overflowing.
// Note: algorithm is taken from GreenNode.WriteTo.
//
// General approach is that we recurse down the nodes, using a real stack object to
// keep track of what node we're on. If full-span is true we'll examine all tokens
// and all the trivia on each token. If full-span is false we'll examine all tokens
// but we'll ignore the leading trivia on the very first trivia and the trailing trivia
// on the very last token.
var stack = s_stackPool.Allocate();
stack.Push((node, leading: fullSpan, trailing: fullSpan));
var result = IsOnSingleLine(stack);
s_stackPool.ClearAndFree(stack);
return result;
}
private bool IsOnSingleLine(
Stack<(SyntaxNodeOrToken nodeOrToken, bool leading, bool trailing)> stack)
{
while (stack.Count > 0)
{
var current = stack.Pop();
var currentNodeOrToken = current.nodeOrToken;
var currentLeading = current.leading;
var currentTrailing = current.trailing;
if (currentNodeOrToken.IsToken)
{
// If this token isn't on a single line, then the original node definitely
// isn't on a single line.
if (!IsOnSingleLine(currentNodeOrToken.AsToken(), currentLeading, currentTrailing))
{
return false;
}
}
else
{
var currentNode = currentNodeOrToken.AsNode();
var childNodesAndTokens = currentNode.ChildNodesAndTokens();
var childCount = childNodesAndTokens.Count;
// Walk the children of this node in reverse, putting on the stack to process.
// This way we process the children in the actual child-order they are in for
// this node.
var index = 0;
foreach (var child in childNodesAndTokens.Reverse())
{
var first = index == 0;
var last = index == childCount - 1;
// We want the leading trivia if we've asked for it, or if we're not the first
// token being processed. We want the trailing trivia if we've asked for it,
// or if we're not the last token being processed.
stack.Push((child, currentLeading | !first, currentTrailing | !last));
index++;
}
}
}
// All tokens were on a single line. This node is on a single line.
return true;
}
private bool IsOnSingleLine(SyntaxToken token, bool leading, bool trailing)
{
return s_aliasMapPool.Allocate();
// If any of our trivia is not on a single line, then we're not on a single line.
if (!IsOnSingleLine(token.LeadingTrivia, leading) ||
!IsOnSingleLine(token.TrailingTrivia, trailing))
{
return false;
}
// Only string literals can span multiple lines. Only need to check those.
if (IsStringLiteral(token) ||
IsInterpolatedStringTextToken(token))
{
// This allocated. But we only do it in the string case. For all other tokens
// we don't need any allocations.
if (!IsOnSingleLine(token.ToString()))
{
return false;
}
}
// Any other type of token is on a single line.
return true;
}
private bool IsOnSingleLine(SyntaxTriviaList triviaList, bool checkTrivia)
{
if (checkTrivia)
{
foreach (var trivia in triviaList)
{
if (trivia.HasStructure)
{
// For structured trivia, we recurse into the trivia to see if it
// is on a single line or not. If it isn't, then we're definitely
// not on a single line.
if (!IsOnSingleLine(trivia.GetStructure(), fullSpan: true))
{
return false;
}
}
else if (IsEndOfLineTrivia(trivia))
{
// Contained an end-of-line trivia. Definitely not on a single line.
return false;
}
else if (!IsWhitespaceTrivia(trivia))
{
// Was some other form of trivia (like a comment). Easiest thing
// to do is just stringify this and count the number of newlines.
// these should be rare. So the allocation here is ok.
if (!IsOnSingleLine(trivia.ToString()))
{
return false;
}
}
}
}
return true;
}
private bool IsOnSingleLine(string value)
=> value.GetNumberOfLineBreaks() == 0;
public abstract bool IsStringLiteral(SyntaxToken token);
public abstract bool IsInterpolatedStringTextToken(SyntaxToken token);
public ImmutableArray<SyntaxTrivia> GetLeadingBlankLines<TSyntaxNode>(TSyntaxNode node)
where TSyntaxNode : SyntaxNode
{
......
......@@ -34,8 +34,9 @@ internal interface ISyntaxFactsService : ILanguageService
bool IsNumericLiteral(SyntaxToken token);
bool IsCharacterLiteral(SyntaxToken token);
bool IsStringLiteral(SyntaxToken token);
bool IsStringLiteralExpression(SyntaxNode node);
bool IsVerbatimStringLiteral(SyntaxToken token);
bool IsInterpolatedStringTextToken(SyntaxToken token);
bool IsStringLiteralExpression(SyntaxNode node);
bool IsTypeNamedVarInVariableOrFieldDeclaration(SyntaxToken token, SyntaxNode parent);
bool IsTypeNamedDynamic(SyntaxToken token, SyntaxNode parent);
......
......@@ -344,6 +344,7 @@
<Compile Include="CodeGeneration\CodeGenerator.cs" />
<Compile Include="CodeStyle\CodeStyleHelpers.cs" />
<Compile Include="CodeStyle\CodeStyleOptions.cs" />
<Compile Include="CodeStyle\ExpressionBodyPreference.cs" />
<Compile Include="CodeStyle\NotificationOption.cs" />
<Compile Include="CodeStyle\CodeStyleOption.cs" />
<Compile Include="Diagnostics\AbstractDiagnosticPropertiesService.cs" />
......
......@@ -1400,10 +1400,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return token.Kind() = SyntaxKind.CharacterLiteralToken
End Function
Public Function IsStringLiteral(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsStringLiteral
Public Overrides Function IsStringLiteral(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsStringLiteral
Return token.IsKind(SyntaxKind.StringLiteralToken)
End Function
Public Overrides Function IsInterpolatedStringTextToken(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsInterpolatedStringTextToken
Return token.IsKind(SyntaxKind.InterpolatedStringTextToken)
End Function
Public Function IsStringLiteralExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsStringLiteralExpression
Return node.Kind() = SyntaxKind.StringLiteralExpression
End Function
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册