| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- using System;
- using System.Collections.Immutable;
- using System.Linq;
- using System.Text;
- using Microsoft.CodeAnalysis;
- using Microsoft.CodeAnalysis.CSharp.Syntax;
- using Microsoft.CodeAnalysis.Diagnostics;
- namespace ET.Analyzer;
- [DiagnosticAnalyzer(LanguageNames.CSharp)]
- public class EntitySystemAnalyzer: DiagnosticAnalyzer
- {
- public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(EntitySystemAnalyzerRule.Rule,EntitySystemMethodNeedSystemOfAttrAnalyzerRule.Rule);
- public override void Initialize(AnalysisContext context)
- {
- if (!AnalyzerGlobalSetting.EnableAnalyzer)
- {
- return;
- }
- context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
- context.EnableConcurrentExecution();
- context.RegisterSymbolAction(this.Analyzer, SymbolKind.NamedType);
- context.RegisterSymbolAction(this.AnalyzeIsSystemMethodValid,SymbolKind.NamedType);
- }
- private static ImmutableArray<ETSystemData> SupportedETSystemDatas => ImmutableArray.Create(
- new ETSystemData(Definition.EntitySystemOfAttribute, Definition.EntitySystemAttribute, Definition.EntityType,Definition.EntitySystemAttributeMetaName,
- new SystemMethodData(Definition.IAwakeInterface, Definition.AwakeMethod),
- new SystemMethodData(Definition.IUpdateInterface, Definition.UpdateMethod),
- new SystemMethodData(Definition.IDestroyInterface, Definition.DestroyMethod),
- new SystemMethodData(Definition.IAddComponentInterface, Definition.AddComponentMethod),
- new SystemMethodData(Definition.IDeserializeInterface, Definition.DeserializeMethod),
- new SystemMethodData(Definition.IGetComponentInterface, Definition.GetComponentMethod),
- new SystemMethodData(Definition.ILoadInterface, Definition.LoadMethod),
- new SystemMethodData(Definition.ILateUpdateInterface, Definition.LateUpdateMethod),
- new SystemMethodData(Definition.ISerializeInterface, Definition.SerializeMethod),
- new SystemMethodData(Definition.ILSRollbackInterface,Definition.LSRollbackMethod)),
- new ETSystemData(Definition.LSEntitySystemOfAttribute,Definition.LSEntitySystemAttribute,Definition.LSEntityType,Definition.LSEntitySystemAttributeMetaName,
- new SystemMethodData(Definition.IAwakeInterface, Definition.AwakeMethod),
- new SystemMethodData(Definition.ILSUpdateInterface, Definition.LSUpdateMethod),
- new SystemMethodData(Definition.IDestroyInterface, Definition.DestroyMethod),
- new SystemMethodData(Definition.IAddComponentInterface, Definition.AddComponentMethod),
- new SystemMethodData(Definition.IDeserializeInterface, Definition.DeserializeMethod),
- new SystemMethodData(Definition.IGetComponentInterface, Definition.GetComponentMethod),
- new SystemMethodData(Definition.ILoadInterface, Definition.LoadMethod),
- new SystemMethodData(Definition.ISerializeInterface, Definition.SerializeMethod),
- new SystemMethodData(Definition.ILSRollbackInterface,Definition.LSRollbackMethod)
- )
- );
- public class ETSystemData
- {
- public string EntityTypeName;
- public string SystemOfAttribute;
- public string SystemAttributeShowName;
- public string SystemAttributeMetaName;
- public SystemMethodData[] SystemMethods;
- public ETSystemData(string systemOfAttribute, string systemAttributeShowName, string entityTypeName, string systemAttributeMetaName, params SystemMethodData[] systemMethods)
- {
- this.SystemOfAttribute = systemOfAttribute;
- this.SystemAttributeShowName = systemAttributeShowName;
- this.EntityTypeName = entityTypeName;
- this.SystemAttributeMetaName = systemAttributeMetaName;
- this.SystemMethods = systemMethods;
- }
- }
- public struct SystemMethodData
- {
- public string InterfaceName;
- public string MethodName;
- public SystemMethodData(string interfaceName, string methodName)
- {
- this.InterfaceName = interfaceName;
- this.MethodName = methodName;
- }
- }
- private void Analyzer(SymbolAnalysisContext context)
- {
- if (!(context.Symbol is INamedTypeSymbol namedTypeSymbol))
- {
- return;
- }
- ImmutableDictionary<string, string?>.Builder? builder = null;
- foreach (ETSystemData? supportedEtSystemData in SupportedETSystemDatas)
- {
- if (supportedEtSystemData != null)
- {
- this.AnalyzeETSystem(context, supportedEtSystemData, ref builder);
- }
- }
- this.ReportNeedGenerateSystem(context, namedTypeSymbol, ref builder);
- }
- private void AnalyzeETSystem(SymbolAnalysisContext context, ETSystemData etSystemData, ref ImmutableDictionary<string, string?>.Builder? builder)
- {
- if (!(context.Symbol is INamedTypeSymbol namedTypeSymbol))
- {
- return;
- }
- // 筛选出含有SystemOf标签的类
- AttributeData? attr = namedTypeSymbol.GetFirstAttribute(etSystemData.SystemOfAttribute);
- if (attr == null)
- {
- return;
- }
-
- // 获取所属的实体类symbol
- if (attr.ConstructorArguments[0].Value is not INamedTypeSymbol entityTypeSymbol)
- {
- return;
- }
- bool ignoreAwake = false;
- if (attr.ConstructorArguments.Length>=2 && attr.ConstructorArguments[1].Value is bool ignore)
- {
- ignoreAwake = ignore;
- }
-
- // 排除非Entity子类
- if (entityTypeSymbol.BaseType?.ToString() != etSystemData.EntityTypeName)
- {
- return;
- }
- foreach (INamedTypeSymbol? interfacetypeSymbol in entityTypeSymbol.AllInterfaces)
- {
- if (ignoreAwake && interfacetypeSymbol.IsInterface(Definition.IAwakeInterface))
- {
- continue;
- }
- foreach (SystemMethodData systemMethodData in etSystemData.SystemMethods)
- {
- if (interfacetypeSymbol.IsInterface(systemMethodData.InterfaceName))
- {
- if (interfacetypeSymbol.IsGenericType)
- {
- var typeArgs = ImmutableArray.Create<ITypeSymbol>(entityTypeSymbol).AddRange(interfacetypeSymbol.TypeArguments);
- if (!namedTypeSymbol.HasMethodWithParams(systemMethodData.MethodName, typeArgs.ToArray()))
- {
- StringBuilder str = new();
- str.Append(entityTypeSymbol);
- str.Append("/");
- str.Append(etSystemData.SystemAttributeShowName);
- foreach (ITypeSymbol? typeArgument in interfacetypeSymbol.TypeArguments)
- {
- str.Append("/");
- str.Append(typeArgument);
- }
- AddProperty(ref builder, $"{systemMethodData.MethodName}`{interfacetypeSymbol.TypeArguments.Length}", str.ToString());
- }
- }
- else
- {
- if (!namedTypeSymbol.HasMethodWithParams(systemMethodData.MethodName, entityTypeSymbol))
- {
- AddProperty(ref builder, systemMethodData.MethodName, $"{entityTypeSymbol}/{etSystemData.SystemAttributeShowName}");
- }
- }
- break;
- }
- }
- }
- }
-
- private void AddProperty(ref ImmutableDictionary<string, string?>.Builder? builder, string methodMetaName, string methodArgs)
- {
- if (builder == null)
- {
- builder = ImmutableDictionary.CreateBuilder<string, string?>();
- }
- if (builder.TryGetValue(Definition.EntitySystemInterfaceSequence, out string? seqValue))
- {
- builder[Definition.EntitySystemInterfaceSequence] = $"{seqValue}/{methodMetaName}";
- }
- else
- {
- builder.Add(Definition.EntitySystemInterfaceSequence, methodMetaName);
- }
- builder.Add(methodMetaName, methodArgs);
- }
- private void ReportNeedGenerateSystem(SymbolAnalysisContext context, INamedTypeSymbol namedTypeSymbol, ref ImmutableDictionary<string, string?>.Builder? builder)
- {
- if (builder == null)
- {
- return;
- }
- foreach (SyntaxReference? reference in namedTypeSymbol.DeclaringSyntaxReferences)
- {
- if (reference.GetSyntax() is ClassDeclarationSyntax classDeclarationSyntax)
- {
- Diagnostic diagnostic = Diagnostic.Create(EntitySystemAnalyzerRule.Rule, classDeclarationSyntax.Identifier.GetLocation(),
- builder.ToImmutable(), namedTypeSymbol.Name);
- context.ReportDiagnostic(diagnostic);
- }
- }
- }
-
- private void AnalyzeIsSystemMethodValid(SymbolAnalysisContext context)
- {
- if (!(context.Symbol is INamedTypeSymbol namedTypeSymbol))
- {
- return;
- }
-
- foreach (ISymbol? symbol in namedTypeSymbol.GetMembers())
- {
- if (symbol is not IMethodSymbol methodSymbol)
- {
- continue;
- }
- foreach (var etSystemData in SupportedETSystemDatas)
- {
- if (!methodSymbol.HasAttribute(etSystemData.SystemAttributeMetaName))
- {
- continue;
- }
- if (methodSymbol.Parameters.Length==0)
- {
- continue;
- }
-
- AttributeData? attr = namedTypeSymbol.GetFirstAttribute(etSystemData.SystemOfAttribute);
- if (attr == null || attr.ConstructorArguments[0].Value is not INamedTypeSymbol entityTypeSymbol
- || entityTypeSymbol.ToString()!=methodSymbol.Parameters[0].Type.ToString())
- {
- ReportNeedSystemOfAttr(context,methodSymbol,etSystemData);
- }
- }
- }
- }
-
- private void ReportNeedSystemOfAttr(SymbolAnalysisContext context, IMethodSymbol methodSymbol,ETSystemData etSystemData)
- {
-
- foreach (SyntaxReference? reference in methodSymbol.DeclaringSyntaxReferences)
- {
- if (reference.GetSyntax() is MethodDeclarationSyntax methodDeclarationSyntax)
- {
- Diagnostic diagnostic = Diagnostic.Create(EntitySystemMethodNeedSystemOfAttrAnalyzerRule.Rule, methodDeclarationSyntax.Identifier.GetLocation()
- ,methodSymbol.Name, etSystemData.SystemAttributeShowName,etSystemData.SystemOfAttribute);
- context.ReportDiagnostic(diagnostic);
- }
- }
- }
- }
|