// 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.Windows.Data;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.VisualStudio.LanguageServices.Implementation.Options;
namespace Microsoft.VisualStudio.LanguageServices.CSharp.Options.Formatting
{
///
/// This is the view model for CodeStyle options page.
///
///
/// The codestyle options page is defined in
///
internal class StyleViewModel : AbstractOptionPreviewViewModel
{
#region "Preview Text"
private static readonly string s_fieldDeclarationPreviewTrue = @"
class C{
int capacity;
void Method()
{
//[
this.capacity = 0;
//]
}
}";
private static readonly string s_fieldDeclarationPreviewFalse = @"
class C{
int capacity;
void Method()
{
//[
capacity = 0;
//]
}
}";
private static readonly string s_propertyDeclarationPreviewTrue = @"
class C{
public int Id { get; set; }
void Method()
{
//[
this.Id = 0;
//]
}
}";
private static readonly string s_propertyDeclarationPreviewFalse = @"
class C{
public int Id { get; set; }
void Method()
{
//[
Id = 0;
//]
}
}";
private static readonly string s_eventDeclarationPreviewTrue = @"
using System;
class C{
event EventHandler Elapsed;
void Handler(object sender, EventArgs args)
{
//[
this.Elapsed += Handler;
//]
}
}";
private static readonly string s_eventDeclarationPreviewFalse = @"
using System;
class C{
event EventHandler Elapsed;
void Handler(object sender, EventArgs args)
{
//[
Elapsed += Handler;
//]
}
}";
private static readonly string s_methodDeclarationPreviewTrue = @"
using System;
class C{
void Display()
{
//[
this.Display();
//]
}
}";
private static readonly string s_methodDeclarationPreviewFalse = @"
using System;
class C{
void Display()
{
//[
Display();
//]
}
}";
private static readonly string s_intrinsicPreviewDeclarationTrue = @"
class Program
{
//[
private int _member;
static void M(int argument)
{
int local;
}
//]
}";
private static readonly string s_intrinsicPreviewDeclarationFalse = @"
using System;
class Program
{
//[
private Int32 _member;
static void M(Int32 argument)
{
Int32 local;
}
//]
}";
private static readonly string s_intrinsicPreviewMemberAccessTrue = @"
class Program
{
//[
static void M()
{
var local = int.MaxValue;
}
//]
}";
private static readonly string s_intrinsicPreviewMemberAccessFalse = @"
using System;
class Program
{
//[
static void M()
{
var local = Int32.MaxValue;
}
//]
}";
private static readonly string s_varForIntrinsicsPreviewFalse = @"
using System;
class C{
void Method()
{
//[
int x = 5; // built-in types
//]
}
}";
private static readonly string s_varForIntrinsicsPreviewTrue = @"
using System;
class C{
void Method()
{
//[
var x = 5; // built-in types
//]
}
}";
private static readonly string s_varWhereApparentPreviewFalse = @"
using System;
class C{
void Method()
{
//[
C cobj = new C(); // type is apparent from assignment expression
//]
}
}";
private static readonly string s_varWhereApparentPreviewTrue = @"
using System;
class C{
void Method()
{
//[
var cobj = new C(); // type is apparent from assignment expression
//]
}
}";
private static readonly string s_varWherePossiblePreviewFalse = @"
using System;
class C{
void Init()
{
//[
Action f = this.Init(); // everywhere else.
//]
}
}";
private static readonly string s_varWherePossiblePreviewTrue = @"
using System;
class C{
void Init()
{
//[
var f = this.Init(); // everywhere else.
//]
}
}";
private static readonly string s_preferThrowExpression = @"
using System;
class C
{
private string s;
public C(string s)
{
//[
// Prefer:
this.s = s ?? throw new ArgumentNullException(nameof(s));
// Over:
if (s == null)
{
throw new ArgumentNullException(nameof(s));
}
this.s = s;
//]
}
}
";
private static readonly string s_preferCoalesceExpression = @"
using System;
class C
{
private string s;
public C(string s)
{
//[
// Prefer:
var v = x ?? y;
// Over:
var v = x != null ? x : y; // or
var v = x == null ? y : x;
//]
}
}
";
private static readonly string s_preferConditionalDelegateCall = @"
using System;
class C
{
private string s;
public C(string s)
{
//[
// Prefer:
func?.Invoke(args);
// Over:
if (func != null)
{
func(args);
}
//]
}
}
";
private static readonly string s_preferNullPropagation = @"
using System;
class C
{
public C(object o)
{
//[
// Prefer:
var v = o?.ToString();
// Over:
var v = o == null ? null : o.ToString(); // or
var v = o != null ? o.ToString() : null;
//]
}
}
";
private static readonly string s_preferPatternMatchingOverAsWithNullCheck = @"
class C
{
void M()
{
//[
// Prefer:
if (o is string s)
{
}
// Over:
var s = o as string;
if (s != null)
{
}
//]
}
}
";
private static readonly string s_preferPatternMatchingOverIsWithCastCheck = @"
class C
{
void M()
{
//[
// Prefer:
if (o is int i)
{
}
// Over:
if (o is int)
{
var i = (int)o;
}
//]
}
}
";
private static readonly string s_preferObjectInitializer = @"
using System;
class Customer
{
private int Age;
public Customer()
{
//[
// Prefer:
var c = new Customer()
{
Age = 21
};
// Over:
var c = new Customer();
c.Age = 21;
//]
}
}
";
private static readonly string s_preferCollectionInitializer = @"
using System.Collections.Generic;
class Customer
{
private int Age;
public Customer()
{
//[
// Prefer:
var list = new List
{
1,
2,
3
};
// Over:
var list = new List();
list.Add(1);
list.Add(2);
list.Add(3);
//]
}
}
";
private static readonly string s_preferExplicitTupleName = @"
class Customer
{
public Customer()
{
//[
// Prefer:
(string name, int age) customer = GetCustomer();
var name = customer.name;
var age = customer.age;
// Over:
(string name, int age) customer = GetCustomer();
var name = customer.Item1;
var age = customer.Item2;
//]
}
}
";
private static readonly string s_preferInlinedVariableDeclaration = @"
using System;
class Customer
{
public Customer(string value)
{
//[
// Prefer:
if (int.TryParse(value, out int i))
{
}
// Over:
int i;
if (int.TryParse(value, out i))
{
}
//]
}
}
";
private static readonly string s_preferExpressionBodyForMethods = @"
using System;
//[
class Customer
{
private int Age;
public int GetAge() => this.Age;
}
//]
";
private static readonly string s_preferBlockBodyForMethods = @"
using System;
//[
class Customer
{
private int Age;
public int GetAge()
{
return this.Age;
}
}
//]
";
private static readonly string s_preferExpressionBodyForConstructors = @"
using System;
//[
class Customer
{
private int Age;
public Customer(int age) => Age = age;
}
//]
";
private static readonly string s_preferBlockBodyForConstructors = @"
using System;
//[
class Customer
{
private int Age;
public Customer(int age)
{
Age = age;
}
}
//]
";
private static readonly string s_preferExpressionBodyForOperators = @"
using System;
struct ComplexNumber
{
//[
public static ComplexNumber operator +(ComplexNumber c1, ComplexNumber c2)
=> new ComplexNumber(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary);
//]
}
";
private static readonly string s_preferBlockBodyForOperators = @"
using System;
struct ComplexNumber
{
//[
public static ComplexNumber operator +(ComplexNumber c1, ComplexNumber c2)
{
return new ComplexNumber(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary);
}
//]
}
";
private static readonly string s_preferExpressionBodyForProperties = @"
using System;
//[
class Customer
{
private int _age;
public int Age => _age;
}
//]
";
private static readonly string s_preferBlockBodyForProperties = @"
using System;
//[
class Customer
{
private int _age;
public int Age { get { return _age; } }
}
//]
";
private static readonly string s_preferExpressionBodyForAccessors = @"
using System;
//[
class Customer
{
private int _age;
public int Age
{
get => _age;
set => _age = value;
}
}
//]
";
private static readonly string s_preferBlockBodyForAccessors = @"
using System;
//[
class Customer
{
private int _age;
public int Age
{
get { return _age; }
set { _age = value; }
}
}
//]
";
private static readonly string s_preferExpressionBodyForIndexers= @"
using System;
//[
class List
{
private T[] _values;
public T this[int i] => _values[i];
}
//]
";
private static readonly string s_preferBlockBodyForIndexers = @"
using System;
//[
class List
{
private T[] _values;
public T this[int i] { get { return _values[i]; } }
}
//]
";
#endregion
internal StyleViewModel(OptionSet optionSet, IServiceProvider serviceProvider) : base(optionSet, serviceProvider, LanguageNames.CSharp)
{
var collectionView = (ListCollectionView)CollectionViewSource.GetDefaultView(CodeStyleItems);
collectionView.GroupDescriptions.Add(new PropertyGroupDescription(nameof(AbstractCodeStyleOptionViewModel.GroupName)));
var qualifyGroupTitle = CSharpVSResources.this_preferences_colon;
var predefinedTypesGroupTitle = CSharpVSResources.predefined_type_preferences_colon;
var varGroupTitle = CSharpVSResources.var_preferences_colon;
var nullCheckingGroupTitle = CSharpVSResources.null_checking_colon;
var codeBlockPreferencesGroupTitle = ServicesVSResources.Code_block_preferences_colon;
var expressionPreferencesGroupTitle = ServicesVSResources.Expression_preferences_colon;
var variablePreferencesGroupTitle = ServicesVSResources.Variable_preferences_colon;
var qualifyMemberAccessPreferences = new List
{
new CodeStylePreference(CSharpVSResources.Prefer_this, isChecked: true),
new CodeStylePreference(CSharpVSResources.Do_not_prefer_this, isChecked: false),
};
var predefinedTypesPreferences = new List
{
new CodeStylePreference(ServicesVSResources.Prefer_predefined_type, isChecked: true),
new CodeStylePreference(ServicesVSResources.Prefer_framework_type, isChecked: false),
};
var typeStylePreferences = new List
{
new CodeStylePreference(CSharpVSResources.Prefer_var, isChecked: true),
new CodeStylePreference(CSharpVSResources.Prefer_explicit_type, isChecked: false),
};
var codeBlockPreferences = new List
{
new CodeStylePreference(CSharpVSResources.Prefer_expression_body, isChecked: true),
new CodeStylePreference(CSharpVSResources.Prefer_block_body, isChecked: false),
};
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.QualifyFieldAccess, CSharpVSResources.Qualify_field_access_with_this, s_fieldDeclarationPreviewTrue, s_fieldDeclarationPreviewFalse, this, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.QualifyPropertyAccess, CSharpVSResources.Qualify_property_access_with_this, s_propertyDeclarationPreviewTrue, s_propertyDeclarationPreviewFalse, this, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CodeStyleOptions.QualifyMethodAccess, CSharpVSResources.Qualify_method_access_with_this, s_methodDeclarationPreviewTrue, s_methodDeclarationPreviewFalse, this, optionSet, qualifyGroupTitle, qualifyMemberAccessPreferences));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(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));
// Use var
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, CSharpVSResources.For_built_in_types, s_varForIntrinsicsPreviewTrue, s_varForIntrinsicsPreviewFalse, this, optionSet, varGroupTitle, typeStylePreferences));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, CSharpVSResources.When_variable_type_is_apparent, s_varWhereApparentPreviewTrue, s_varWhereApparentPreviewFalse, this, optionSet, varGroupTitle, typeStylePreferences));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, CSharpVSResources.Elsewhere, s_varWherePossiblePreviewTrue, s_varWherePossiblePreviewFalse, this, optionSet, varGroupTitle, typeStylePreferences));
// Code block
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, ServicesVSResources.For_methods, s_preferExpressionBodyForMethods, s_preferBlockBodyForMethods, this, optionSet, codeBlockPreferencesGroupTitle, codeBlockPreferences));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, ServicesVSResources.For_constructors, s_preferExpressionBodyForConstructors, s_preferBlockBodyForConstructors, this, optionSet, codeBlockPreferencesGroupTitle, codeBlockPreferences));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, ServicesVSResources.For_operators, s_preferExpressionBodyForOperators, s_preferBlockBodyForOperators, this, optionSet, codeBlockPreferencesGroupTitle, codeBlockPreferences));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, ServicesVSResources.For_properties, s_preferExpressionBodyForProperties, s_preferBlockBodyForProperties, this, optionSet, codeBlockPreferencesGroupTitle, codeBlockPreferences));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, ServicesVSResources.For_indexers, s_preferExpressionBodyForIndexers, s_preferBlockBodyForIndexers, this, optionSet, codeBlockPreferencesGroupTitle, codeBlockPreferences));
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, ServicesVSResources.For_accessors, s_preferExpressionBodyForAccessors, s_preferBlockBodyForAccessors, this, optionSet, codeBlockPreferencesGroupTitle, codeBlockPreferences));
// 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));
// Variable preferences
CodeStyleItems.Add(new SimpleCodeStyleOptionViewModel(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));
}
}
}