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 3 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
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema

<!--
Microsoft ResX Schema
maxkoshevoi marked this conversation as resolved.
Show resolved Hide resolved
Version 2.0

The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.

Example:

... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
Expand All @@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>

There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.

Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.

The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:

Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.

mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
Expand Down Expand Up @@ -252,4 +252,10 @@
<data name="AvoidPropertySelfAssignmentMessage" xml:space="preserve">
<value>The property {0} should not be assigned to itself.</value>
</data>
<data name="ReferingToObjectAndReassigningItInTheSameStatementMessage" xml:space="preserve">
maxkoshevoi marked this conversation as resolved.
Show resolved Hide resolved
<value>Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</value>
maxkoshevoi marked this conversation as resolved.
Show resolved Hide resolved
maxkoshevoi marked this conversation as resolved.
Show resolved Hide resolved
</data>
<data name="ReferingToObjectAndReassigningItInTheSameStatementTitle" xml:space="preserve">
<value>Refering to object and reassigning it in the same statement.</value>
</data>
</root>
@@ -0,0 +1,96 @@
// 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>
/// ReferenceChanged: 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 ReferingToObjectAndReassigningItInTheSameStatement : DiagnosticAnalyzer
maxkoshevoi marked this conversation as resolved.
Show resolved Hide resolved
{
internal const string RuleId = "ReferenceChanged";
maxkoshevoi marked this conversation as resolved.
Show resolved Hide resolved

private static readonly LocalizableString s_localizableTitle = new LocalizableResourceString(nameof(MicrosoftQualityGuidelinesAnalyzersResources.ReferingToObjectAndReassigningItInTheSameStatementTitle), MicrosoftQualityGuidelinesAnalyzersResources.ResourceManager, typeof(MicrosoftQualityGuidelinesAnalyzersResources));
private static readonly LocalizableString s_localizableMessage = new LocalizableResourceString(nameof(MicrosoftQualityGuidelinesAnalyzersResources.ReferingToObjectAndReassigningItInTheSameStatementMessage), MicrosoftQualityGuidelinesAnalyzersResources.ResourceManager, typeof(MicrosoftQualityGuidelinesAnalyzersResources));

internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor(RuleId,
s_localizableTitle,
s_localizableMessage,
DiagnosticCategory.Usage,
DiagnosticHelpers.DefaultDiagnosticSeverity,
isEnabledByDefault: DiagnosticHelpers.EnabledByDefaultIfNotBuildingVSIX,
helpLinkUri: null);

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;
string violatingObjectName;
if (operationTarget.Instance is ILocalReferenceOperation localInstance)
maxkoshevoi marked this conversation as resolved.
Show resolved Hide resolved
{
violatingObjectName = localInstance.Local.Name;
isViolationFound = AnalyzeMemberAssignment(assignmentOperation, localInstance, (a, b) => a.Local == b.Local);
maxkoshevoi marked this conversation as resolved.
Show resolved Hide resolved
}
else if (operationTarget.Instance is IMemberReferenceOperation memberInstance)
{
violatingObjectName = memberInstance.Member.Name;
isViolationFound = AnalyzeMemberAssignment(assignmentOperation, memberInstance, (a, b) => a.Member == b.Member);
}
else
{
return;
}

if (isViolationFound)
{
var diagnostic = Diagnostic.Create(Rule, operationTarget.Syntax.GetLocation(), violatingObjectName);
context.ReportDiagnostic(diagnostic);
}
}

