Просмотр исходного кода

更新分析器 (#486)

* 更新IGetComponentSys分析器支持

* 新增FiberLog分析器 实体类内部或含有实体类参数的函数内部必须使用Fiber输出日志
susices 2 лет назад
Родитель
Сommit
6d4da2ecd9

+ 11 - 3
Share/Analyzer/Analyzer/EntitySystemAnalyzer.cs

@@ -1,4 +1,3 @@
-using System;
 using System.Collections.Immutable;
 using System.Linq;
 using System.Text;
@@ -51,7 +50,7 @@ public class EntitySystemAnalyzer: DiagnosticAnalyzer
         )
     );
 
-    public class ETSystemData
+    private class ETSystemData
     {
         public string EntityTypeName;
         public string SystemOfAttribute;
@@ -141,6 +140,8 @@ public class EntitySystemAnalyzer: DiagnosticAnalyzer
             {
                 continue;
             }
+
+            
             foreach (SystemMethodData systemMethodData in etSystemData.SystemMethods)
             {
                 if (interfacetypeSymbol.IsInterface(systemMethodData.InterfaceName))
@@ -165,7 +166,14 @@ public class EntitySystemAnalyzer: DiagnosticAnalyzer
                     }
                     else
                     {
-                        if (!namedTypeSymbol.HasMethodWithParams(systemMethodData.MethodName, entityTypeSymbol))
+                        if (interfacetypeSymbol.IsInterface(Definition.IGetComponentInterface))
+                        {
+                            if (!namedTypeSymbol.HasMethodWithParams(systemMethodData.MethodName, entityTypeSymbol.ToString(),"System.Type"))
+                            {
+                                AddProperty(ref builder, systemMethodData.MethodName, $"{entityTypeSymbol}/{etSystemData.SystemAttributeShowName}/System.Type");
+                            }
+                        }
+                        else if (!namedTypeSymbol.HasMethodWithParams(systemMethodData.MethodName, entityTypeSymbol))
                         {
                             AddProperty(ref builder, systemMethodData.MethodName, $"{entityTypeSymbol}/{etSystemData.SystemAttributeShowName}");
                         }

+ 91 - 0
Share/Analyzer/Analyzer/FiberLogAnalyzer.cs

@@ -0,0 +1,91 @@
+using System.Collections.Immutable;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Diagnostics;
+
+namespace ET.Analyzer;
+[DiagnosticAnalyzer(LanguageNames.CSharp)]
+public class FiberLogAnalyzer:DiagnosticAnalyzer
+{
+    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(FiberLogAnalyzerRule.Rule);
+    
+    public override void Initialize(AnalysisContext context)
+    {
+        if (!AnalyzerGlobalSetting.EnableAnalyzer)
+        {
+            return;
+        }
+        context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+        context.EnableConcurrentExecution();
+        context.RegisterCompilationStartAction((analysisContext =>
+        {
+            if (AnalyzerHelper.IsAssemblyNeedAnalyze(analysisContext.Compilation.AssemblyName, AnalyzeAssembly.AllModelHotfix))
+            {
+                analysisContext.RegisterSyntaxNodeAction(AnalyzeMemberAccessExpression,SyntaxKind.InvocationExpression);
+            }
+        } ));
+    }
+
+    private void AnalyzeMemberAccessExpression(SyntaxNodeAnalysisContext context)
+    {
+        if (!(context.Node is InvocationExpressionSyntax invocationExpressionSyntax))
+        {
+            return;
+        }
+
+        var methodSymbol = context.SemanticModel.GetSymbolInfo(invocationExpressionSyntax).Symbol as IMethodSymbol;
+
+        if (methodSymbol==null)
+        {
+            return;
+        }
+
+        // 筛选出调用ET.Log的日志输出
+        if (methodSymbol.ContainingType.ToString() != Definition.ETLog)
+        {
+            return;
+        }
+
+        if (invocationExpressionSyntax.GetNeareastAncestor<ClassDeclarationSyntax>() is not ClassDeclarationSyntax parentClassSyntax)
+        {
+            return;
+        }
+
+        if (context.SemanticModel.GetDeclaredSymbol(parentClassSyntax) is not INamedTypeSymbol parentClassSymbol)
+        {
+            return;
+        }
+
+        // 判断是否在实体类内部调用
+        if (parentClassSymbol.ToString()==Definition.EntityType|| parentClassSymbol.ToString()==Definition.LSEntityType || parentClassSymbol.BaseType?.ToString()==Definition.EntityType ||parentClassSymbol.BaseType?.ToString()==Definition.LSEntityType)
+        {
+            Diagnostic diagnostic = Diagnostic.Create(FiberLogAnalyzerRule.Rule, invocationExpressionSyntax?.GetLocation());
+            context.ReportDiagnostic(diagnostic);
+            return;
+        }
+
+        // 判断是否在含实体类参数的函数内调用
+        if (invocationExpressionSyntax.GetNeareastAncestor<MethodDeclarationSyntax>() is not MethodDeclarationSyntax methodDeclarationSyntax)
+        {
+            return;
+        }
+
+        if (context.SemanticModel.GetDeclaredSymbol(methodDeclarationSyntax) is not IMethodSymbol containningMethodSymbol)
+        {
+            return;
+        }
+
+        foreach (var parameter in containningMethodSymbol.Parameters)
+        {
+            var parameterType = parameter.Type.ToString();
+            var parameterBaseType = parameter.Type.BaseType?.ToString();
+            if (parameterType== Definition.EntityType|| parameterType==Definition.LSEntityType ||parameterBaseType==Definition.EntityType ||parameterBaseType==Definition.LSEntityType)
+            {
+                Diagnostic diagnostic = Diagnostic.Create(FiberLogAnalyzerRule.Rule, invocationExpressionSyntax?.GetLocation());
+                context.ReportDiagnostic(diagnostic);
+                return;
+            }
+        }
+    }
+}

+ 4 - 2
Share/Analyzer/Config/Definition.cs

@@ -63,8 +63,8 @@
         public const string IDeserializeInterface = "ET.IDeserialize";
         public const string DeserializeMethod = "Deserialize";
 
-        public const string IGetComponentInterface = "ET.IGetComponent";
-        public const string GetComponentMethod = "ET.GetComponent";
+        public const string IGetComponentInterface = "ET.IGetComponentSys";
+        public const string GetComponentMethod = "GetComponentSys";
 
         public const string ILoadInterface = "ET.ILoad";
         public const string LoadMethod = "Load";
@@ -84,6 +84,8 @@
 
         public const string ILSUpdateInterface = "ET.ILSUpdate";
         public const string LSUpdateMethod = "LSUpdate";
+
+        public const string ETLog = "ET.Log";
     }
 }
 

