mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
- 将所有小写的命名空间导入更正为首字母大写格式 - 统一 GFramework 框架的命名空间引用规范 - 修复 core、ecs、godot 等模块的命名空间导入错误 - 标准化文档示例代码中的 using 语句格式 - 确保所有文档中的命名空间引用保持一致性 - 更新 global using 语句以匹配正确的命名空间格式
114 lines
3.8 KiB
C#
114 lines
3.8 KiB
C#
using System.Collections.Immutable;
|
|
using GFramework.SourceGenerators.Diagnostics;
|
|
using Microsoft.CodeAnalysis;
|
|
using Microsoft.CodeAnalysis.Diagnostics;
|
|
using Microsoft.CodeAnalysis.Operations;
|
|
|
|
namespace GFramework.SourceGenerators.Analyzers;
|
|
|
|
/// <summary>
|
|
/// 优先级使用分析器,检测应该使用 GetAllByPriority 而非 GetAll 的场景
|
|
/// </summary>
|
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
|
public sealed class PriorityUsageAnalyzer : DiagnosticAnalyzer
|
|
{
|
|
/// <summary>
|
|
/// 支持的诊断规则
|
|
/// </summary>
|
|
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
|
|
ImmutableArray.Create(PriorityDiagnostic.SuggestGetAllByPriority);
|
|
|
|
/// <summary>
|
|
/// 初始化分析器
|
|
/// </summary>
|
|
public override void Initialize(AnalysisContext context)
|
|
{
|
|
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
|
|
context.EnableConcurrentExecution();
|
|
|
|
context.RegisterCompilationStartAction(compilationContext =>
|
|
{
|
|
// 缓存符号查找
|
|
var iPrioritized = compilationContext.Compilation.GetTypeByMetadataName(
|
|
"GFramework.Core.Abstractions.Bases.IPrioritized");
|
|
|
|
if (iPrioritized == null)
|
|
return;
|
|
|
|
var iocContainer = compilationContext.Compilation.GetTypeByMetadataName(
|
|
"GFramework.Core.Abstractions.IoC.IIocContainer");
|
|
|
|
var architectureContext = compilationContext.Compilation.GetTypeByMetadataName(
|
|
"GFramework.Core.Abstractions.Architecture.IArchitectureContext");
|
|
|
|
compilationContext.RegisterOperationAction(
|
|
operationContext => AnalyzeInvocation(
|
|
operationContext,
|
|
iPrioritized,
|
|
iocContainer,
|
|
architectureContext),
|
|
OperationKind.Invocation);
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// 分析方法调用
|
|
/// </summary>
|
|
private static void AnalyzeInvocation(
|
|
OperationAnalysisContext context,
|
|
INamedTypeSymbol iPrioritized,
|
|
INamedTypeSymbol? iocContainer,
|
|
INamedTypeSymbol? architectureContext)
|
|
{
|
|
var invocation = (IInvocationOperation)context.Operation;
|
|
var method = invocation.TargetMethod;
|
|
|
|
// 检查方法名是否为 GetAll
|
|
if (method.Name != "GetAll")
|
|
return;
|
|
|
|
// 检查是否为泛型方法
|
|
if (!method.IsGenericMethod || method.TypeArguments.Length != 1)
|
|
return;
|
|
|
|
// 检查方法来源
|
|
var containingType = method.ContainingType;
|
|
if (iocContainer != null && SymbolEqualityComparer.Default.Equals(containingType, iocContainer))
|
|
{
|
|
// 来自 IIocContainer
|
|
}
|
|
else if (architectureContext != null &&
|
|
SymbolEqualityComparer.Default.Equals(containingType, architectureContext))
|
|
{
|
|
// 来自 IArchitectureContext
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 检查泛型参数是否实现了 IPrioritized
|
|
var typeArgument = method.TypeArguments[0];
|
|
if (typeArgument is not INamedTypeSymbol namedType)
|
|
return;
|
|
|
|
if (!ImplementsInterface(namedType, iPrioritized))
|
|
return;
|
|
|
|
// 报告诊断
|
|
var diagnostic = Diagnostic.Create(
|
|
PriorityDiagnostic.SuggestGetAllByPriority,
|
|
invocation.Syntax.GetLocation(),
|
|
typeArgument.ToDisplayString());
|
|
|
|
context.ReportDiagnostic(diagnostic);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查类型是否实现了指定接口
|
|
/// </summary>
|
|
private static bool ImplementsInterface(INamedTypeSymbol type, INamedTypeSymbol interfaceType)
|
|
{
|
|
return type.AllInterfaces.Any(i => SymbolEqualityComparer.Default.Equals(i, interfaceType));
|
|
}
|
|
} |