private static bool AnalyzeMemberAssignment<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 != null && assignmentOperation.Value.Kind == OperationKind.SimpleAssignment)
maxkoshevoi marked this conversation as resolved.
Show resolved Hide resolved
{
assignmentOperation = (ISimpleAssignmentOperation)assignmentOperation.Value;

var operationValue = assignmentOperation.Target as T;
if (equalityComparer(instance, operationValue))
{
return true;
}
}
return false;
}
}
}
Expand Up @@ -22,6 +22,16 @@
<target state="translated">Některé odkazy na {0} nešlo opravit. Měly by se opravit ručně.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementMessage">
<source>Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</source>
<target state="new">Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementTitle">
<source>Refering to object and reassigning it in the same statement.</source>
<target state="new">Refering to object and reassigning it in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="UseLiteralsWhereAppropriateTitle">
<source>Use literals where appropriate</source>
<target state="translated">Tam, kde je to vhodné, použijte literály</target>
Expand Down
Expand Up @@ -22,6 +22,16 @@
<target state="translated">Einige Verweise auf "{0}" konnten nicht korrigiert werden. Korrigieren Sie sie manuell.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementMessage">
<source>Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</source>
<target state="new">Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementTitle">
<source>Refering to object and reassigning it in the same statement.</source>
<target state="new">Refering to object and reassigning it in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="UseLiteralsWhereAppropriateTitle">
<source>Use literals where appropriate</source>
<target state="translated">Nach Möglichkeit Literale verwenden</target>
Expand Down
Expand Up @@ -22,6 +22,16 @@
<target state="translated">Algunas referencias a "{0}" podrían no corregirse, así que tendría que hacerlo manualmente.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementMessage">
<source>Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</source>
<target state="new">Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementTitle">
<source>Refering to object and reassigning it in the same statement.</source>
<target state="new">Refering to object and reassigning it in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="UseLiteralsWhereAppropriateTitle">
<source>Use literals where appropriate</source>
<target state="translated">Usar literales cuando resulte apropiado</target>
Expand Down
Expand Up @@ -22,6 +22,16 @@
<target state="translated">Des références à '{0}' n'ont pas pu être corrigées, elles doivent être corrigées manuellement.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementMessage">
<source>Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</source>
<target state="new">Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementTitle">
<source>Refering to object and reassigning it in the same statement.</source>
<target state="new">Refering to object and reassigning it in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="UseLiteralsWhereAppropriateTitle">
<source>Use literals where appropriate</source>
<target state="translated">Utiliser des littéraux quand cela est approprié</target>
Expand Down
Expand Up @@ -22,6 +22,16 @@
<target state="translated">Non è stato possibile correggere alcuni riferimenti a '{0}'. Correggerli manualmente.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementMessage">
<source>Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</source>
<target state="new">Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementTitle">
<source>Refering to object and reassigning it in the same statement.</source>
<target state="new">Refering to object and reassigning it in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="UseLiteralsWhereAppropriateTitle">
<source>Use literals where appropriate</source>
<target state="translated">Usa valori letterali dove appropriato</target>
Expand Down
Expand Up @@ -22,6 +22,16 @@
<target state="translated">'{0}' への参照を修正できませんでした。手動で修正する必要があります。</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementMessage">
<source>Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</source>
<target state="new">Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementTitle">
<source>Refering to object and reassigning it in the same statement.</source>
<target state="new">Refering to object and reassigning it in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="UseLiteralsWhereAppropriateTitle">
<source>Use literals where appropriate</source>
<target state="translated">適切な場所にリテラルを使用します</target>
Expand Down
Expand Up @@ -22,6 +22,16 @@
<target state="translated">'{0}'에 대한 일부 참조를 수정할 수 없습니다. 수동으로 수정해야 합니다.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementMessage">
<source>Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</source>
<target state="new">Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementTitle">
<source>Refering to object and reassigning it in the same statement.</source>
<target state="new">Refering to object and reassigning it in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="UseLiteralsWhereAppropriateTitle">
<source>Use literals where appropriate</source>
<target state="translated">적합한 리터럴을 사용하세요.</target>
Expand Down
Expand Up @@ -22,6 +22,16 @@
<target state="translated">Nie można naprawić niektórych odwołań do „{0}”. Należy je naprawić ręcznie.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementMessage">
<source>Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</source>
<target state="new">Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementTitle">
<source>Refering to object and reassigning it in the same statement.</source>
<target state="new">Refering to object and reassigning it in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="UseLiteralsWhereAppropriateTitle">
<source>Use literals where appropriate</source>
<target state="translated">Używaj literałów w odpowiednich miejscach</target>
Expand Down
Expand Up @@ -22,6 +22,16 @@
<target state="translated">Algumas referências a '{0}' não puderam ser corrigidas, elas devem ser corrigidas manualmente.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementMessage">
<source>Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</source>
<target state="new">Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementTitle">
<source>Refering to object and reassigning it in the same statement.</source>
<target state="new">Refering to object and reassigning it in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="UseLiteralsWhereAppropriateTitle">
<source>Use literals where appropriate</source>
<target state="translated">Usar literais sempre que apropriado</target>
Expand Down
Expand Up @@ -22,6 +22,16 @@
<target state="translated">Не удалось исправить некоторые ссылки на "{0}". Их следует исправить вручную.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementMessage">
<source>Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</source>
<target state="new">Object '{0}' is being referred to and reassigned in the same statement. You are at risk of referring to unintended object.</target>
<note />
</trans-unit>
<trans-unit id="ReferingToObjectAndReassigningItInTheSameStatementTitle">
<source>Refering to object and reassigning it in the same statement.</source>
<target state="new">Refering to object and reassigning it in the same statement.</target>
<note />
</trans-unit>
<trans-unit id="UseLiteralsWhereAppropriateTitle">
<source>Use literals where appropriate</source>
<target state="translated">Используйте литералы, когда это уместно</target>
Expand Down