Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CA2246 Warning for unobvious assignment #2717

Merged
merged 19 commits into from Sep 12, 2019
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,97 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Immutable;
using Analyzer.Utilities;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;

namespace Microsoft.CodeQuality.Analyzers.QualityGuidelines
{
/// <summary>
/// CA2246: Prevent objects from being referenced in statements where they are reassigned
/// </summary>
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
maxkoshevoi marked this conversation as resolved.
Show resolved Hide resolved
public sealed class AssigningSymbolAndItsMemberInSameStatement : DiagnosticAnalyzer
{
internal const string RuleId = "CA2246";

private static readonly LocalizableString s_localizableTitle = new LocalizableResourceString(nameof(MicrosoftQualityGuidelinesAnalyzersResources.AssigningSymbolAndItsMemberInSameStatementTitle), MicrosoftQualityGuidelinesAnalyzersResources.ResourceManager, typeof(MicrosoftQualityGuidelinesAnalyzersResources));
private static readonly LocalizableString s_localizableMessage = new LocalizableResourceString(nameof(MicrosoftQualityGuidelinesAnalyzersResources.AssigningSymbolAndItsMemberInSameStatementMessage), MicrosoftQualityGuidelinesAnalyzersResources.ResourceManager, typeof(MicrosoftQualityGuidelinesAnalyzersResources));
private static readonly LocalizableString s_localizableDescription = new LocalizableResourceString(nameof(MicrosoftQualityGuidelinesAnalyzersResources.AssigningSymbolAndItsMemberInSameStatementDescription), MicrosoftQualityGuidelinesAnalyzersResources.ResourceManager, typeof(MicrosoftQualityGuidelinesAnalyzersResources));

internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor(RuleId,
s_localizableTitle,
s_localizableMessage,
DiagnosticCategory.Usage,
DiagnosticHelpers.DefaultDiagnosticSeverity,
DiagnosticHelpers.EnabledByDefaultIfNotBuildingVSIX,
s_localizableDescription);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);

public override void Initialize(AnalysisContext context)
{
context.RegisterOperationAction(AnalyzeAssignment, OperationKind.SimpleAssignment);
}

private void AnalyzeAssignment(OperationAnalysisContext context)
{
var assignmentOperation = (ISimpleAssignmentOperation)context.Operation;

// Check if there are more then one assignment in a statement
if (!(assignmentOperation.Target is IMemberReferenceOperation operationTarget))
{
return;
}

// This analyzer makes sense only for reference type objects
if (operationTarget.Instance?.Type.IsValueType == true)
{
return;
}

// Search for object equal to operationTarget.Instance further in assignment chain
bool isViolationFound = false;
if (operationTarget.Instance is ILocalReferenceOperation localInstance)
{
isViolationFound = AnalyzeAssignmentToMember(assignmentOperation, localInstance, (a, b) => a.Local == b.Local);
}
else if (operationTarget.Instance is IMemberReferenceOperation memberInstance)
{
isViolationFound = AnalyzeAssignmentToMember(assignmentOperation, memberInstance, (a, b) => a.Member == b.Member && a.Instance?.Syntax.ToString() == b.Instance?.Syntax.ToString());
}
else if (operationTarget.Instance is IParameterReferenceOperation parameterInstance)
{
isViolationFound = AnalyzeAssignmentToMember(assignmentOperation, parameterInstance, (a, b) => a.Parameter == b.Parameter);
}
else
{
return;
}

if (isViolationFound)
{
var diagnostic = Diagnostic.Create(Rule, operationTarget.Syntax.GetLocation(), operationTarget.Instance.Syntax.ToString());
maxkoshevoi marked this conversation as resolved.
Show resolved Hide resolved
context.ReportDiagnostic(diagnostic);
}
}

private static bool AnalyzeAssignmentToMember<T>(ISimpleAssignmentOperation assignmentOperation, T instance, Func<T, T, bool> equalityComparer) where T : class, IOperation
{
// Check every simple assignments target in a statement for equality to `instance`
while (assignmentOperation.Value.Kind == OperationKind.SimpleAssignment)
{
assignmentOperation = (ISimpleAssignmentOperation)assignmentOperation.Value;

var operationValue = assignmentOperation.Target as T;
if (equalityComparer(instance, operationValue))
{
return true;
}
}
return false;
}
}
}
Expand Up @@ -252,4 +252,13 @@
<data name="AvoidPropertySelfAssignmentMessage" xml:space="preserve">
<value>The property {0} should not be assigned to itself.</value>
</data>
</root>
<data name="AssigningSymbolAndItsMemberInSameStatementMessage" xml:space="preserve">
<value>Symbol '{0}' and its member '{1}' are both assigned in the same statement. You are at risk of assigning the member of an unintended object.</value>
</data>
<data name="AssigningSymbolAndItsMemberInSameStatementTitle" xml:space="preserve">
<value>Assigning symbol and its member in the same statement.</value>
</data>
<data name="AssigningSymbolAndItsMemberInSameStatementDescription" xml:space="preserve">
<value>Assigning to a symbol and its member (field/property) in the same statement is not recommended. It is not clear if the member access was intended to use symbol's old value prior to the assignment or new value from the assignment in this statement. For clarity, consider splitting the assignments into separate statements.</value>
</data>
</root>
Expand Up @@ -2,6 +2,21 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="cs" original="../MicrosoftQualityGuidelinesAnalyzersResources.resx">
<body>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementDescription">
<source>Assigning to a symbol and its member (field/property) in the same statement is not recommended. It is not clear if the member access was intended to use symbol's old value prior to the assignment or new value from the assignment in this statement. For clarity, consider splitting the assignments into separate statements.</source>
<target state="new">Assigning to a symbol and its member (field/property) in the same statement is not recommended. It is not clear if the member access was intended to use symbol's old value prior to the assignment or new value from the assignment in this statement. For clarity, consider splitting the assignments into separate statements.</target>
<note />
</trans-unit>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementMessage">
<source>Symbol '{0}' and its member '{1}' are both assigned in the same statement. You are at risk of assigning the member of an unintended object.</source>
<target state="new">Symbol '{0}' and its member '{1}' are both assigned in the same statement. You are at risk of assigning the member of an unintended object.</target>
<note />
</trans-unit>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementTitle">
<source>Assigning symbol and its member in the same statement.</source>
<target state="new">Assigning symbol and its member in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPropertySelfAssignmentMessage">
<source>The property {0} should not be assigned to itself.</source>
<target state="translated">Vlastnost {0} nesmí být přiřazena sama k sobě.</target>
Expand Down
Expand Up @@ -2,6 +2,21 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="de" original="../MicrosoftQualityGuidelinesAnalyzersResources.resx">
<body>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementDescription">
<source>Assigning to a symbol and its member (field/property) in the same statement is not recommended. It is not clear if the member access was intended to use symbol's old value prior to the assignment or new value from the assignment in this statement. For clarity, consider splitting the assignments into separate statements.</source>
<target state="new">Assigning to a symbol and its member (field/property) in the same statement is not recommended. It is not clear if the member access was intended to use symbol's old value prior to the assignment or new value from the assignment in this statement. For clarity, consider splitting the assignments into separate statements.</target>
<note />
</trans-unit>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementMessage">
<source>Symbol '{0}' and its member '{1}' are both assigned in the same statement. You are at risk of assigning the member of an unintended object.</source>
<target state="new">Symbol '{0}' and its member '{1}' are both assigned in the same statement. You are at risk of assigning the member of an unintended object.</target>
<note />
</trans-unit>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementTitle">
<source>Assigning symbol and its member in the same statement.</source>
<target state="new">Assigning symbol and its member in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPropertySelfAssignmentMessage">
<source>The property {0} should not be assigned to itself.</source>
<target state="translated">Die Eigenschaft "{0}" darf nicht sich selbst zugewiesen werden.</target>
Expand Down
Expand Up @@ -2,6 +2,21 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="es" original="../MicrosoftQualityGuidelinesAnalyzersResources.resx">
<body>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementDescription">
<source>Assigning to a symbol and its member (field/property) in the same statement is not recommended. It is not clear if the member access was intended to use symbol's old value prior to the assignment or new value from the assignment in this statement. For clarity, consider splitting the assignments into separate statements.</source>
<target state="new">Assigning to a symbol and its member (field/property) in the same statement is not recommended. It is not clear if the member access was intended to use symbol's old value prior to the assignment or new value from the assignment in this statement. For clarity, consider splitting the assignments into separate statements.</target>
<note />
</trans-unit>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementMessage">
<source>Symbol '{0}' and its member '{1}' are both assigned in the same statement. You are at risk of assigning the member of an unintended object.</source>
<target state="new">Symbol '{0}' and its member '{1}' are both assigned in the same statement. You are at risk of assigning the member of an unintended object.</target>
<note />
</trans-unit>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementTitle">
<source>Assigning symbol and its member in the same statement.</source>
<target state="new">Assigning symbol and its member in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPropertySelfAssignmentMessage">
<source>The property {0} should not be assigned to itself.</source>
<target state="translated">La propiedad {0} no debe asignarse a sí misma.</target>
Expand Down
Expand Up @@ -2,6 +2,21 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="fr" original="../MicrosoftQualityGuidelinesAnalyzersResources.resx">
<body>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementDescription">
<source>Assigning to a symbol and its member (field/property) in the same statement is not recommended. It is not clear if the member access was intended to use symbol's old value prior to the assignment or new value from the assignment in this statement. For clarity, consider splitting the assignments into separate statements.</source>
<target state="new">Assigning to a symbol and its member (field/property) in the same statement is not recommended. It is not clear if the member access was intended to use symbol's old value prior to the assignment or new value from the assignment in this statement. For clarity, consider splitting the assignments into separate statements.</target>
<note />
</trans-unit>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementMessage">
<source>Symbol '{0}' and its member '{1}' are both assigned in the same statement. You are at risk of assigning the member of an unintended object.</source>
<target state="new">Symbol '{0}' and its member '{1}' are both assigned in the same statement. You are at risk of assigning the member of an unintended object.</target>
<note />
</trans-unit>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementTitle">
<source>Assigning symbol and its member in the same statement.</source>
<target state="new">Assigning symbol and its member in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPropertySelfAssignmentMessage">
<source>The property {0} should not be assigned to itself.</source>
<target state="translated">La propriété {0} ne doit pas être assignée à elle-même.</target>
Expand Down
Expand Up @@ -2,6 +2,21 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="it" original="../MicrosoftQualityGuidelinesAnalyzersResources.resx">
<body>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementDescription">
<source>Assigning to a symbol and its member (field/property) in the same statement is not recommended. It is not clear if the member access was intended to use symbol's old value prior to the assignment or new value from the assignment in this statement. For clarity, consider splitting the assignments into separate statements.</source>
<target state="new">Assigning to a symbol and its member (field/property) in the same statement is not recommended. It is not clear if the member access was intended to use symbol's old value prior to the assignment or new value from the assignment in this statement. For clarity, consider splitting the assignments into separate statements.</target>
<note />
</trans-unit>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementMessage">
<source>Symbol '{0}' and its member '{1}' are both assigned in the same statement. You are at risk of assigning the member of an unintended object.</source>
<target state="new">Symbol '{0}' and its member '{1}' are both assigned in the same statement. You are at risk of assigning the member of an unintended object.</target>
<note />
</trans-unit>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementTitle">
<source>Assigning symbol and its member in the same statement.</source>
<target state="new">Assigning symbol and its member in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPropertySelfAssignmentMessage">
<source>The property {0} should not be assigned to itself.</source>
<target state="translated">La proprietà {0} non deve essere assegnata a se stessa.</target>
Expand Down
Expand Up @@ -2,6 +2,21 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="ja" original="../MicrosoftQualityGuidelinesAnalyzersResources.resx">
<body>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementDescription">
<source>Assigning to a symbol and its member (field/property) in the same statement is not recommended. It is not clear if the member access was intended to use symbol's old value prior to the assignment or new value from the assignment in this statement. For clarity, consider splitting the assignments into separate statements.</source>
<target state="new">Assigning to a symbol and its member (field/property) in the same statement is not recommended. It is not clear if the member access was intended to use symbol's old value prior to the assignment or new value from the assignment in this statement. For clarity, consider splitting the assignments into separate statements.</target>
<note />
</trans-unit>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementMessage">
<source>Symbol '{0}' and its member '{1}' are both assigned in the same statement. You are at risk of assigning the member of an unintended object.</source>
<target state="new">Symbol '{0}' and its member '{1}' are both assigned in the same statement. You are at risk of assigning the member of an unintended object.</target>
<note />
</trans-unit>
<trans-unit id="AssigningSymbolAndItsMemberInSameStatementTitle">
<source>Assigning symbol and its member in the same statement.</source>
<target state="new">Assigning symbol and its member in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPropertySelfAssignmentMessage">
<source>The property {0} should not be assigned to itself.</source>
<target state="translated">プロパティ {0} をそれ自体に割り当てることはできません。</target>
Expand Down