提交 62ae8a04 编写于 作者: B Balaji Krishnan

Incorporate PR feedback from @cyrusnajmabadi

Most fixes are about code style.

Major changes are in:
1. the algorithm to determine if type is apparent in creation or conversion methods.
2. option serialization/deserialization.
上级 41a68099
...@@ -32,19 +32,19 @@ public class UseExplicitTypingTests : AbstractCSharpDiagnosticProviderBasedUserD ...@@ -32,19 +32,19 @@ public class UseExplicitTypingTests : AbstractCSharpDiagnosticProviderBasedUserD
// specify all options explicitly to override defaults. // specify all options explicitly to override defaults.
private IDictionary<OptionKey, object> ExplicitTypingEverywhere() => private IDictionary<OptionKey, object> ExplicitTypingEverywhere() =>
Options(CSharpCodeStyleOptions.UseVarWherePossible, offWithInfo) Options(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, offWithInfo)
.With(CSharpCodeStyleOptions.UseVarWhenTypeIsApparent, offWithInfo) .With(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, offWithInfo)
.With(CSharpCodeStyleOptions.UseVarForIntrinsicTypes, offWithInfo); .With(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, offWithInfo);
private IDictionary<OptionKey, object> ExplicitTypingEnforcements() => private IDictionary<OptionKey, object> ExplicitTypingEnforcements() =>
Options(CSharpCodeStyleOptions.UseVarWherePossible, offWithWarning) Options(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, offWithWarning)
.With(CSharpCodeStyleOptions.UseVarWhenTypeIsApparent, offWithError) .With(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, offWithError)
.With(CSharpCodeStyleOptions.UseVarForIntrinsicTypes, offWithInfo); .With(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, offWithInfo);
private IDictionary<OptionKey, object> ExplicitTypingNoneEnforcement() => private IDictionary<OptionKey, object> ExplicitTypingNoneEnforcement() =>
Options(CSharpCodeStyleOptions.UseVarWherePossible, offWithNone) Options(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, offWithNone)
.With(CSharpCodeStyleOptions.UseVarWhenTypeIsApparent, offWithNone) .With(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, offWithNone)
.With(CSharpCodeStyleOptions.UseVarForIntrinsicTypes, offWithNone); .With(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, offWithNone);
private IDictionary<OptionKey, object> Options(OptionKey option, object value) private IDictionary<OptionKey, object> Options(OptionKey option, object value)
{ {
......
...@@ -33,34 +33,34 @@ public class UseImplicitTypingTests : AbstractCSharpDiagnosticProviderBasedUserD ...@@ -33,34 +33,34 @@ public class UseImplicitTypingTests : AbstractCSharpDiagnosticProviderBasedUserD
// specify all options explicitly to override defaults. // specify all options explicitly to override defaults.
private IDictionary<OptionKey, object> ImplicitTypingEverywhere() => private IDictionary<OptionKey, object> ImplicitTypingEverywhere() =>
Options(CSharpCodeStyleOptions.UseVarWherePossible, onWithInfo) Options(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, onWithInfo)
.With(CSharpCodeStyleOptions.UseVarWhenTypeIsApparent, onWithInfo) .With(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithInfo)
.With(CSharpCodeStyleOptions.UseVarForIntrinsicTypes, onWithInfo); .With(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, onWithInfo);
private IDictionary<OptionKey, object> ImplicitTypingWhereApparent() => private IDictionary<OptionKey, object> ImplicitTypingWhereApparent() =>
Options(CSharpCodeStyleOptions.UseVarWherePossible, offWithInfo) Options(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, offWithInfo)
.With(CSharpCodeStyleOptions.UseVarWhenTypeIsApparent, onWithInfo) .With(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithInfo)
.With(CSharpCodeStyleOptions.UseVarForIntrinsicTypes, offWithInfo); .With(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, offWithInfo);
private IDictionary<OptionKey, object> ImplicitTypingWhereApparentAndForIntrinsics() => private IDictionary<OptionKey, object> ImplicitTypingWhereApparentAndForIntrinsics() =>
Options(CSharpCodeStyleOptions.UseVarWherePossible, offWithInfo) Options(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, offWithInfo)
.With(CSharpCodeStyleOptions.UseVarWhenTypeIsApparent, onWithInfo) .With(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithInfo)
.With(CSharpCodeStyleOptions.UseVarForIntrinsicTypes, onWithInfo); .With(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, onWithInfo);
private IDictionary<OptionKey, object> ImplicitTypingButKeepIntrinsics() => private IDictionary<OptionKey, object> ImplicitTypingButKeepIntrinsics() =>
Options(CSharpCodeStyleOptions.UseVarWherePossible, onWithInfo) Options(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, onWithInfo)
.With(CSharpCodeStyleOptions.UseVarForIntrinsicTypes, offWithInfo) .With(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, offWithInfo)
.With(CSharpCodeStyleOptions.UseVarWhenTypeIsApparent, onWithInfo); .With(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithInfo);
private IDictionary<OptionKey, object> ImplicitTypingEnforcements() => private IDictionary<OptionKey, object> ImplicitTypingEnforcements() =>
Options(CSharpCodeStyleOptions.UseVarWherePossible, onWithWarning) Options(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, onWithWarning)
.With(CSharpCodeStyleOptions.UseVarWhenTypeIsApparent, onWithError) .With(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithError)
.With(CSharpCodeStyleOptions.UseVarForIntrinsicTypes, onWithInfo); .With(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, onWithInfo);
private IDictionary<OptionKey, object> ImplicitTypingNoneEnforcement() => private IDictionary<OptionKey, object> ImplicitTypingNoneEnforcement() =>
Options(CSharpCodeStyleOptions.UseVarWherePossible, onWithNone) Options(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, onWithNone)
.With(CSharpCodeStyleOptions.UseVarWhenTypeIsApparent, onWithNone) .With(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithNone)
.With(CSharpCodeStyleOptions.UseVarForIntrinsicTypes, onWithNone); .With(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, onWithNone);
private IDictionary<OptionKey, object> Options(OptionKey option, object value) private IDictionary<OptionKey, object> Options(OptionKey option, object value)
{ {
...@@ -906,6 +906,30 @@ static void M() ...@@ -906,6 +906,30 @@ static void M()
}", options: ImplicitTypingEverywhere()); }", options: ImplicitTypingEverywhere());
} }
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitTyping)]
public async Task SuggestVarInUnCheckedExpression()
{
await TestAsync(
@"using System;
class C
{
static void M()
{
long number1 = int.MaxValue + 20L;
[|int|] intNumber = unchecked((int)number1);
}
}",
@"using System;
class C
{
static void M()
{
long number1 = int.MaxValue + 20L;
var intNumber = unchecked((int)number1);
}
}", options: ImplicitTypingEverywhere());
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitTyping)] [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitTyping)]
public async Task SuggestVarInAwaitExpression() public async Task SuggestVarInAwaitExpression()
{ {
...@@ -1182,6 +1206,56 @@ public void Process() ...@@ -1182,6 +1206,56 @@ public void Process()
}", options: ImplicitTypingWhereApparent()); }", options: ImplicitTypingWhereApparent());
} }
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitTyping)]
public async Task SuggestVarWhereTypingIsEvident_CreationHelpers()
{
await TestAsync(
@"class C
{
public void Process()
{
[|XElement|] a = XElement.Load();
}
}
class XElement
{
internal static XElement Load() => return null;
}",
@"class C
{
public void Process()
{
var a = XElement.Load();
}
}
class XElement
{
internal static XElement Load() => return null;
}", options: ImplicitTypingWhereApparent());
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitTyping)]
public async Task SuggestVarWhereTypingIsEvident_CreationHelpersWithInferredTypeArguments()
{
await TestAsync(
@"using System;
class C
{
public void Process()
{
[|Tuple<int, bool>|] a = Tuple.Create(0, true);
}
}",
@"using System;
class C
{
public void Process()
{
var a = Tuple.Create(0, true);
}
}", options: ImplicitTypingWhereApparent());
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitTyping)] [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitTyping)]
public async Task SuggestVarWhereTypingIsEvident_ConvertToType() public async Task SuggestVarWhereTypingIsEvident_ConvertToType()
{ {
......
...@@ -908,38 +908,38 @@ internal class CSharpFeaturesResources { ...@@ -908,38 +908,38 @@ internal class CSharpFeaturesResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Use explicit typing instead of &apos;var&apos;. /// Looks up a localized string similar to Use explicit type instead of &apos;var&apos;.
/// </summary> /// </summary>
internal static string UseExplicitTyping { internal static string UseExplicitType {
get { get {
return ResourceManager.GetString("UseExplicitTyping", resourceCulture); return ResourceManager.GetString("UseExplicitType", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Use explicit typing. /// Looks up a localized string similar to Use explicit type.
/// </summary> /// </summary>
internal static string UseExplicitTypingDiagnosticTitle { internal static string UseExplicitTypeDiagnosticTitle {
get { get {
return ResourceManager.GetString("UseExplicitTypingDiagnosticTitle", resourceCulture); return ResourceManager.GetString("UseExplicitTypeDiagnosticTitle", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to use &apos;var&apos; instead of typename. /// Looks up a localized string similar to use &apos;var&apos; instead of explicit type.
/// </summary> /// </summary>
internal static string UseImplicitTyping { internal static string UseImplicitType {
get { get {
return ResourceManager.GetString("UseImplicitTyping", resourceCulture); return ResourceManager.GetString("UseImplicitType", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Use implicit typing. /// Looks up a localized string similar to Use implicit type.
/// </summary> /// </summary>
internal static string UseImplicitTypingDiagnosticTitle { internal static string UseImplicitTypeDiagnosticTitle {
get { get {
return ResourceManager.GetString("UseImplicitTypingDiagnosticTitle", resourceCulture); return ResourceManager.GetString("UseImplicitTypeDiagnosticTitle", resourceCulture);
} }
} }
......
...@@ -437,16 +437,16 @@ ...@@ -437,16 +437,16 @@
<data name="DelegateInvocationCanBeSimplified" xml:space="preserve"> <data name="DelegateInvocationCanBeSimplified" xml:space="preserve">
<value>Delegate invocation can be simplified.</value> <value>Delegate invocation can be simplified.</value>
</data> </data>
<data name="UseExplicitTyping" xml:space="preserve"> <data name="UseExplicitType" xml:space="preserve">
<value>Use explicit typing instead of 'var'</value> <value>Use explicit type instead of 'var'</value>
</data> </data>
<data name="UseExplicitTypingDiagnosticTitle" xml:space="preserve"> <data name="UseExplicitTypeDiagnosticTitle" xml:space="preserve">
<value>Use explicit typing</value> <value>Use explicit type</value>
</data> </data>
<data name="UseImplicitTyping" xml:space="preserve"> <data name="UseImplicitType" xml:space="preserve">
<value>use 'var' instead of typename</value> <value>use 'var' instead of explicit type</value>
</data> </data>
<data name="UseImplicitTypingDiagnosticTitle" xml:space="preserve"> <data name="UseImplicitTypeDiagnosticTitle" xml:space="preserve">
<value>Use implicit typing</value> <value>Use implicit type</value>
</data> </data>
</root> </root>
\ No newline at end of file
...@@ -35,18 +35,10 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) ...@@ -35,18 +35,10 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
return; return;
} }
var node = token.GetAncestors<SyntaxNode>().First(n => n.Span.Contains(span)); var node = root.FindNode(span, getInnermostNodeForTie: true);
if (node?.IsKind(SyntaxKind.PredefinedType,
SyntaxKind.ArrayType,
SyntaxKind.IdentifierName,
SyntaxKind.GenericName,
SyntaxKind.AliasQualifiedName) == false)
{
return;
}
var codeAction = new MyCodeAction( var codeAction = new MyCodeAction(
CSharpFeaturesResources.UseExplicitTyping, CSharpFeaturesResources.UseExplicitType,
c => HandleDeclaration(document, root, node, context.CancellationToken)); c => HandleDeclaration(document, root, node, context.CancellationToken));
context.RegisterCodeFix(codeAction, context.Diagnostics.First()); context.RegisterCodeFix(codeAction, context.Diagnostics.First());
...@@ -69,7 +61,7 @@ private async Task<Document> HandleDeclaration(Document document, SyntaxNode roo ...@@ -69,7 +61,7 @@ private async Task<Document> HandleDeclaration(Document document, SyntaxNode roo
else else
{ {
Debug.Assert(false, $"unhandled kind {declarationContext.Kind().ToString()}"); Debug.Assert(false, $"unhandled kind {declarationContext.Kind().ToString()}");
return null; return document;
} }
var typeSymbol = semanticModel.GetTypeInfo(typeSyntax).ConvertedType; var typeSymbol = semanticModel.GetTypeInfo(typeSyntax).ConvertedType;
......
...@@ -32,25 +32,20 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) ...@@ -32,25 +32,20 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
return; return;
} }
var node = token.GetAncestors<SyntaxNode>().First(n => n.Span.Contains(span)); var node = root.FindNode(span, getInnermostNodeForTie: true);
if (node == null || if (node == null || !SyntaxFacts.IsTypeSyntax(node.Kind()))
!(node.IsKind(SyntaxKind.PredefinedType) ||
node.IsKind(SyntaxKind.ArrayType) ||
node.IsKind(SyntaxKind.IdentifierName) ||
node.IsKind(SyntaxKind.GenericName) ||
node.IsKind(SyntaxKind.AliasQualifiedName)))
{ {
return; return;
} }
var codeAction = new MyCodeAction( var codeAction = new MyCodeAction(
CSharpFeaturesResources.UseImplicitTyping, CSharpFeaturesResources.UseImplicitType,
c => ReplaceTypeWithVar(document, root, node)); c => ReplaceTypeWithVarAsync(document, root, node));
context.RegisterCodeFix(codeAction, context.Diagnostics.First()); context.RegisterCodeFix(codeAction, context.Diagnostics.First());
} }
private static Task<Document> ReplaceTypeWithVar(Document document, SyntaxNode root, SyntaxNode node) private static Task<Document> ReplaceTypeWithVarAsync(Document document, SyntaxNode root, SyntaxNode node)
{ {
var implicitType = SyntaxFactory.IdentifierName("var") var implicitType = SyntaxFactory.IdentifierName("var")
.WithLeadingTrivia(node.GetLeadingTrivia()) .WithLeadingTrivia(node.GetLeadingTrivia())
......
...@@ -17,8 +17,8 @@ internal static class CSharpCodeStyleOptions ...@@ -17,8 +17,8 @@ internal static class CSharpCodeStyleOptions
// TODO: get sign off on public api changes. // TODO: get sign off on public api changes.
public static readonly Option<bool> UseVarWhenDeclaringLocals = new Option<bool>(FeatureName, "UseVarWhenDeclaringLocals", defaultValue: true); public static readonly Option<bool> UseVarWhenDeclaringLocals = new Option<bool>(FeatureName, "UseVarWhenDeclaringLocals", defaultValue: true);
public static readonly Option<SimpleCodeStyleOption> UseVarForIntrinsicTypes = new Option<SimpleCodeStyleOption>(FeatureName, "UseImplicitTypingForIntrinsics", defaultValue: SimpleCodeStyleOption.Default); public static readonly Option<SimpleCodeStyleOption> UseImplicitTypeForIntrinsicTypes = new Option<SimpleCodeStyleOption>(FeatureName, nameof(UseImplicitTypeForIntrinsicTypes), defaultValue: SimpleCodeStyleOption.Default);
public static readonly Option<SimpleCodeStyleOption> UseVarWhenTypeIsApparent = new Option<SimpleCodeStyleOption>(FeatureName, "UseImplicitTypingWhereApparent", defaultValue: SimpleCodeStyleOption.Default); public static readonly Option<SimpleCodeStyleOption> UseImplicitTypeWhereApparent = new Option<SimpleCodeStyleOption>(FeatureName, nameof(UseImplicitTypeWhereApparent), defaultValue: SimpleCodeStyleOption.Default);
public static readonly Option<SimpleCodeStyleOption> UseVarWherePossible = new Option<SimpleCodeStyleOption>(FeatureName, "UseImplicitTypingWherePossible", defaultValue: SimpleCodeStyleOption.Default); public static readonly Option<SimpleCodeStyleOption> UseImplicitTypeWherePossible = new Option<SimpleCodeStyleOption>(FeatureName, nameof(UseImplicitTypeWherePossible), defaultValue: SimpleCodeStyleOption.Default);
} }
} }
...@@ -14,9 +14,9 @@ internal class CSharpCodeStyleOptionsProvider : IOptionProvider ...@@ -14,9 +14,9 @@ internal class CSharpCodeStyleOptionsProvider : IOptionProvider
private readonly IEnumerable<IOption> _options = new List<IOption> private readonly IEnumerable<IOption> _options = new List<IOption>
{ {
CSharpCodeStyleOptions.UseVarWhenDeclaringLocals, CSharpCodeStyleOptions.UseVarWhenDeclaringLocals,
CSharpCodeStyleOptions.UseVarWherePossible, CSharpCodeStyleOptions.UseImplicitTypeWherePossible,
CSharpCodeStyleOptions.UseVarWhenTypeIsApparent, CSharpCodeStyleOptions.UseImplicitTypeWhereApparent,
CSharpCodeStyleOptions.UseVarForIntrinsicTypes CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes
}.ToImmutableArray(); }.ToImmutableArray();
public IEnumerable<IOption> GetOptions() public IEnumerable<IOption> GetOptions()
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.TypingStyles namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.TypingStyles
{ {
...@@ -16,9 +17,9 @@ internal partial class CSharpTypingStyleDiagnosticAnalyzerBase ...@@ -16,9 +17,9 @@ internal partial class CSharpTypingStyleDiagnosticAnalyzerBase
{ {
internal class State internal class State
{ {
private readonly Dictionary<TypingStyles, DiagnosticSeverity> _styleToSeverityMap; private readonly Dictionary<TypeStyle, DiagnosticSeverity> _styleToSeverityMap;
public TypingStyles StylePreferences { get; private set; } public TypeStyle TypeStyle { get; private set; }
public bool IsInIntrinsicTypeContext { get; private set; } public bool IsInIntrinsicTypeContext { get; private set; }
public bool IsTypingApparentInContext { get; private set; } public bool IsTypingApparentInContext { get; private set; }
public bool IsInVariableDeclarationContext { get; } public bool IsInVariableDeclarationContext { get; }
...@@ -26,7 +27,7 @@ internal class State ...@@ -26,7 +27,7 @@ internal class State
public State(bool isVariableDeclarationContext) public State(bool isVariableDeclarationContext)
{ {
this.IsInVariableDeclarationContext = isVariableDeclarationContext; this.IsInVariableDeclarationContext = isVariableDeclarationContext;
_styleToSeverityMap = new Dictionary<TypingStyles, DiagnosticSeverity>(); _styleToSeverityMap = new Dictionary<TypeStyle, DiagnosticSeverity>();
} }
public static State Generate(SyntaxNode declaration, SemanticModel semanticModel, OptionSet optionSet, bool isVariableDeclarationContext, CancellationToken cancellationToken) public static State Generate(SyntaxNode declaration, SemanticModel semanticModel, OptionSet optionSet, bool isVariableDeclarationContext, CancellationToken cancellationToken)
...@@ -40,15 +41,15 @@ public DiagnosticSeverity GetDiagnosticSeverityPreference() ...@@ -40,15 +41,15 @@ public DiagnosticSeverity GetDiagnosticSeverityPreference()
{ {
if (IsInIntrinsicTypeContext) if (IsInIntrinsicTypeContext)
{ {
return _styleToSeverityMap[TypingStyles.VarForIntrinsic]; return _styleToSeverityMap[TypeStyle.ImplicitTypeForIntrinsicTypes];
} }
else if (IsTypingApparentInContext) else if (IsTypingApparentInContext)
{ {
return _styleToSeverityMap[TypingStyles.VarWhereApparent]; return _styleToSeverityMap[TypeStyle.ImplicitTypeWhereApparent];
} }
else else
{ {
return _styleToSeverityMap[TypingStyles.VarWherePossible]; return _styleToSeverityMap[TypeStyle.ImplicitTypeWherePossible];
} }
} }
...@@ -57,13 +58,11 @@ public DiagnosticSeverity GetDiagnosticSeverityPreference() ...@@ -57,13 +58,11 @@ public DiagnosticSeverity GetDiagnosticSeverityPreference()
private void Initialize(SyntaxNode declaration, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken) private void Initialize(SyntaxNode declaration, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken)
{ {
this.StylePreferences = GetCurrentTypingStylePreferences(optionSet); this.TypeStyle = GetCurrentTypingStylePreferences(optionSet);
IsTypingApparentInContext = IsTypingApparentInContext =
IsInVariableDeclarationContext IsInVariableDeclarationContext
? IsTypeApparentInDeclaration((VariableDeclarationSyntax)declaration, && IsTypeApparentInDeclaration((VariableDeclarationSyntax)declaration, semanticModel, TypeStyle, cancellationToken);
semanticModel, StylePreferences, cancellationToken)
: false;
IsInIntrinsicTypeContext = IsIntrinsicType(declaration); IsInIntrinsicTypeContext = IsIntrinsicType(declaration);
} }
...@@ -72,7 +71,7 @@ private void Initialize(SyntaxNode declaration, SemanticModel semanticModel, Opt ...@@ -72,7 +71,7 @@ private void Initialize(SyntaxNode declaration, SemanticModel semanticModel, Opt
/// Returns true if type information could be gleaned by simply looking at the given statement. /// Returns true if type information could be gleaned by simply looking at the given statement.
/// This typically means that the type name occurs in either left hand or right hand side of an assignment. /// This typically means that the type name occurs in either left hand or right hand side of an assignment.
/// </summary> /// </summary>
private bool IsTypeApparentInDeclaration(VariableDeclarationSyntax variableDeclaration, SemanticModel semanticModel, TypingStyles stylePreferences, CancellationToken cancellationToken) private bool IsTypeApparentInDeclaration(VariableDeclarationSyntax variableDeclaration, SemanticModel semanticModel, TypeStyle stylePreferences, CancellationToken cancellationToken)
{ {
var initializer = variableDeclaration.Variables.Single().Initializer; var initializer = variableDeclaration.Variables.Single().Initializer;
var initializerExpression = GetInitializerExpression(initializer); var initializerExpression = GetInitializerExpression(initializer);
...@@ -86,7 +85,7 @@ private bool IsTypeApparentInDeclaration(VariableDeclarationSyntax variableDecla ...@@ -86,7 +85,7 @@ private bool IsTypeApparentInDeclaration(VariableDeclarationSyntax variableDecla
// literals, use var if options allow usage here. // literals, use var if options allow usage here.
if (initializerExpression.IsAnyLiteralExpression()) if (initializerExpression.IsAnyLiteralExpression())
{ {
return stylePreferences.HasFlag(TypingStyles.VarForIntrinsic); return stylePreferences.HasFlag(TypeStyle.ImplicitTypeForIntrinsicTypes);
} }
// constructor invocations cases: // constructor invocations cases:
...@@ -107,13 +106,12 @@ private bool IsTypeApparentInDeclaration(VariableDeclarationSyntax variableDecla ...@@ -107,13 +106,12 @@ private bool IsTypeApparentInDeclaration(VariableDeclarationSyntax variableDecla
} }
// other Conversion cases: // other Conversion cases:
// a. conversion with helpers like: int.Parse, TextSpan.From methods // a. conversion with helpers like: int.Parse methods
// b. types that implement IConvertible and then invoking .ToType() // b. types that implement IConvertible and then invoking .ToType()
// c. System.Convert.Totype() // c. System.Convert.Totype()
var declaredTypeSymbol = semanticModel.GetTypeInfo(variableDeclaration.Type, cancellationToken).Type; var declaredTypeSymbol = semanticModel.GetTypeInfo(variableDeclaration.Type, cancellationToken).Type;
var expressionOnRightSide = initializerExpression.WalkDownParentheses();
var memberName = expressionOnRightSide.GetRightmostName(); var memberName = initializerExpression.GetRightmostName();
if (memberName == null) if (memberName == null)
{ {
return false; return false;
...@@ -135,14 +133,7 @@ private bool IsTypeApparentInDeclaration(VariableDeclarationSyntax variableDecla ...@@ -135,14 +133,7 @@ private bool IsTypeApparentInDeclaration(VariableDeclarationSyntax variableDecla
} }
private bool IsIntrinsicType(SyntaxNode declarationStatement) => private bool IsIntrinsicType(SyntaxNode declarationStatement) =>
declarationStatement.IsKind(SyntaxKind.VariableDeclaration) (declarationStatement as VariableDeclarationSyntax)?.Variables.Single().Initializer.Value.IsAnyLiteralExpression() == true;
? ((VariableDeclarationSyntax)declarationStatement).Variables.Single().Initializer.Value.IsAnyLiteralExpression()
: false;
private ExpressionSyntax GetInitializerExpression(EqualsValueClauseSyntax initializer) =>
initializer.Value is CheckedExpressionSyntax
? ((CheckedExpressionSyntax)initializer.Value).Expression
: initializer.Value;
private bool IsPossibleCreationOrConversionMethod(IMethodSymbol methodSymbol, ITypeSymbol declaredType, SemanticModel semanticModel, ExpressionSyntax typeName, CancellationToken cancellationToken) private bool IsPossibleCreationOrConversionMethod(IMethodSymbol methodSymbol, ITypeSymbol declaredType, SemanticModel semanticModel, ExpressionSyntax typeName, CancellationToken cancellationToken)
{ {
...@@ -157,32 +148,24 @@ private bool IsPossibleCreationOrConversionMethod(IMethodSymbol methodSymbol, IT ...@@ -157,32 +148,24 @@ private bool IsPossibleCreationOrConversionMethod(IMethodSymbol methodSymbol, IT
|| IsPossibleConversionMethod(methodSymbol, declaredType, typeInInvocation, semanticModel, cancellationToken); || IsPossibleConversionMethod(methodSymbol, declaredType, typeInInvocation, semanticModel, cancellationToken);
} }
/// <summary>
/// Looks for types that have static methods that return the same type as the container.
/// e.g: int.Parse, XElement.Load, Tuple.Create etc.
/// </summary>
private bool IsPossibleCreationMethod(IMethodSymbol methodSymbol, ITypeSymbol declaredType, ITypeSymbol typeInInvocation) private bool IsPossibleCreationMethod(IMethodSymbol methodSymbol, ITypeSymbol declaredType, ITypeSymbol typeInInvocation)
{ {
var isTypeInfoSame = false; if (!methodSymbol.IsStatic)
// Pattern: Method name is a prefix match of one of these well known method names
// and method is a member of type being created.
// cases: int.ParseXXX, TextSpan.FromBounds,
if (methodSymbol.Name.StartsWith("Parse", StringComparison.Ordinal)
|| methodSymbol.Name.StartsWith("From", StringComparison.Ordinal))
{ {
isTypeInfoSame = typeInInvocation.Equals(declaredType); return false;
}
// Pattern: Method name is an exact match of one of these well known creation methods
// and method is a member of type being created.
// cases: node.With, Tuple.Create, State.Generate
if (methodSymbol.Name.Equals("With", StringComparison.Ordinal)
|| methodSymbol.Name.Equals("Create", StringComparison.Ordinal)
|| methodSymbol.Name.Equals("Generate", StringComparison.Ordinal))
{
isTypeInfoSame = typeInInvocation.Equals(declaredType);
} }
return isTypeInfoSame; return IsDeclaredTypeEqualToReturnType(methodSymbol, declaredType, typeInInvocation);
} }
/// <summary>
/// If we have a method ToXXX and its return type is also XXX, then type name is apparent
/// e.g: Convert.ToString.
/// </summary>
private bool IsPossibleConversionMethod(IMethodSymbol methodSymbol, ITypeSymbol declaredType, ITypeSymbol typeInInvocation, SemanticModel semanticModel, CancellationToken cancellationToken) private bool IsPossibleConversionMethod(IMethodSymbol methodSymbol, ITypeSymbol declaredType, ITypeSymbol typeInInvocation, SemanticModel semanticModel, CancellationToken cancellationToken)
{ {
// take `char` from `char? c = ` // take `char` from `char? c = `
...@@ -190,44 +173,62 @@ private bool IsPossibleConversionMethod(IMethodSymbol methodSymbol, ITypeSymbol ...@@ -190,44 +173,62 @@ private bool IsPossibleConversionMethod(IMethodSymbol methodSymbol, ITypeSymbol
? declaredType.GetTypeArguments().First().Name ? declaredType.GetTypeArguments().First().Name
: declaredType.Name; : declaredType.Name;
// case: Convert.ToString or iConvertible.ToChar var returnType = methodSymbol.ReturnType;
if (methodSymbol.Name.Equals("To" + declaredTypeName, StringComparison.Ordinal)) if (methodSymbol.Name.Equals("To" + declaredTypeName, StringComparison.Ordinal))
{ {
var convertType = semanticModel.Compilation.ConvertType(); return IsDeclaredTypeEqualToReturnType(methodSymbol, declaredType, typeInInvocation);
var iConvertibleType = semanticModel.Compilation.IConvertibleType();
return typeInInvocation.Equals(convertType)
|| typeInInvocation.Equals(iConvertibleType);
} }
return false; return false;
} }
private TypingStyles GetCurrentTypingStylePreferences(OptionSet optionSet) /// <remarks>
/// If there are type arguments on either side of assignment, we match type names instead of type equality
/// to account for inferred generic type arguments.
/// e.g: Tuple.Create(0, true) returns Tuple&lt;X,y&gt; which isn't the same as type Tuple.
/// otherwise, we match for type equivalence
/// </remarks>
private static bool IsDeclaredTypeEqualToReturnType(IMethodSymbol methodSymbol, ITypeSymbol declaredType, ITypeSymbol typeInInvocation)
{
var returnType = methodSymbol.ReturnType;
if (declaredType.GetTypeArguments().Length > 0 ||
typeInInvocation.GetTypeArguments().Length > 0)
{
return declaredType.Name.Equals(returnType.Name);
}
else
{
return declaredType.Equals(returnType);
}
}
private TypeStyle GetCurrentTypingStylePreferences(OptionSet optionSet)
{ {
var stylePreferences = TypingStyles.None; var stylePreferences = TypeStyle.None;
var styleForIntrinsicTypes = optionSet.GetOption(CSharpCodeStyleOptions.UseVarForIntrinsicTypes); var styleForIntrinsicTypes = optionSet.GetOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes);
var styleForApparent = optionSet.GetOption(CSharpCodeStyleOptions.UseVarWhenTypeIsApparent); var styleForApparent = optionSet.GetOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent);
var styleForElsewhere = optionSet.GetOption(CSharpCodeStyleOptions.UseVarWherePossible); var styleForElsewhere = optionSet.GetOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible);
_styleToSeverityMap.Add(TypingStyles.VarForIntrinsic, styleForIntrinsicTypes.Notification.Value); _styleToSeverityMap.Add(TypeStyle.ImplicitTypeForIntrinsicTypes, styleForIntrinsicTypes.Notification.Value);
_styleToSeverityMap.Add(TypingStyles.VarWhereApparent, styleForApparent.Notification.Value); _styleToSeverityMap.Add(TypeStyle.ImplicitTypeWhereApparent, styleForApparent.Notification.Value);
_styleToSeverityMap.Add(TypingStyles.VarWherePossible, styleForElsewhere.Notification.Value); _styleToSeverityMap.Add(TypeStyle.ImplicitTypeWherePossible, styleForElsewhere.Notification.Value);
if (styleForIntrinsicTypes.IsChecked) if (styleForIntrinsicTypes.IsChecked)
{ {
stylePreferences |= TypingStyles.VarForIntrinsic; stylePreferences |= TypeStyle.ImplicitTypeForIntrinsicTypes;
} }
if (styleForApparent.IsChecked) if (styleForApparent.IsChecked)
{ {
stylePreferences |= TypingStyles.VarWhereApparent; stylePreferences |= TypeStyle.ImplicitTypeWhereApparent;
} }
if (styleForElsewhere.IsChecked) if (styleForElsewhere.IsChecked)
{ {
stylePreferences |= TypingStyles.VarWherePossible; stylePreferences |= TypeStyle.ImplicitTypeWherePossible;
} }
return stylePreferences; return stylePreferences;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Options;
...@@ -16,34 +17,34 @@ namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.TypingStyles ...@@ -16,34 +17,34 @@ namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.TypingStyles
internal abstract partial class CSharpTypingStyleDiagnosticAnalyzerBase : DiagnosticAnalyzer, IBuiltInAnalyzer internal abstract partial class CSharpTypingStyleDiagnosticAnalyzerBase : DiagnosticAnalyzer, IBuiltInAnalyzer
{ {
[Flags] [Flags]
internal enum TypingStyles internal enum TypeStyle
{ {
None = 0, None = 0,
VarForIntrinsic = 1 << 0, ImplicitTypeForIntrinsicTypes = 1 << 0,
VarWhereApparent = 1 << 1, ImplicitTypeWhereApparent = 1 << 1,
VarWherePossible = 1 << 2, ImplicitTypeWherePossible = 1 << 2,
} }
private readonly string _diagnosticId; private readonly string _diagnosticId;
private readonly LocalizableString _title; private readonly LocalizableString _title;
private readonly LocalizableString _message; private readonly LocalizableString _message;
private readonly Lazy<DiagnosticDescriptor> _noneDiagnosticDescriptor; private readonly DiagnosticDescriptor _noneDiagnosticDescriptor;
private readonly Lazy<DiagnosticDescriptor> _infoDiagnosticDescriptor; private readonly DiagnosticDescriptor _infoDiagnosticDescriptor;
private readonly Lazy<DiagnosticDescriptor> _warningDiagnosticDescriptor; private readonly DiagnosticDescriptor _warningDiagnosticDescriptor;
private readonly Lazy<DiagnosticDescriptor> _errorDiagnosticDescriptor; private readonly DiagnosticDescriptor _errorDiagnosticDescriptor;
private readonly Dictionary<DiagnosticSeverity, Lazy<DiagnosticDescriptor>> _severityToDescriptorMap; private readonly Dictionary<DiagnosticSeverity, DiagnosticDescriptor> _severityToDescriptorMap;
public CSharpTypingStyleDiagnosticAnalyzerBase(string diagnosticId, LocalizableString title, LocalizableString message) public CSharpTypingStyleDiagnosticAnalyzerBase(string diagnosticId, LocalizableString title, LocalizableString message)
{ {
_diagnosticId = diagnosticId; _diagnosticId = diagnosticId;
_title = title; _title = title;
_message = message; _message = message;
_noneDiagnosticDescriptor = new Lazy<DiagnosticDescriptor>(() => CreateDiagnosticDescriptor(DiagnosticSeverity.Hidden)); _noneDiagnosticDescriptor = CreateDiagnosticDescriptor(DiagnosticSeverity.Hidden);
_infoDiagnosticDescriptor = new Lazy<DiagnosticDescriptor>(() => CreateDiagnosticDescriptor(DiagnosticSeverity.Info)); _infoDiagnosticDescriptor = CreateDiagnosticDescriptor(DiagnosticSeverity.Info);
_warningDiagnosticDescriptor = new Lazy<DiagnosticDescriptor>(() => CreateDiagnosticDescriptor(DiagnosticSeverity.Warning)); _warningDiagnosticDescriptor = CreateDiagnosticDescriptor(DiagnosticSeverity.Warning);
_errorDiagnosticDescriptor = new Lazy<DiagnosticDescriptor>(() => CreateDiagnosticDescriptor(DiagnosticSeverity.Error)); _errorDiagnosticDescriptor = CreateDiagnosticDescriptor(DiagnosticSeverity.Error);
_severityToDescriptorMap = _severityToDescriptorMap =
new Dictionary<DiagnosticSeverity, Lazy<DiagnosticDescriptor>> new Dictionary<DiagnosticSeverity, DiagnosticDescriptor>
{ {
{DiagnosticSeverity.Hidden, _noneDiagnosticDescriptor }, {DiagnosticSeverity.Hidden, _noneDiagnosticDescriptor },
{DiagnosticSeverity.Info, _infoDiagnosticDescriptor }, {DiagnosticSeverity.Info, _infoDiagnosticDescriptor },
...@@ -62,8 +63,8 @@ public CSharpTypingStyleDiagnosticAnalyzerBase(string diagnosticId, LocalizableS ...@@ -62,8 +63,8 @@ public CSharpTypingStyleDiagnosticAnalyzerBase(string diagnosticId, LocalizableS
isEnabledByDefault: true); isEnabledByDefault: true);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
ImmutableArray.Create(_noneDiagnosticDescriptor.Value, _infoDiagnosticDescriptor.Value, ImmutableArray.Create(_noneDiagnosticDescriptor, _infoDiagnosticDescriptor,
_warningDiagnosticDescriptor.Value, _errorDiagnosticDescriptor.Value); _warningDiagnosticDescriptor, _errorDiagnosticDescriptor);
public DiagnosticAnalyzerCategory GetAnalyzerCategory() => public DiagnosticAnalyzerCategory GetAnalyzerCategory() =>
DiagnosticAnalyzerCategory.SemanticSpanAnalysis; DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
...@@ -73,29 +74,36 @@ public override void Initialize(AnalysisContext context) ...@@ -73,29 +74,36 @@ public override void Initialize(AnalysisContext context)
context.RegisterSyntaxNodeAction(HandleVariableDeclaration, SyntaxKind.VariableDeclaration, SyntaxKind.ForEachStatement); context.RegisterSyntaxNodeAction(HandleVariableDeclaration, SyntaxKind.VariableDeclaration, SyntaxKind.ForEachStatement);
} }
protected abstract bool IsStylePreferred(SyntaxNode declarationStatement, SemanticModel semanticModel, OptionSet optionSet, State state, CancellationToken cancellationToken); protected abstract bool IsStylePreferred(SemanticModel semanticModel, OptionSet optionSet, State state, CancellationToken cancellationToken);
protected abstract bool TryAnalyzeVariableDeclaration(TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken, out TextSpan issueSpan); protected abstract bool TryAnalyzeVariableDeclaration(TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken, out TextSpan issueSpan);
protected abstract bool AssignmentSupportsStylePreference(SyntaxToken identifier, TypeSyntax typeName, EqualsValueClauseSyntax initializer, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken); protected abstract bool AssignmentSupportsStylePreference(SyntaxToken identifier, TypeSyntax typeName, EqualsValueClauseSyntax initializer, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken);
protected static ExpressionSyntax GetInitializerExpression(EqualsValueClauseSyntax initializer) =>
initializer.Value is CheckedExpressionSyntax
? ((CheckedExpressionSyntax)initializer.Value).Expression.WalkDownParentheses()
: initializer.Value.WalkDownParentheses();
private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context) private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context)
{ {
TypeSyntax declaredType; TypeSyntax declaredType;
State state = null;
var shouldAnalyze = false; var shouldAnalyze = false;
var declarationStatement = context.Node; var declarationStatement = context.Node;
var optionSet = GetOptionSet(context.Options); var optionSet = GetOptionSet(context.Options);
State state = null; var semanticModel = context.SemanticModel;
var cancellationToken = context.CancellationToken;
if (declarationStatement.IsKind(SyntaxKind.VariableDeclaration)) if (declarationStatement.IsKind(SyntaxKind.VariableDeclaration))
{ {
var declaration = (VariableDeclarationSyntax)declarationStatement; var declaration = (VariableDeclarationSyntax)declarationStatement;
declaredType = declaration.Type; declaredType = declaration.Type;
shouldAnalyze = ShouldAnalyzeVariableDeclaration(declaration, context.SemanticModel, context.CancellationToken); shouldAnalyze = ShouldAnalyzeVariableDeclaration(declaration, semanticModel, cancellationToken);
if (shouldAnalyze) if (shouldAnalyze)
{ {
state = State.Generate(declarationStatement, context.SemanticModel, optionSet, isVariableDeclarationContext: true, cancellationToken: context.CancellationToken); state = State.Generate(declarationStatement, semanticModel, optionSet, isVariableDeclarationContext: true, cancellationToken: cancellationToken);
shouldAnalyze = IsStylePreferred(declaration, context.SemanticModel, optionSet, state, context.CancellationToken); shouldAnalyze = IsStylePreferred(semanticModel, optionSet, state, cancellationToken);
} }
} }
else if (declarationStatement.IsKind(SyntaxKind.ForEachStatement)) else if (declarationStatement.IsKind(SyntaxKind.ForEachStatement))
...@@ -103,8 +111,8 @@ private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context) ...@@ -103,8 +111,8 @@ private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context)
var declaration = (ForEachStatementSyntax)declarationStatement; var declaration = (ForEachStatementSyntax)declarationStatement;
declaredType = declaration.Type; declaredType = declaration.Type;
state = State.Generate(declarationStatement, context.SemanticModel, optionSet, isVariableDeclarationContext: false, cancellationToken: context.CancellationToken); state = State.Generate(declarationStatement, semanticModel, optionSet, isVariableDeclarationContext: false, cancellationToken: cancellationToken);
shouldAnalyze = IsStylePreferred(declaration, context.SemanticModel, optionSet, state, context.CancellationToken); shouldAnalyze = IsStylePreferred(semanticModel, optionSet, state, cancellationToken);
} }
else else
{ {
...@@ -118,10 +126,10 @@ private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context) ...@@ -118,10 +126,10 @@ private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context)
TextSpan diagnosticSpan; TextSpan diagnosticSpan;
if (TryAnalyzeVariableDeclaration(declaredType, context.SemanticModel, optionSet, context.CancellationToken, out diagnosticSpan)) if (TryAnalyzeVariableDeclaration(declaredType, semanticModel, optionSet, cancellationToken, out diagnosticSpan))
{ {
var descriptor = _severityToDescriptorMap[state.GetDiagnosticSeverityPreference()]; var descriptor = _severityToDescriptorMap[state.GetDiagnosticSeverityPreference()];
context.ReportDiagnostic(CreateDiagnostic(descriptor.Value, declarationStatement, diagnosticSpan)); context.ReportDiagnostic(CreateDiagnostic(descriptor, declarationStatement, diagnosticSpan));
} }
} }
} }
...@@ -132,15 +140,15 @@ private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context) ...@@ -132,15 +140,15 @@ private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context)
private bool ShouldAnalyzeVariableDeclaration(VariableDeclarationSyntax variableDeclaration, SemanticModel semanticModel, CancellationToken cancellationToken) private bool ShouldAnalyzeVariableDeclaration(VariableDeclarationSyntax variableDeclaration, SemanticModel semanticModel, CancellationToken cancellationToken)
{ {
// var is applicable only for local variables. // var is applicable only for local variables.
if (variableDeclaration.Parent.IsKind(SyntaxKind.FieldDeclaration) || if (variableDeclaration.IsParentKind(SyntaxKind.FieldDeclaration,
variableDeclaration.Parent.IsKind(SyntaxKind.EventFieldDeclaration)) SyntaxKind.EventFieldDeclaration))
{ {
return false; return false;
} }
// implicitly typed variables cannot have multiple declarators and // implicitly typed variables cannot have multiple declarators and
// must have an initializer. // must have an initializer.
if (variableDeclaration.Variables.Count > 1 || if (variableDeclaration.Variables.Count != 1 ||
!variableDeclaration.Variables.Single().Initializer.IsKind(SyntaxKind.EqualsValueClause)) !variableDeclaration.Variables.Single().Initializer.IsKind(SyntaxKind.EqualsValueClause))
{ {
return false; return false;
......
...@@ -15,10 +15,10 @@ namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.TypingStyles ...@@ -15,10 +15,10 @@ namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.TypingStyles
internal sealed class CSharpUseExplicitTypingDiagnosticAnalyzer : CSharpTypingStyleDiagnosticAnalyzerBase internal sealed class CSharpUseExplicitTypingDiagnosticAnalyzer : CSharpTypingStyleDiagnosticAnalyzerBase
{ {
private static readonly LocalizableString s_Title = private static readonly LocalizableString s_Title =
new LocalizableResourceString(nameof(CSharpFeaturesResources.UseExplicitTypingDiagnosticTitle), CSharpFeaturesResources.ResourceManager, typeof(CSharpFeaturesResources)); new LocalizableResourceString(nameof(CSharpFeaturesResources.UseExplicitTypeDiagnosticTitle), CSharpFeaturesResources.ResourceManager, typeof(CSharpFeaturesResources));
private static readonly LocalizableString s_Message = private static readonly LocalizableString s_Message =
new LocalizableResourceString(nameof(CSharpFeaturesResources.UseExplicitTyping), CSharpFeaturesResources.ResourceManager, typeof(CSharpFeaturesResources)); new LocalizableResourceString(nameof(CSharpFeaturesResources.UseExplicitType), CSharpFeaturesResources.ResourceManager, typeof(CSharpFeaturesResources));
public CSharpUseExplicitTypingDiagnosticAnalyzer() public CSharpUseExplicitTypingDiagnosticAnalyzer()
: base(diagnosticId: IDEDiagnosticIds.UseExplicitTypingDiagnosticId, : base(diagnosticId: IDEDiagnosticIds.UseExplicitTypingDiagnosticId,
...@@ -27,9 +27,9 @@ public CSharpUseExplicitTypingDiagnosticAnalyzer() ...@@ -27,9 +27,9 @@ public CSharpUseExplicitTypingDiagnosticAnalyzer()
{ {
} }
protected override bool IsStylePreferred(SyntaxNode declarationStatement, SemanticModel semanticModel, OptionSet optionSet, State state, CancellationToken cancellationToken) protected override bool IsStylePreferred(SemanticModel semanticModel, OptionSet optionSet, State state, CancellationToken cancellationToken)
{ {
var stylePreferences = state.StylePreferences; var stylePreferences = state.TypeStyle;
var shouldNotify = state.ShouldNotify(); var shouldNotify = state.ShouldNotify();
// If notification preference is None, don't offer the suggestion. // If notification preference is None, don't offer the suggestion.
...@@ -40,15 +40,15 @@ protected override bool IsStylePreferred(SyntaxNode declarationStatement, Semant ...@@ -40,15 +40,15 @@ protected override bool IsStylePreferred(SyntaxNode declarationStatement, Semant
if (state.IsInIntrinsicTypeContext) if (state.IsInIntrinsicTypeContext)
{ {
return !stylePreferences.HasFlag(TypingStyles.VarForIntrinsic); return !stylePreferences.HasFlag(TypeStyle.ImplicitTypeForIntrinsicTypes);
} }
else if (state.IsTypingApparentInContext) else if (state.IsTypingApparentInContext)
{ {
return !stylePreferences.HasFlag(TypingStyles.VarWhereApparent); return !stylePreferences.HasFlag(TypeStyle.ImplicitTypeWhereApparent);
} }
else else
{ {
return !stylePreferences.HasFlag(TypingStyles.VarWherePossible); return !stylePreferences.HasFlag(TypeStyle.ImplicitTypeWherePossible);
} }
} }
......
...@@ -17,10 +17,10 @@ internal sealed class CSharpUseImplicitTypingDiagnosticAnalyzer : CSharpTypingSt ...@@ -17,10 +17,10 @@ internal sealed class CSharpUseImplicitTypingDiagnosticAnalyzer : CSharpTypingSt
{ {
private static readonly LocalizableString s_Title = private static readonly LocalizableString s_Title =
new LocalizableResourceString(nameof(CSharpFeaturesResources.UseImplicitTypingDiagnosticTitle), CSharpFeaturesResources.ResourceManager, typeof(CSharpFeaturesResources)); new LocalizableResourceString(nameof(CSharpFeaturesResources.UseImplicitTypeDiagnosticTitle), CSharpFeaturesResources.ResourceManager, typeof(CSharpFeaturesResources));
private static readonly LocalizableString s_Message = private static readonly LocalizableString s_Message =
new LocalizableResourceString(nameof(CSharpFeaturesResources.UseImplicitTyping), CSharpFeaturesResources.ResourceManager, typeof(CSharpFeaturesResources)); new LocalizableResourceString(nameof(CSharpFeaturesResources.UseImplicitType), CSharpFeaturesResources.ResourceManager, typeof(CSharpFeaturesResources));
public CSharpUseImplicitTypingDiagnosticAnalyzer() public CSharpUseImplicitTypingDiagnosticAnalyzer()
: base(diagnosticId: IDEDiagnosticIds.UseImplicitTypingDiagnosticId, : base(diagnosticId: IDEDiagnosticIds.UseImplicitTypingDiagnosticId,
...@@ -29,9 +29,9 @@ public CSharpUseImplicitTypingDiagnosticAnalyzer() ...@@ -29,9 +29,9 @@ public CSharpUseImplicitTypingDiagnosticAnalyzer()
{ {
} }
protected override bool IsStylePreferred(SyntaxNode declarationStatement, SemanticModel semanticModel, OptionSet optionSet, State state, CancellationToken cancellationToken) protected override bool IsStylePreferred(SemanticModel semanticModel, OptionSet optionSet, State state, CancellationToken cancellationToken)
{ {
var stylePreferences = state.StylePreferences; var stylePreferences = state.TypeStyle;
var shouldNotify = state.ShouldNotify(); var shouldNotify = state.ShouldNotify();
// If notification preference is None, don't offer the suggestion. // If notification preference is None, don't offer the suggestion.
...@@ -42,25 +42,24 @@ protected override bool IsStylePreferred(SyntaxNode declarationStatement, Semant ...@@ -42,25 +42,24 @@ protected override bool IsStylePreferred(SyntaxNode declarationStatement, Semant
if (state.IsInIntrinsicTypeContext) if (state.IsInIntrinsicTypeContext)
{ {
return stylePreferences.HasFlag(TypingStyles.VarForIntrinsic); return stylePreferences.HasFlag(TypeStyle.ImplicitTypeForIntrinsicTypes);
} }
else if (state.IsTypingApparentInContext) else if (state.IsTypingApparentInContext)
{ {
return stylePreferences.HasFlag(TypingStyles.VarWhereApparent); return stylePreferences.HasFlag(TypeStyle.ImplicitTypeWhereApparent);
} }
else else
{ {
return stylePreferences.HasFlag(TypingStyles.VarWherePossible); return stylePreferences.HasFlag(TypeStyle.ImplicitTypeWherePossible);
} }
} }
protected override bool TryAnalyzeVariableDeclaration(TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken, out TextSpan issueSpan) protected override bool TryAnalyzeVariableDeclaration(TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken, out TextSpan issueSpan)
{ {
issueSpan = default(TextSpan);
// If it is already var, return. // If it is already var, return.
if (typeName.IsTypeInferred(semanticModel)) if (typeName.IsTypeInferred(semanticModel))
{ {
issueSpan = default(TextSpan);
return false; return false;
} }
...@@ -74,6 +73,7 @@ protected override bool TryAnalyzeVariableDeclaration(TypeSyntax typeName, Seman ...@@ -74,6 +73,7 @@ protected override bool TryAnalyzeVariableDeclaration(TypeSyntax typeName, Seman
var conflict = semanticModel.GetSpeculativeSymbolInfo(typeName.SpanStart, candidateReplacementNode, SpeculativeBindingOption.BindAsTypeOrNamespace).Symbol; var conflict = semanticModel.GetSpeculativeSymbolInfo(typeName.SpanStart, candidateReplacementNode, SpeculativeBindingOption.BindAsTypeOrNamespace).Symbol;
if (conflict?.IsKind(SymbolKind.NamedType) == true) if (conflict?.IsKind(SymbolKind.NamedType) == true)
{ {
issueSpan = default(TextSpan);
return false; return false;
} }
...@@ -85,6 +85,7 @@ protected override bool TryAnalyzeVariableDeclaration(TypeSyntax typeName, Seman ...@@ -85,6 +85,7 @@ protected override bool TryAnalyzeVariableDeclaration(TypeSyntax typeName, Seman
// implicitly typed variables cannot be constants. // implicitly typed variables cannot be constants.
if ((variableDeclaration.Parent as LocalDeclarationStatementSyntax)?.IsConst == true) if ((variableDeclaration.Parent as LocalDeclarationStatementSyntax)?.IsConst == true)
{ {
issueSpan = default(TextSpan);
return false; return false;
} }
...@@ -92,14 +93,17 @@ protected override bool TryAnalyzeVariableDeclaration(TypeSyntax typeName, Seman ...@@ -92,14 +93,17 @@ protected override bool TryAnalyzeVariableDeclaration(TypeSyntax typeName, Seman
if (AssignmentSupportsStylePreference(variable.Identifier, typeName, variable.Initializer, semanticModel, optionSet, cancellationToken)) if (AssignmentSupportsStylePreference(variable.Identifier, typeName, variable.Initializer, semanticModel, optionSet, cancellationToken))
{ {
issueSpan = candidateIssueSpan; issueSpan = candidateIssueSpan;
return true;
} }
} }
else if (typeName.IsParentKind(SyntaxKind.ForEachStatement)) else if (typeName.IsParentKind(SyntaxKind.ForEachStatement))
{ {
issueSpan = candidateIssueSpan; issueSpan = candidateIssueSpan;
return true;
} }
return issueSpan != default(TextSpan); issueSpan = default(TextSpan);
return false;
} }
/// <summary> /// <summary>
...@@ -111,7 +115,7 @@ protected override bool TryAnalyzeVariableDeclaration(TypeSyntax typeName, Seman ...@@ -111,7 +115,7 @@ protected override bool TryAnalyzeVariableDeclaration(TypeSyntax typeName, Seman
/// </returns> /// </returns>
protected override bool AssignmentSupportsStylePreference(SyntaxToken identifier, TypeSyntax typeName, EqualsValueClauseSyntax initializer, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken) protected override bool AssignmentSupportsStylePreference(SyntaxToken identifier, TypeSyntax typeName, EqualsValueClauseSyntax initializer, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken)
{ {
var expression = initializer.Value; var expression = GetInitializerExpression(initializer);
// var cannot be assigned null // var cannot be assigned null
if (expression.IsKind(SyntaxKind.NullLiteralExpression)) if (expression.IsKind(SyntaxKind.NullLiteralExpression))
...@@ -121,9 +125,8 @@ protected override bool AssignmentSupportsStylePreference(SyntaxToken identifier ...@@ -121,9 +125,8 @@ protected override bool AssignmentSupportsStylePreference(SyntaxToken identifier
// cannot use implicit typing on method group, anonymous function or on dynamic // cannot use implicit typing on method group, anonymous function or on dynamic
var declaredType = semanticModel.GetTypeInfo(typeName, cancellationToken).Type; var declaredType = semanticModel.GetTypeInfo(typeName, cancellationToken).Type;
if (declaredType != null if (declaredType != null &&
&& (declaredType.TypeKind == TypeKind.Delegate (declaredType.TypeKind == TypeKind.Delegate || declaredType.TypeKind == TypeKind.Dynamic))
|| declaredType.TypeKind == TypeKind.Dynamic))
{ {
return false; return false;
} }
......
...@@ -36,7 +36,7 @@ internal static class PredefinedCodeFixProviderNames ...@@ -36,7 +36,7 @@ internal static class PredefinedCodeFixProviderNames
public const string Suppression = nameof(Suppression); public const string Suppression = nameof(Suppression);
public const string AddOverloads = "Add Overloads to member"; public const string AddOverloads = "Add Overloads to member";
public const string AddNew = "Add new keyword to member"; public const string AddNew = "Add new keyword to member";
public const string UseImplicitTyping = "Use var"; public const string UseImplicitTyping = nameof(UseImplicitTyping);
public const string UseExplicitTyping = "Use typename instead of var"; public const string UseExplicitTyping = nameof(UseExplicitTyping);
} }
} }
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // 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.Runtime.Serialization;
namespace Microsoft.CodeAnalysis.CodeStyle namespace Microsoft.CodeAnalysis.CodeStyle
{ {
[DataContract]
internal class NotificationOption internal class NotificationOption
{ {
public string Name { get; } [DataMember]
public DiagnosticSeverity Value { get; } public string Name { get; set; }
[DataMember]
public DiagnosticSeverity Value { get; set; }
public static readonly NotificationOption None = new NotificationOption(nameof(None), DiagnosticSeverity.Hidden); public static readonly NotificationOption None = new NotificationOption(nameof(None), DiagnosticSeverity.Hidden);
public static readonly NotificationOption Info = new NotificationOption(nameof(Info), DiagnosticSeverity.Info); public static readonly NotificationOption Info = new NotificationOption(nameof(Info), DiagnosticSeverity.Info);
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // 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.Runtime.Serialization;
namespace Microsoft.CodeAnalysis.CodeStyle namespace Microsoft.CodeAnalysis.CodeStyle
{ {
[DataContract]
internal class SimpleCodeStyleOption internal class SimpleCodeStyleOption
{ {
public static readonly SimpleCodeStyleOption Default = new SimpleCodeStyleOption(false, NotificationOption.None); public static readonly SimpleCodeStyleOption Default = new SimpleCodeStyleOption(false, NotificationOption.None);
...@@ -12,8 +15,10 @@ public SimpleCodeStyleOption(bool isChecked, NotificationOption notification) ...@@ -12,8 +15,10 @@ public SimpleCodeStyleOption(bool isChecked, NotificationOption notification)
Notification = notification; Notification = notification;
} }
[DataMember]
public bool IsChecked { get; set; } public bool IsChecked { get; set; }
[DataMember]
public NotificationOption Notification { get; set; } public NotificationOption Notification { get; set; }
} }
} }
...@@ -158,6 +158,7 @@ ...@@ -158,6 +158,7 @@
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" /> <Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Windows.Forms" /> <Reference Include="System.Windows.Forms" />
<Reference Include="System.Xaml" /> <Reference Include="System.Xaml" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
...@@ -206,6 +207,7 @@ ...@@ -206,6 +207,7 @@
<Compile Include="ObjectBrowser\ListItemFactory.cs" /> <Compile Include="ObjectBrowser\ListItemFactory.cs" />
<Compile Include="Options\AdvancedOptionPageStrings.cs" /> <Compile Include="Options\AdvancedOptionPageStrings.cs" />
<Compile Include="Options\IntelliSenseOptionPageStrings.cs" /> <Compile Include="Options\IntelliSenseOptionPageStrings.cs" />
<Compile Include="Options\SerializationHelpers.cs" />
<Compile Include="Venus\CSharpAdditionalFormattingRuleLanguageService.cs" /> <Compile Include="Venus\CSharpAdditionalFormattingRuleLanguageService.cs" />
<Compile Include="CSharpPackage.cs" /> <Compile Include="CSharpPackage.cs" />
<Compile Include="CSharpVSResources.Designer.cs"> <Compile Include="CSharpVSResources.Designer.cs">
......
...@@ -459,42 +459,42 @@ public int Style_UseVarWhenDeclaringLocals ...@@ -459,42 +459,42 @@ public int Style_UseVarWhenDeclaringLocals
set { SetBooleanOption(CSharpCodeStyleOptions.UseVarWhenDeclaringLocals, value); } set { SetBooleanOption(CSharpCodeStyleOptions.UseVarWhenDeclaringLocals, value); }
} }
public int Style_UseVarWherePossible public string Style_UseVarWherePossible
{ {
get get
{ {
var option = _optionService.GetOption(CSharpCodeStyleOptions.UseVarWherePossible); var option = _optionService.GetOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible);
return GetUseVarOption(option); return GetUseVarOption(option);
} }
set set
{ {
SetUseVarOption(CSharpCodeStyleOptions.UseVarWherePossible, value); SetUseVarOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, value);
} }
} }
public int Style_UseVarWhenTypeIsApparent public string Style_UseVarWhenTypeIsApparent
{ {
get get
{ {
var option = _optionService.GetOption(CSharpCodeStyleOptions.UseVarWhenTypeIsApparent); var option = _optionService.GetOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent);
return GetUseVarOption(option); return GetUseVarOption(option);
} }
set set
{ {
SetUseVarOption(CSharpCodeStyleOptions.UseVarWhenTypeIsApparent, value); SetUseVarOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, value);
} }
} }
public int Style_UseVarForIntrinsicTypes public string Style_UseVarForIntrinsicTypes
{ {
get get
{ {
var option = _optionService.GetOption(CSharpCodeStyleOptions.UseVarForIntrinsicTypes); var option = _optionService.GetOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes);
return GetUseVarOption(option); return GetUseVarOption(option);
} }
set set
{ {
SetUseVarOption(CSharpCodeStyleOptions.UseVarForIntrinsicTypes, value); SetUseVarOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, value);
} }
} }
...@@ -562,49 +562,17 @@ private void SetBooleanOption(PerLanguageOption<bool> key, int value) ...@@ -562,49 +562,17 @@ private void SetBooleanOption(PerLanguageOption<bool> key, int value)
_optionService.SetOptions(optionSet); _optionService.SetOptions(optionSet);
} }
private static int GetUseVarOption(SimpleCodeStyleOption option) private static string GetUseVarOption(SimpleCodeStyleOption option)
{ {
var offset = option.IsChecked ? 0 : Enum.GetValues(typeof(DiagnosticSeverity)).Length; return option.SerializeObject();
var baseValue = (int)option.Notification.Value;
return offset + baseValue;
} }
private void SetUseVarOption(Option<SimpleCodeStyleOption> option, int value) private void SetUseVarOption(Option<SimpleCodeStyleOption> option, string value)
{ {
SimpleCodeStyleOption convertedValue = SimpleCodeStyleOption.Default; SimpleCodeStyleOption convertedValue = SimpleCodeStyleOption.Default;
var optionSet = _optionService.GetOptions(); var optionSet = _optionService.GetOptions();
switch (value)
{
case 0:
convertedValue = new SimpleCodeStyleOption(true, NotificationOption.None);
break;
case 1:
convertedValue = new SimpleCodeStyleOption(true, NotificationOption.Info);
break;
case 2:
convertedValue = new SimpleCodeStyleOption(true, NotificationOption.Warning);
break;
case 3:
convertedValue = new SimpleCodeStyleOption(true, NotificationOption.Error);
break;
case 4:
convertedValue = new SimpleCodeStyleOption(false, NotificationOption.None);
break;
case 5:
convertedValue = new SimpleCodeStyleOption(false, NotificationOption.Info);
break;
case 6:
convertedValue = new SimpleCodeStyleOption(false, NotificationOption.Warning);
break;
case 7:
convertedValue = new SimpleCodeStyleOption(false, NotificationOption.Error);
break;
default:
break;
}
convertedValue = (SimpleCodeStyleOption)value.DeserializeObject<SimpleCodeStyleOption>();
optionSet = optionSet.WithChangedOption(option, convertedValue); optionSet = optionSet.WithChangedOption(option, convertedValue);
_optionService.SetOptions(optionSet); _optionService.SetOptions(optionSet);
} }
......
...@@ -211,19 +211,19 @@ public override bool TryFetch(OptionKey optionKey, out object value) ...@@ -211,19 +211,19 @@ public override bool TryFetch(OptionKey optionKey, out object value)
} }
// code style: use var options. // code style: use var options.
if (optionKey.Option == CSharpCodeStyleOptions.UseVarForIntrinsicTypes) if (optionKey.Option == CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes)
{ {
var useVarValue = this.Manager.GetValueOrDefault(Style_UseVarForIntrinsicTypes, defaultValue: 0); var useVarValue = this.Manager.GetValueOrDefault<string>(Style_UseVarForIntrinsicTypes);
return FetchUseVarOption(useVarValue, out value); return FetchUseVarOption(useVarValue, out value);
} }
else if (optionKey.Option == CSharpCodeStyleOptions.UseVarWhenTypeIsApparent) else if (optionKey.Option == CSharpCodeStyleOptions.UseImplicitTypeWhereApparent)
{ {
var useVarValue = this.Manager.GetValueOrDefault(Style_UseVarWhenTypeIsApparent, defaultValue: 0); var useVarValue = this.Manager.GetValueOrDefault<string>(Style_UseVarWhenTypeIsApparent);
return FetchUseVarOption(useVarValue, out value); return FetchUseVarOption(useVarValue, out value);
} }
else if (optionKey.Option == CSharpCodeStyleOptions.UseVarWherePossible) else if (optionKey.Option == CSharpCodeStyleOptions.UseImplicitTypeWherePossible)
{ {
var useVarValue = this.Manager.GetValueOrDefault(Style_UseVarWherePossible, defaultValue: 0); var useVarValue = this.Manager.GetValueOrDefault<string>(Style_UseVarWherePossible);
return FetchUseVarOption(useVarValue, out value); return FetchUseVarOption(useVarValue, out value);
} }
...@@ -297,15 +297,15 @@ public override bool TryPersist(OptionKey optionKey, object value) ...@@ -297,15 +297,15 @@ public override bool TryPersist(OptionKey optionKey, object value)
} }
// code style: use var options. // code style: use var options.
if (optionKey.Option == CSharpCodeStyleOptions.UseVarForIntrinsicTypes) if (optionKey.Option == CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes)
{ {
return PersistUseVarOption(Style_UseVarForIntrinsicTypes, value); return PersistUseVarOption(Style_UseVarForIntrinsicTypes, value);
} }
else if (optionKey.Option == CSharpCodeStyleOptions.UseVarWhenTypeIsApparent) else if (optionKey.Option == CSharpCodeStyleOptions.UseImplicitTypeWhereApparent)
{ {
return PersistUseVarOption(Style_UseVarWhenTypeIsApparent, value); return PersistUseVarOption(Style_UseVarWhenTypeIsApparent, value);
} }
else if (optionKey.Option == CSharpCodeStyleOptions.UseVarWherePossible) else if (optionKey.Option == CSharpCodeStyleOptions.UseImplicitTypeWherePossible)
{ {
return PersistUseVarOption(Style_UseVarWherePossible, value); return PersistUseVarOption(Style_UseVarWherePossible, value);
} }
...@@ -315,48 +315,23 @@ public override bool TryPersist(OptionKey optionKey, object value) ...@@ -315,48 +315,23 @@ public override bool TryPersist(OptionKey optionKey, object value)
private bool PersistUseVarOption(string option, object value) private bool PersistUseVarOption(string option, object value)
{ {
var convertedValue = (SimpleCodeStyleOption)value; var serializedValue = ((SimpleCodeStyleOption)value).SerializeObject();
var offset = convertedValue.IsChecked ? 0 : Enum.GetValues(typeof(DiagnosticSeverity)).Length; this.Manager.SetValueAsync(option, value: serializedValue, isMachineLocal: false);
var baseValue = (int)convertedValue.Notification.Value;
this.Manager.SetValueAsync(option, value: baseValue + offset, isMachineLocal: false);
return true; return true;
} }
private static bool FetchUseVarOption(int useVarOptionValue, out object value) private static bool FetchUseVarOption(string useVarOptionValue, out object value)
{ {
switch (useVarOptionValue) if (string.IsNullOrEmpty(useVarOptionValue))
{ {
case 0: value = SimpleCodeStyleOption.Default;
value = new SimpleCodeStyleOption(true, NotificationOption.None); }
break; else
case 1: {
value = new SimpleCodeStyleOption(true, NotificationOption.Info); value = useVarOptionValue.DeserializeObject<SimpleCodeStyleOption>();
break;
case 2:
value = new SimpleCodeStyleOption(true, NotificationOption.Warning);
break;
case 3:
value = new SimpleCodeStyleOption(true, NotificationOption.Error);
break;
case 4:
value = new SimpleCodeStyleOption(false, NotificationOption.None);
break;
case 5:
value = new SimpleCodeStyleOption(false, NotificationOption.Info);
break;
case 6:
value = new SimpleCodeStyleOption(false, NotificationOption.Warning);
break;
case 7:
value = new SimpleCodeStyleOption(false, NotificationOption.Error);
break;
default:
value = null;
break;
} }
return value != null; return true;
} }
} }
} }
\ No newline at end of file
...@@ -191,9 +191,9 @@ internal StyleViewModel(OptionSet optionSet, IServiceProvider serviceProvider) : ...@@ -191,9 +191,9 @@ internal StyleViewModel(OptionSet optionSet, IServiceProvider serviceProvider) :
new NotificationOptionViewModel(NotificationOption.Error, KnownMonikers.StatusError) new NotificationOptionViewModel(NotificationOption.Error, KnownMonikers.StatusError)
}; };
Items.Add(new CheckBoxWithComboOptionViewModel(CSharpCodeStyleOptions.UseVarForIntrinsicTypes, CSharpVSResources.UseVarForIntrinsicTypes, s_varForIntrinsicsPreviewTrue, s_varForIntrinsicsPreviewFalse, this, optionSet, notificationOptions)); Items.Add(new CheckBoxWithComboOptionViewModel(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, CSharpVSResources.UseVarForIntrinsicTypes, s_varForIntrinsicsPreviewTrue, s_varForIntrinsicsPreviewFalse, this, optionSet, notificationOptions));
Items.Add(new CheckBoxWithComboOptionViewModel(CSharpCodeStyleOptions.UseVarWhenTypeIsApparent, CSharpVSResources.UseVarWhenTypeIsApparent, s_varWhereApparentPreviewTrue, s_varWhereApparentPreviewFalse, this, optionSet, notificationOptions)); Items.Add(new CheckBoxWithComboOptionViewModel(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, CSharpVSResources.UseVarWhenTypeIsApparent, s_varWhereApparentPreviewTrue, s_varWhereApparentPreviewFalse, this, optionSet, notificationOptions));
Items.Add(new CheckBoxWithComboOptionViewModel(CSharpCodeStyleOptions.UseVarWherePossible, CSharpVSResources.UseVarWhenPossible, s_varWherePossiblePreviewTrue, s_varWherePossiblePreviewFalse, this, optionSet, notificationOptions)); Items.Add(new CheckBoxWithComboOptionViewModel(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, CSharpVSResources.UseVarWhenPossible, s_varWherePossiblePreviewTrue, s_varWherePossiblePreviewFalse, this, optionSet, notificationOptions));
} }
} }
} }
using System.IO;
using System.Runtime.Serialization;
using System.Text;
namespace Microsoft.VisualStudio.LanguageServices.CSharp.Options
{
internal static class SerializationHelpers
{
public static string SerializeObject<T>(this T toSerialize)
{
using (var stream = new MemoryStream())
{
var serializer = new DataContractSerializer(typeof(T));
serializer.WriteObject(stream, toSerialize);
stream.Seek(0, SeekOrigin.Begin);
using (var streamReader = new StreamReader(stream))
{
return streamReader.ReadToEnd();
}
}
}
public static object DeserializeObject<T>(this string toDeserialize)
{
using (var stream = new MemoryStream())
{
var data = Encoding.UTF8.GetBytes(toDeserialize);
stream.Write(data, 0, data.Length);
stream.Seek(0, SeekOrigin.Begin);
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
return serializer.ReadObject(stream);
}
}
}
}
...@@ -33,7 +33,7 @@ public CheckBoxWithComboOptionViewModel(IOption option, string description, stri ...@@ -33,7 +33,7 @@ public CheckBoxWithComboOptionViewModel(IOption option, string description, stri
var codeStyleOption = ((SimpleCodeStyleOption)options.GetOption(new OptionKey(option, option.IsPerLanguage ? info.Language : null))); var codeStyleOption = ((SimpleCodeStyleOption)options.GetOption(new OptionKey(option, option.IsPerLanguage ? info.Language : null)));
SetProperty(ref _isChecked, codeStyleOption.IsChecked); SetProperty(ref _isChecked, codeStyleOption.IsChecked);
var notificationViewModel = items.Where(i => i.Notification == codeStyleOption.Notification).Single(); var notificationViewModel = items.Where(i => i.Notification.Value == codeStyleOption.Notification.Value).Single();
SetProperty(ref _selectedNotificationOption, notificationViewModel); SetProperty(ref _selectedNotificationOption, notificationViewModel);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册