Skip to content

Commit 35bb41b

Browse files
authored
Merge pull request #6873 from Youssef1313/Ca1824-no-comp-end
Write CA1824 as non-compilation-end
2 parents 8b1675a + 2073e40 commit 35bb41b

File tree

6 files changed

+79
-32
lines changed

6 files changed

+79
-32
lines changed

src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Resources/CSharpMarkAssembliesWithNeutralResourcesLanguage.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,15 @@ namespace Microsoft.NetCore.CSharp.Analyzers.Resources
1515
[DiagnosticAnalyzer(LanguageNames.CSharp)]
1616
public sealed class CSharpMarkAssembliesWithNeutralResourcesLanguageAnalyzer : MarkAssembliesWithNeutralResourcesLanguageAnalyzer
1717
{
18-
protected override void RegisterAttributeAnalyzer(CompilationStartAnalysisContext context, Action onResourceFound, INamedTypeSymbol generatedCode)
18+
protected override void RegisterAttributeAnalyzer(CompilationStartAnalysisContext context, Func<bool> shouldAnalyze, Action<SyntaxNodeAnalysisContext> onResourceFound, INamedTypeSymbol generatedCode)
1919
{
2020
context.RegisterSyntaxNodeAction(context =>
2121
{
22+
if (!shouldAnalyze())
23+
{
24+
return;
25+
}
26+
2227
var attributeSyntax = (AttributeSyntax)context.Node;
2328
if (!CheckAttribute(attributeSyntax))
2429
{
@@ -30,7 +35,7 @@ protected override void RegisterAttributeAnalyzer(CompilationStartAnalysisContex
3035
return;
3136
}
3237

33-
onResourceFound();
38+
onResourceFound(context);
3439
}, SyntaxKind.Attribute);
3540
}
3641

src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Resources/MarkAssembliesWithNeutralResourcesLanguage.cs

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Collections.Generic;
55
using System.Collections.Immutable;
66
using System.Linq;
7+
using System.Runtime.CompilerServices;
78
using System.Threading;
89
using Analyzer.Utilities;
910
using Analyzer.Utilities.Extensions;
@@ -33,10 +34,9 @@ public abstract class MarkAssembliesWithNeutralResourcesLanguageAnalyzer : Diagn
3334
RuleLevel.IdeSuggestion,
3435
description: CreateLocalizableResourceString(nameof(MarkAssembliesWithNeutralResourcesLanguageDescription)),
3536
isPortedFxCopRule: true,
36-
isDataflowRule: false,
37-
isReportedAtCompilationEnd: true);
37+
isDataflowRule: false);
3838

39-
protected abstract void RegisterAttributeAnalyzer(CompilationStartAnalysisContext context, Action onResourceFound, INamedTypeSymbol generatedCode);
39+
protected abstract void RegisterAttributeAnalyzer(CompilationStartAnalysisContext context, Func<bool> shouldAnalyze, Action<SyntaxNodeAnalysisContext> onResourceFound, INamedTypeSymbol generatedCode);
4040

4141
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(Rule);
4242

@@ -68,28 +68,48 @@ public override void Initialize(AnalysisContext context)
6868
return;
6969
}
7070

71-
var hasResource = false;
72-
RegisterAttributeAnalyzer(context, () => hasResource = true, generatedCode);
71+
var alreadyReportedDiagnostic = new StrongBox<bool>(false);
72+
var @lock = new object();
7373

74-
context.RegisterCompilationEndAction(context =>
75-
{
76-
// there is nothing to do.
77-
if (!hasResource)
74+
RegisterAttributeAnalyzer(
75+
context,
76+
shouldAnalyze: () =>
7877
{
79-
return;
80-
}
81-
82-
if (data != null &&
83-
data.ApplicationSyntaxReference?.GetSyntax(context.CancellationToken) is { } attributeSyntax)
78+
// This value can only change from false to true. So no need to lock if it's already true here.
79+
if (alreadyReportedDiagnostic.Value)
80+
{
81+
return false;
82+
}
83+
84+
lock (@lock)
85+
{
86+
return !alreadyReportedDiagnostic.Value;
87+
}
88+
},
89+
onResourceFound: context =>
8490
{
85-
// we have the attribute but its doing it wrong.
86-
context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(Rule));
87-
return;
88-
}
89-
90-
// attribute just don't exist
91-
context.ReportNoLocationDiagnostic(Rule);
92-
});
91+
lock (@lock)
92+
{
93+
if (alreadyReportedDiagnostic.Value)
94+
{
95+
return;
96+
}
97+
98+
alreadyReportedDiagnostic.Value = true;
99+
100+
if (data != null &&
101+
data.ApplicationSyntaxReference?.GetSyntax(context.CancellationToken) is { } attributeSyntax)
102+
{
103+
// we have the attribute but its doing it wrong.
104+
context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(Rule));
105+
return;
106+
}
107+
108+
// attribute just don't exist
109+
context.ReportNoLocationDiagnostic(Rule);
110+
}
111+
},
112+
generatedCode);
93113
});
94114
}
95115