+ 2 - 0
Share/Analyzer/Config/DiagnosticIds.cs

@@ -52,5 +52,7 @@
 
         public const string EntitySystemMethodNeedSystemOfAttrAnalyzerRuleId = "ET0025";
 
+        public const string FiberLogAnalyzerRuleId = "ET0026";
+
     }
 }

+ 18 - 0
Share/Analyzer/Config/DiagnosticRules.cs

@@ -359,4 +359,22 @@ namespace ET.Analyzer
                     true,
                     Description);
     }
+
+    public static class FiberLogAnalyzerRule
+    {
+        private const string Title = "实体类内部或含有实体类参数的函数内部必须使用Fiber输出日志";
+
+        private const string MessageFormat = "实体类内部或含有实体类参数的函数内部必须使用Fiber输出日志";
+
+        private const string Description = "实体类内部或含有实体类参数的函数内部必须使用Fiber输出日志.";
+
+        public static readonly DiagnosticDescriptor Rule =
+                new DiagnosticDescriptor(DiagnosticIds.FiberLogAnalyzerRuleId,
+                    Title,
+                    MessageFormat,
+                    DiagnosticCategories.All,
+                    DiagnosticSeverity.Error,
+                    true,
+                    Description);
+    }
 }

+ 51 - 0
Share/Analyzer/Extension/AnalyzerHelper.cs

@@ -428,6 +428,7 @@ namespace ET.Analyzer
         /// </summary>
         public static bool HasMethodWithParams(this INamedTypeSymbol namedTypeSymbol, string methodName, params ITypeSymbol[] typeSymbols)
         {
+            
             foreach (var member in namedTypeSymbol.GetMembers())
             {
                 if (member is not IMethodSymbol methodSymbol)
@@ -469,6 +470,56 @@ namespace ET.Analyzer
 
             return false;
         }
+        
+        /// <summary>
+        /// 类型symbol是否有指定名字 指定参数的方法
+        /// </summary>
+        public static bool HasMethodWithParams(this INamedTypeSymbol namedTypeSymbol, string methodName, params string[] typeSymbols)
+        {
+            
+            foreach (var member in namedTypeSymbol.GetMembers())
+            {
+                if (member is not IMethodSymbol methodSymbol)
+                {
+                    continue;
+                }
+
+                if (methodSymbol.Name!=methodName)
+                {
+                    continue;
+                }
+                
+                if (typeSymbols.Length!=methodSymbol.Parameters.Length)
+                {
+                    continue;
+                }
+                
+                if (typeSymbols.Length==0)
+                {
+                    return true;
+                }
+
+                bool isEqual = true;
+                
+                for (int i = 0; i < typeSymbols.Length; i++)
+                {
+                    if (typeSymbols[i]!=methodSymbol.Parameters[i].Type.ToString())
+                    {
+                        isEqual = false;
+                        break;
+                    }
+                }
+
+                if (isEqual)
+                {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+        
+        
 
 
         /// <summary>

+ 13 - 0
Share/Share.SourceGenerator/Generator/ETSystemGenerator/ETSystemGenerator.cs

@@ -163,6 +163,8 @@ namespace {{namespaceName}}
                 string argsVarsWithout0 = string.Join(", ", argsVarsWithout0List);
                 string argsTypesVarsWithout0 = string.Join(", ", argsTypeVarsWithout0List);
 
+                SpeicalProcessForArgs();
+                
                 code = code.Replace("$attribute$", attributeString);
                 code = code.Replace("$attributeType$", attributeType);
                 code = code.Replace("$methodName$", methodName);
@@ -185,10 +187,21 @@ namespace {{namespaceName}}
                 string fileName = $"{namespaceName}.{className}.{methodName}.{argsTypesUnderLine}.g.cs";
                 
                 context.AddSource(fileName, code);
+                
+                void SpeicalProcessForArgs()
+                {
+                    if ((attributeType=="EntitySystem" || attributeType=="LSEntitySystem")&&methodName==Definition.GetComponentMethod)
+                    {
+                        argsTypes = argsTypes.Split(',')[0];
+                    }
+                }
             }
         }
     }
 
+
+    
+
     class SyntaxContextReceiver: ISyntaxContextReceiver
     {
         internal static ISyntaxContextReceiver Create(AttributeTemplate attributeTemplate)

+ 1 - 1
Unity/Assets/Scripts/Core/Entity/IGetComponentSysSystem.cs.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 7b625637dbe58da439eb317e7172bed6
+guid: 6ac363a766c88274a9afa9f4fc063d52
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2

+ 0 - 11
Unity/Assets/Scripts/Core/Entity/IGetComponentSystem.cs.meta

@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 29d1c2616b1b96540a5f57836f3175e2
-MonoImporter:
-  externalObjects: {}
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: