diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/MicrosoftCodeQualityAnalyzersResources.resx b/src/Microsoft.CodeQuality.Analyzers/Core/MicrosoftCodeQualityAnalyzersResources.resx index 5fc9391b6a..302c58cfc6 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/MicrosoftCodeQualityAnalyzersResources.resx +++ b/src/Microsoft.CodeQuality.Analyzers/Core/MicrosoftCodeQualityAnalyzersResources.resx @@ -1334,4 +1334,13 @@ The property {0} should not be assigned to itself. + + 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. + + + 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. + + + Assigning symbol and its member in the same statement. + \ No newline at end of file diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/AssigningSymbolAndItsMemberInSameStatement.cs b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/AssigningSymbolAndItsMemberInSameStatement.cs new file mode 100644 index 0000000000..aa73798712 --- /dev/null +++ b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/AssigningSymbolAndItsMemberInSameStatement.cs @@ -0,0 +1,100 @@ +// 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 +{ + /// + /// CA2246: Prevent objects from being referenced in statements where they are reassigned + /// + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public sealed class AssigningSymbolAndItsMemberInSameStatement : DiagnosticAnalyzer + { + internal const string RuleId = "CA2246"; + + private static readonly LocalizableString s_localizableTitle = new LocalizableResourceString(nameof(MicrosoftCodeQualityAnalyzersResources.AssigningSymbolAndItsMemberInSameStatementTitle), MicrosoftCodeQualityAnalyzersResources.ResourceManager, typeof(MicrosoftCodeQualityAnalyzersResources)); + private static readonly LocalizableString s_localizableMessage = new LocalizableResourceString(nameof(MicrosoftCodeQualityAnalyzersResources.AssigningSymbolAndItsMemberInSameStatementMessage), MicrosoftCodeQualityAnalyzersResources.ResourceManager, typeof(MicrosoftCodeQualityAnalyzersResources)); + private static readonly LocalizableString s_localizableDescription = new LocalizableResourceString(nameof(MicrosoftCodeQualityAnalyzersResources.AssigningSymbolAndItsMemberInSameStatementDescription), MicrosoftCodeQualityAnalyzersResources.ResourceManager, typeof(MicrosoftCodeQualityAnalyzersResources)); + + internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor(RuleId, + s_localizableTitle, + s_localizableMessage, + DiagnosticCategory.Usage, + DiagnosticHelpers.DefaultDiagnosticSeverity, + DiagnosticHelpers.EnabledByDefaultIfNotBuildingVSIX, + s_localizableDescription); + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); + + public override void Initialize(AnalysisContext context) + { + context.EnableConcurrentExecution(); + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + + 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.Equals(b.Local)); + } + else if (operationTarget.Instance is IMemberReferenceOperation memberInstance) + { + isViolationFound = AnalyzeAssignmentToMember(assignmentOperation, memberInstance, (a, b) => a.Member.Equals(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.Equals(b.Parameter)); + } + else + { + return; + } + + if (isViolationFound) + { + var diagnostic = Diagnostic.Create(Rule, operationTarget.Syntax.GetLocation(), operationTarget.Instance.Syntax, operationTarget.Member.Name); + context.ReportDiagnostic(diagnostic); + } + } + + private static bool AnalyzeAssignmentToMember(ISimpleAssignmentOperation assignmentOperation, T instance, Func 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; + } + } +} diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf index 429a2e0ffc..04e41a7c3e 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf +++ b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf @@ -7,6 +7,21 @@ Připojit .ConfigureAwait(true) + + 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. + 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. + + + + 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. + 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. + + + + Assigning symbol and its member in the same statement. + Assigning symbol and its member in the same statement. + + Avoid Async Void Vyhněte se Async Void. diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf index eee1e1abab..b57851f6b0 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf +++ b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf @@ -7,6 +7,21 @@ "ConfigureAwait(true)" anfügen + + 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. + 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. + + + + 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. + 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. + + + + Assigning symbol and its member in the same statement. + Assigning symbol and its member in the same statement. + + Avoid Async Void Async Void vermeiden diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf index 166e4cb384..a0aef542d9 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf +++ b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf @@ -7,6 +7,21 @@ Anexar .ConfigureAwait(true) + + 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. + 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. + + + + 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. + 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. + + + + Assigning symbol and its member in the same statement. + Assigning symbol and its member in the same statement. + + Avoid Async Void Evitar async void diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf index dbf3088ede..34d10025a9 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf +++ b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf @@ -7,6 +7,21 @@ Ajouter .ConfigureAwait(true) + + 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. + 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. + + + + 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. + 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. + + + + Assigning symbol and its member in the same statement. + Assigning symbol and its member in the same statement. + + Avoid Async Void Éviter Async Void diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf index baf56acf31..91fc429240 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf +++ b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf @@ -7,6 +7,21 @@ Accoda .ConfigureAwait(true) + + 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. + 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. + + + + 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. + 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. + + + + Assigning symbol and its member in the same statement. + Assigning symbol and its member in the same statement. + + Avoid Async Void Evitare metodi asincroni void diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf index 6d732b023c..2c24cd26e1 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf +++ b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf @@ -7,6 +7,21 @@ .ConfigureAwait(true) を追加します + + 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. + 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. + + + + 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. + 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. + + + + Assigning symbol and its member in the same statement. + Assigning symbol and its member in the same statement. + + Avoid Async Void Async Void を使用しないでください diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf index 6479de034d..1419222343 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf +++ b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf @@ -7,6 +7,21 @@ .ConfigureAwait(true) 추가 + + 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. + 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. + + + + 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. + 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. + + + + Assigning symbol and its member in the same statement. + Assigning symbol and its member in the same statement. + + Avoid Async Void Async Void를 사용하지 마세요. diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf index aef0bba149..e7fed8d697 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf +++ b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf @@ -7,6 +7,21 @@ Dołącz element .ConfigureAwait(true) + + 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. + 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. + + + + 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. + 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. + + + + Assigning symbol and its member in the same statement. + Assigning symbol and its member in the same statement. + + Avoid Async Void Unikaj metod async void diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf index ea6ab6a1ce..dc5bf3b9dd 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf +++ b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf @@ -7,6 +7,21 @@ Acrescentar .ConfigureAwait(true) + + 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. + 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. + + + + 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. + 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. + + + + Assigning symbol and its member in the same statement. + Assigning symbol and its member in the same statement. + + Avoid Async Void Evitar async void diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf index 7a18bac8fb..4c8e6ae113 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf +++ b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf @@ -7,6 +7,21 @@ Добавить .ConfigureAwait(true) + + 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. + 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. + + + + 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. + 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. + + + + Assigning symbol and its member in the same statement. + Assigning symbol and its member in the same statement. + + Avoid Async Void Избегание Async Void diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf index 7b0d6f4647..49d772185a 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf +++ b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf @@ -7,6 +7,21 @@ Ekle .ConfigureAwait(true) + + 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. + 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. + + + + 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. + 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. + + + + Assigning symbol and its member in the same statement. + Assigning symbol and its member in the same statement. + + Avoid Async Void Async Void Kullanmayın diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf index bedc87ede3..6ad957d082 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf +++ b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf @@ -7,6 +7,21 @@ 附加 .ConfigureAwait(true) + + 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. + 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. + + + + 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. + 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. + + + + Assigning symbol and its member in the same statement. + Assigning symbol and its member in the same statement. + + Avoid Async Void 避免使用 Async Void diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf index e4f37856e6..d535b6895d 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf +++ b/src/Microsoft.CodeQuality.Analyzers/Core/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf @@ -7,6 +7,21 @@ 附加 .ConfigureAwait(true) + + 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. + 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. + + + + 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. + 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. + + + + Assigning symbol and its member in the same statement. + Assigning symbol and its member in the same statement. + + Avoid Async Void 避免 Async Void diff --git a/src/Microsoft.CodeQuality.Analyzers/UnitTests/QualityGuidelines/AssigningSymbolAndItsMemberInSameStatementTests.cs b/src/Microsoft.CodeQuality.Analyzers/UnitTests/QualityGuidelines/AssigningSymbolAndItsMemberInSameStatementTests.cs new file mode 100644 index 0000000000..e9dfdf21a1 --- /dev/null +++ b/src/Microsoft.CodeQuality.Analyzers/UnitTests/QualityGuidelines/AssigningSymbolAndItsMemberInSameStatementTests.cs @@ -0,0 +1,320 @@ +// 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 Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeQuality.Analyzers.QualityGuidelines; +using Test.Utilities; +using Xunit; + +namespace Microsoft.CodeQuality.Analyzers.UnitTests.QualityGuidelines +{ + public partial class AssigningSymbolAndItsMemberInSameStatementTests : DiagnosticAnalyzerTestBase + { + protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer() + { + return new AssigningSymbolAndItsMemberInSameStatement(); + } + + protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() + { + return new AssigningSymbolAndItsMemberInSameStatement(); + } + + [Fact] + public void CSharpReassignLocalVariableAndReferToItsField() + { + VerifyCSharp(@" +public class C +{ + public C Field; +} + +public class Test +{ + public void Method() + { + C a = new C(), b = new C(); + a.Field = a = b; + } +} +", + GetCSharpResultAt(12, 9, AssigningSymbolAndItsMemberInSameStatement.Rule, "a", "Field")); + } + + [Fact] + public void CSharpReassignLocalVariableAndReferToItsProperty() + { + VerifyCSharp(@" +public class C +{ + public C Property { get; set; } +} + +public class Test +{ + public void Method() + { + C a = new C(), b = new C(), c; + a.Property = c = a = b; + } +} +", + GetCSharpResultAt(12, 9, AssigningSymbolAndItsMemberInSameStatement.Rule, "a", "Property")); + } + + [Fact] + public void CSharpReassignLocalVariablesPropertyAndReferToItsProperty() + { + VerifyCSharp(@" +public class C +{ + public C Property { get; set; } +} + +public class Test +{ + public void Method() + { + C a = new C(), b = new C(); + a.Property.Property = a.Property = b; + } +} +", + GetCSharpResultAt(12, 9, AssigningSymbolAndItsMemberInSameStatement.Rule, "a.Property", "Property")); + } + + [Fact] + public void CSharpReassignLocalVariableAndItsPropertyAndReferToItsProperty() + { + VerifyCSharp(@" +public class C +{ + public C Property { get; set; } +} + +public class Test +{ + public void Method() + { + C a = new C(), b = new C(); + a.Property.Property = a.Property = a = b; + } +} +", + GetCSharpResultAt(12, 9, AssigningSymbolAndItsMemberInSameStatement.Rule, "a.Property", "Property"), + GetCSharpResultAt(12, 31, AssigningSymbolAndItsMemberInSameStatement.Rule, "a", "Property")); + } + + [Fact] + public void CSharpReferToFieldOfReferenceTypeLocalVariableAfterItsReassignment() + { + VerifyCSharp(@" +public class C +{ + public C Field; +} + +public class Test +{ + static C x, y; + + public void Method() + { + x.Field = x = y; + } +} +", + GetCSharpResultAt(13, 9, AssigningSymbolAndItsMemberInSameStatement.Rule, "x", "Field")); + } + + [Fact] + public void CSharpReassignGlobalVariableAndReferToItsField() + { + VerifyCSharp(@" +public class C +{ + public C Property { get; set; } +} + +public class Test +{ + static C x, y; + + public void Method() + { + x.Property.Property = x.Property = y; + } +} +", + GetCSharpResultAt(13, 9, AssigningSymbolAndItsMemberInSameStatement.Rule, "x.Property", "Property")); + } + + [Fact] + public void CSharpReassignGlobalVariableAndItsPropertyAndReferToItsProperty() + { + VerifyCSharp(@" +public class C +{ + public C Property { get; set; } +} + +public class Test +{ + static C x, y; + + public void Method() + { + x.Property.Property = x.Property = x = y; + } +} +", + GetCSharpResultAt(13, 9, AssigningSymbolAndItsMemberInSameStatement.Rule, "x.Property", "Property"), + GetCSharpResultAt(13, 31, AssigningSymbolAndItsMemberInSameStatement.Rule, "x", "Property")); + } + + + [Fact] + public void CSharpReassignGlobalPropertyAndItsPropertyAndReferToItsProperty() + { + VerifyCSharp(@" +public class C +{ + public C Property { get; set; } +} + +public class Test +{ + static C x { get; set; } + static C y { get; set; } + + public void Method() + { + x.Property.Property = x.Property = x = y; + } +} +", + GetCSharpResultAt(14, 9, AssigningSymbolAndItsMemberInSameStatement.Rule, "x.Property", "Property"), + GetCSharpResultAt(14, 31, AssigningSymbolAndItsMemberInSameStatement.Rule, "x", "Property")); + } + + [Fact] + public void CSharpReassignSecondLocalVariableAndReferToItsPropertyOfFirstVariable() + { + VerifyCSharp(@" +public class C +{ + public C Property { get; set; } +} + +public class Test +{ + public void Method() + { + C a = new C(), b; + a.Property = b = a; + } +} +"); + } + + [Fact] + public void CSharpReassignPropertyOfFirstLocalVariableWithSecondAndReferToPropertyOfSecondVariable() + { + VerifyCSharp(@" +public class C +{ + public C Property { get; set; } +} + +public class Test +{ + public void Method() + { + C a = new C(), b = new C(), c; + b.Property.Property = a.Property = b; + } +} +"); + } + + [Fact] + public void CSharpReassignPropertyOfFirstLocalVariableWithThirdAndReferToPropertyOfSecondVariable() + { + VerifyCSharp(@" +public class C +{ + public C Property { get; set; } +} + +public class Test +{ + public void Method() + { + C a = new C(), b = new C(), c = new C(); + b.Property.Property = a.Property = c; + } +} +"); + } + + [Fact] + public void CSharpReassignMethodParameterAndReferToItsProperty() + { + VerifyCSharp(@" +public class C +{ + public C Property { get; set; } +} + +public class Test +{ + public void Method(C b) + { + C a = new C(); + b.Property = b = a; + } +} +", + GetCSharpResultAt(12, 9, AssigningSymbolAndItsMemberInSameStatement.Rule, "b", "Property")); + } + + [Fact] + public void CSharpReassignLocalValueTypeVariableAndReferToItsField() + { + VerifyCSharp(@" +public struct S +{ + public S Field; +} + +public class Test +{ + public void Method() + { + S a, b; + a.Field = a = b; + } +} +", TestValidationMode.AllowCompileErrors); + } + + [Fact] + public void CSharpReassignLocalValueTypeVariableAndReferToItsProperty() + { + VerifyCSharp(@" +public struct S +{ + public S Property { get; set; } +} + +public class Test +{ + public void Method() + { + S a, b; + a.Property = c = a = b; + } +} +", TestValidationMode.AllowCompileErrors); + } + } +}