src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,7 @@
222222
"tags": [
223223
"PortedFromFxCop",
224224
"Telemetry",
225-
"EnabledRuleInAggressiveMode",
226-
"CompilationEnd"
225+
"EnabledRuleInAggressiveMode"
227226
]
228227
}
229228
},
@@ -6463,8 +6462,7 @@
64636462
"tags": [
64646463
"PortedFromFxCop",
64656464
"Telemetry",
6466-
"EnabledRuleInAggressiveMode",
6467-
"CompilationEnd"
6465+
"EnabledRuleInAggressiveMode"
64686466
]
64696467
}
64706468
},

src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Resources/MarkAssembliesWithNeutralResourcesLanguageTests.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
1+
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
22

33
using System.Threading.Tasks;
44
using Microsoft.CodeAnalysis.Testing;
@@ -18,13 +18,27 @@ public class MarkAssembliesWithNeutralResourcesLanguageTests
1818
namespace DesignerFile {
1919
[global::System.CodeDom.Compiler.GeneratedCodeAttribute(""System.Resources.Tools.StronglyTypedResourceBuilder"", ""4.0.0.0"")]
2020
internal class Resource1 { }
21+
22+
[global::System.CodeDom.Compiler.GeneratedCodeAttribute(""System.Resources.Tools.StronglyTypedResourceBuilder"", ""4.0.0.0"")]
23+
internal class Resource2 { }
24+
25+
[global::System.CodeDom.Compiler.GeneratedCodeAttribute(""System.Resources.Tools.StronglyTypedResourceBuilder"", ""4.0.0.0"")]
26+
internal class Resource3 { }
2127
}";
2228

2329
private const string BasicDesignerFile = @"
2430
Namespace My.Resources
2531
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute(""System.Resources.Tools.StronglyTypedResourceBuilder"", ""4.0.0.0"")> _
2632
Friend Class Resource1
2733
End Class
34+
35+
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute(""System.Resources.Tools.StronglyTypedResourceBuilder"", ""4.0.0.0"")> _
36+
Friend Class Resource2
37+
End Class
38+
39+
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute(""System.Resources.Tools.StronglyTypedResourceBuilder"", ""4.0.0.0"")> _
40+
Friend Class Resource3
41+
End Class
2842
End Namespace";
2943

3044
[Fact]

src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Resources/BasicMarkAssembliesWithNeutralResourcesLanguage.vb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
1+
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
22

33
Imports Microsoft.NetCore.Analyzers.Resources
44
Imports Microsoft.CodeAnalysis
@@ -13,9 +13,13 @@ Namespace Microsoft.NetCore.VisualBasic.Analyzers.Resources
1313
<DiagnosticAnalyzer(LanguageNames.VisualBasic)>
1414
Public NotInheritable Class BasicMarkAssembliesWithNeutralResourcesLanguageAnalyzer
1515
Inherits MarkAssembliesWithNeutralResourcesLanguageAnalyzer
16-
Protected Overrides Sub RegisterAttributeAnalyzer(context As CompilationStartAnalysisContext, onResourceFound As Action, generatedCode As INamedTypeSymbol)
16+
Protected Overrides Sub RegisterAttributeAnalyzer(context As CompilationStartAnalysisContext, shouldAnalyze As Func(Of Boolean), onResourceFound As Action(Of SyntaxNodeAnalysisContext), generatedCode As INamedTypeSymbol)
1717
context.RegisterSyntaxNodeAction(
1818
Sub(nc)
19+
If Not shouldAnalyze() Then
20+
Return
21+
End If
22+
1923
Dim attributeSyntax = DirectCast(nc.Node, AttributeSyntax)
2024
If Not CheckBasicAttribute(attributeSyntax) Then
2125
Return
@@ -25,7 +29,7 @@ Namespace Microsoft.NetCore.VisualBasic.Analyzers.Resources
2529
Return
2630
End If
2731

28-
onResourceFound()
32+
onResourceFound(nc)
2933
End Sub, SyntaxKind.Attribute)
3034
End Sub
3135

src/Utilities/Compiler/Extensions/DiagnosticExtensions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,12 @@ public static void ReportNoLocationDiagnostic(
169169
params object[] args)
170170
=> context.Compilation.ReportNoLocationDiagnostic(rule, context.ReportDiagnostic, properties: null, args);
171171

172+
public static void ReportNoLocationDiagnostic(
173+
this SyntaxNodeAnalysisContext context,
174+
DiagnosticDescriptor rule,
175+
params object[] args)
176+
=> context.Compilation.ReportNoLocationDiagnostic(rule, context.ReportDiagnostic, properties: null, args);
177+
172178
public static void ReportNoLocationDiagnostic(
173179
this Compilation compilation,
174180
DiagnosticDescriptor rule,

0 commit comments

Comments
 (0)