-
-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathStrongStaticReflectionCacheAnalyzer.cs
More file actions
73 lines (63 loc) · 2.93 KB
/
Copy pathStrongStaticReflectionCacheAnalyzer.cs
File metadata and controls
73 lines (63 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// <copyright file="StrongStaticReflectionCacheAnalyzer.cs" company="GSharp">
// Copyright (C) GSharp Authors. All rights reserved.
// </copyright>
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
namespace GSharp.InternalAnalyzers;
/// <summary>
/// Flags static dictionaries that strongly hold reflection identity keys.
/// </summary>
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class StrongStaticReflectionCacheAnalyzer : DiagnosticAnalyzer
{
/// <inheritdoc />
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; }
= ImmutableArray.Create(DiagnosticDescriptors.StrongStaticReflectionCache);
/// <inheritdoc />
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSymbolAction(AnalyzeField, SymbolKind.Field);
}
private static void AnalyzeField(SymbolAnalysisContext context)
{
var field = (IFieldSymbol)context.Symbol;
if (!field.IsStatic || !IsCompilerMetadataArea(field.ContainingNamespace))
{
return;
}
if (field.Type is not INamedTypeSymbol namedType || namedType.TypeArguments.Length != 2 || !IsStrongDictionary(namedType))
{
return;
}
var keyType = namedType.TypeArguments[0];
if (IsReflectionIdentityType(keyType))
{
context.ReportDiagnostic(Diagnostic.Create(
DiagnosticDescriptors.StrongStaticReflectionCache,
field.Locations.Length > 0 ? field.Locations[0] : null,
keyType.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat)));
}
}
private static bool IsCompilerMetadataArea(INamespaceSymbol namespaceSymbol)
{
var namespaceName = namespaceSymbol?.ToDisplayString();
return namespaceName == "GSharp.Core.CodeAnalysis.Emit"
|| namespaceName == "GSharp.Core.CodeAnalysis.Symbols"
|| namespaceName == "GSharp.Core.CodeAnalysis.Binding";
}
private static bool IsStrongDictionary(INamedTypeSymbol type)
{
var metadataName = type.ConstructedFrom.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
return metadataName == "global::System.Collections.Generic.Dictionary<TKey, TValue>"
|| metadataName == "global::System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>";
}
private static bool IsReflectionIdentityType(ITypeSymbol type)
{
return type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) == "global::System.Type"
|| type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) == "global::System.Reflection.Assembly"
|| type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) == "global::System.Reflection.Module";
}
}