Files
TEngine/Tools/GameEventSourceGenerator/.idea/.idea.SourceGenerator/.idea/CopilotChatHistory.xml
Alex-Rachel 551727687f TEngine 6
2025-03-07 23:09:46 +08:00

253 lines
80 KiB
XML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CopilotChatHistory">
<option name="conversations">
<list>
<Conversation>
<option name="createTime" value="1741358197966" />
<option name="id" value="019571096cce7d9faa91ed5f210ae04a" />
<option name="title" value="@workspace 162行 sb.AppendLine($&quot; " />
<option name="turns">
<list>
<Turn>
<option name="agent" value="workspace" />
<option name="answer" value="&lt;gsrmp&gt;&#10;好的用户的问题是关于X#源代码生成器中参数类型可能缺少命名空间的问题。他们提供的代码片段显示在生成方法时,参数列表直接使用了类型名称,而没有考虑可能的命名空间冲突。需要优化这部分,确保生成的代码中的类型包含完整的命名空间。&#10;&#10;首先我需要分析现有的代码。在VevmgRmgviuzxvTvmvizgli.xh的第839行附近生成方法参数的部分使用了nvgslw.KziznvgviOrhg.Kziznvgvih.Hvovxg(k =&gt; $&quot;{k.Gbkv} {k.Rwvmgrurvi}&quot;)。这里的k.Gbkv可能只是类型名称没有命名空间导致生成的代码中类型不明确尤其是在不同命名空间有同名类时会出错。&#10;&#10;解决方案应该是获取每个参数类型的完全限定名。在Ilhobm中可以通过语义模型获取参数符号然后使用GlWrhkozbHgirmt(HbnyloWrhkozbUlinzg.UfoobJfzorurvwUlinzg)来得到包含命名空间的完整类型名。&#10;&#10;需要检查代码中是否有访问语义模型的途径。在生成器上下文中通常可以通过HbmgzcMlwv获取Hbnylo信息。可能需要修改TvmvizgvVevmgXozhh方法传入语义模型或者通过其他方式获取每个参数的类型符号。&#10;&#10;查看用户提供的代码上下文发现TvmvizgvVevmgXozhh方法的参数包括RmgviuzxvWvxozizgrlmHbmgzc rmgviuzxvMlwv但可能没有直接访问语义模型。因此可能需要调整生成器的结构确保在生成代码时能够访问到每个参数的完全限定类型名。&#10;&#10;具体步骤可能包括:&#10;8. 在生成参数列表时,获取每个参数的类型符号。&#10;7. 使用HbnyloWrhkozbUlinzg.UfoobJfzorurvwUlinzg将类型转换为全局限定的名称例如tolyzo::NbMznvhkzxv.NbGbkv。&#10;6. 替换原有的k.Gbkv为完全限定名。&#10;&#10;需要确保在生成代码时能够正确访问到语义模型以便获取类型符号。可能需要修改方法签名传递必要的上下文如HvnzmgrxNlwvo或者在生成器初始化时获取这些信息。&#10;&#10;此外,还需要测试生成的代码,确保所有类型都正确引用了命名空间,避免编译错误。同时,考虑性能影响,因为获取符号可能增加处理时间,但源生成器通常在编译时运行,影响应该可控。&#10;&#10;最后,修改对应的代码行,将参数类型替换为完全限定名,并验证生成的代码是否正确。&#10;&lt;/gsrmp&gt;&#10;&#10;&#10;需要为参数类型添加全局命名空间限定。修改参数生成逻辑,使用符号的完全限定名称:&#10;&#10;在`VevmgRmgviuzxvTvmvizgli.xh`中修改参数生成部分:&#10;&#10;```xhszik&#10;// 原代码&#10;ezi kziznvgvih = hgirmt.Qlrm(&quot;, &quot;, nvgslw.KziznvgviOrhg.Kziznvgvih.Hvovxg(k =&gt; $&quot;{k.Gbkv} {k.Rwvmgrurvi}&quot;));&#10;&#10;// 修改为&#10;ezi kziznvgvih = hgirmt.Qlrm(&quot;, &quot;, nvgslw.KziznvgviOrhg.Kziznvgvih.Hvovxg(k =&gt; &#10; $&quot;{k.Gbkv.TvgUfooMznvDrgsTolyzo()} {k.Rwvmgrurvi}&quot;));&#10;```&#10;&#10;需要新增扩展方法(添加到`ZmzobaviSvokvi.xh`&#10;&#10;###[Zmzobavi/Vcgvmhrlm/ZmzobaviSvokvi.xh](urov:///Zmzobavi/Vcgvmhrlm/ZmzobaviSvokvi.xh)&#10;```xhszik&#10;kfyorx hgzgrx hgirmt TvgUfooMznvDrgsTolyzo(gsrh GbkvHbmgzc gbkvHbmgzc)&#10;{&#10; ru (gbkvHbmgzc rh KivwvurmvwGbkvHbmgzc kivwvurmvwGbkv)&#10; ivgfim kivwvurmvwGbkv.Pvbdliw.EzofvGvcg;&#10; &#10; ru (gbkvHbmgzc rh RwvmgrurviMznvHbmgzc rwvmgrurvi)&#10; ivgfim $&quot;tolyzo::{rwvmgrurvi.Rwvmgrurvi.EzofvGvcg}&quot;;&#10; &#10; ru (gbkvHbmgzc rh JfzorurvwMznvHbmgzc jfzorurvwMznv)&#10; ivgfim $&quot;tolyzo::{jfzorurvwMznv.GlHgirmt()}&quot;;&#10; &#10; ivgfim gbkvHbmgzc.GlHgirmt();&#10;}&#10;```&#10;&#10;该方案通过:&#10;8. 为类型名称添加`tolyzo::`前缀避免命名冲突&#10;7. 处理基础类型如rmg/hgirmt不需要命名空间&#10;6. 支持完整限定名的类型声明&#10;5. 保留原有类型解析逻辑的同时增加命名空间保障&#10;&#10;注意:需要确保在代码生成上下文中可以访问到`GbkvHbmgzc`的符号信息,若需要更精确的类型解析,需结合语义模型获取完全限定名。" />
<option name="chatResource" value="user" />
<option name="codeReferences">
<list>
<CodeReferencesBean>
<option name="content" value=" hy.ZkkvmwOrmv($&quot; kfyorx elrw {nvgslwMznv}({kziznvgvih})&quot;); " />
<option name="end_line" value="161" />
<option name="filename" value="EventInterfaceGenerator.cs" />
<option name="language" value="C#" />
<option name="range">
<Range>
<option name="end">
<Position>
<option name="character" value="79" />
<option name="line" value="161" />
</Position>
</option>
<option name="start">
<Position>
<option name="line" value="161" />
</Position>
</option>
</Range>
</option>
<option name="start_line" value="161" />
<option name="type" value="editor" />
<option name="url" value="file:///E:/WorkSpace/ZGame/Tools/GameEventSourceGenerator/SourceGenerator/Generator/EventInterfaceGenerator.cs" />
</CodeReferencesBean>
</list>
</option>
<option name="codebaseContextVariableValues">
<list>
<CodebaseContextVariableValue>
<option name="chunk" value="SourceGenerator\Generator\EventInterfaceGenerator.cs: sb.AppendLine($&quot;using {Definition.FrameworkNameSpace};&quot;);&#10; sb.AppendLine();&#10; sb.AppendLine($&quot;namespace {Definition.NameSpace}&quot;);&#10; sb.AppendLine($&quot;{{&quot;);&#10; sb.AppendLine($&quot; public static class GameEventHelper&quot;);&#10; sb.AppendLine(&quot; {&quot;);&#10; sb.AppendLine($&quot; public static void Init()&quot;);&#10; sb.AppendLine(&quot; {&quot;);&#10; foreach (var className in classNameList)&#10; {&#10; sb.AppendLine($&quot; var m_{className} = new {className}(GameEvent.EventMgr.GetDispatcher());&quot;);&#10; }&#10; sb.AppendLine(&quot; }&quot;);&#10; sb.AppendLine(&quot; }&quot;);&#10; sb.AppendLine(&quot;}&quot;);&#10; return sb.ToString();&#10;}&#10;private string GenerateEventClass(string interfaceName, string className, InterfaceDeclarationSyntax interfaceNode) &#10;{ &#10; var methods = interfaceNode.Members.OfType&lt;MethodDeclarationSyntax&gt;(); &#10; var sb = new StringBuilder(); &#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;This code was generated by autoBindTool.&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;Changes to this file may cause incorrect behavior and will be lost if&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;the code is regenerated.&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;/auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine();" />
<option name="filePath" value="$PROJECT_DIR$/SourceGenerator/Generator/EventInterfaceGenerator.cs" />
<option name="range">
<Range>
<option name="endColumn" value="1" />
<option name="endLine" value="108" />
<option name="startColumn" value="1" />
<option name="startLine" value="74" />
</Range>
</option>
<option name="relativePath" value="SourceGenerator\Generator\EventInterfaceGenerator.cs" />
</CodebaseContextVariableValue>
<CodebaseContextVariableValue>
<option name="chunk" value="SourceGenerator\Generator\EventInterfaceGenerator.cs: var parameters = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; $&quot;{p.Type} {p.Identifier}&quot;)); &#10; sb.AppendLine($&quot; public void {methodName}({parameters})&quot;); &#10; sb.AppendLine(&quot; {&quot;); &#10; if (method.ParameterList.Parameters.Count &gt; 0) &#10; { &#10; var paramNames = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; p.Identifier.ToString())); &#10; sb.AppendLine($&quot; _dispatcher.Send({interfaceName}_Event.{methodName}, {paramNames});&quot;); &#10; } &#10; else &#10; { &#10; sb.AppendLine($&quot; _dispatcher.Send({interfaceName}_Event.{methodName});&quot;); &#10; } &#10; sb.AppendLine(&quot; }&quot;); &#10; } &#10; sb.AppendLine(&quot; }&quot;); &#10; sb.AppendLine(&quot;}&quot;); &#10; return sb.ToString(); &#10; } &#10;}" />
<option name="filePath" value="$PROJECT_DIR$/SourceGenerator/Generator/EventInterfaceGenerator.cs" />
<option name="range">
<Range>
<option name="endColumn" value="1" />
<option name="endLine" value="180" />
<option name="startColumn" value="1" />
<option name="startLine" value="161" />
</Range>
</option>
<option name="relativePath" value="SourceGenerator\Generator\EventInterfaceGenerator.cs" />
</CodebaseContextVariableValue>
<CodebaseContextVariableValue>
<option name="chunk" value="SourceGenerator\Generator\EventInterfaceGenerator.cs: .Concat(new[] { interfaceName })&#10; .Aggregate((a, b) =&gt; a + &quot;.&quot; + b);&#10; var eventClassName = $&quot;{interfaceName}_Event&quot;; &#10; var eventClassCode = GenerateEventClass(interfaceName, eventClassName, interfaceNode); &#10; context.AddSource($&quot;{eventClassName}.g.cs&quot;, eventClassCode); &#10; // 生成实现类 &#10; var implementationClassCode = GenerateImplementationClass(fullName, interfaceName, interfaceNode); &#10; context.AddSource($&quot;{interfaceName}_Gen.g.cs&quot;, implementationClassCode); &#10; &#10; &#10; classNameList.Add($&quot;{interfaceName}_Gen&quot;);&#10; } &#10; } &#10; &#10; string uniqueFileName = $&quot;GameEventHelper.g.cs&quot;;&#10; context.AddSource(uniqueFileName, GenerateGameEventHelper(classNameList));&#10;} &#10;&#10;private string GenerateGameEventHelper(List&lt;string&gt; classNameList)&#10;{&#10; var sb = new StringBuilder();&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;);&#10; sb.AppendLine($&quot;// &lt;auto-generated&gt;&quot;);&#10; sb.AppendLine($&quot;// This code was generated by autoBindTool.&quot;);&#10; sb.AppendLine($&quot;// Changes to this file may cause incorrect behavior and will be lost if&quot;);&#10; sb.AppendLine($&quot;// the code is regenerated.&quot;);&#10; sb.AppendLine($&quot;// &lt;/auto-generated&gt;&quot;);&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;);&#10; sb.AppendLine();&#10; sb.AppendLine($&quot;using UnityEngine;&quot;);&#10; sb.AppendLine($&quot;using UnityEngine.UI;&quot;);" />
<option name="filePath" value="$PROJECT_DIR$/SourceGenerator/Generator/EventInterfaceGenerator.cs" />
<option name="range">
<Range>
<option name="endColumn" value="1" />
<option name="endLine" value="73" />
<option name="startColumn" value="1" />
<option name="startLine" value="41" />
</Range>
</option>
<option name="relativePath" value="SourceGenerator\Generator\EventInterfaceGenerator.cs" />
</CodebaseContextVariableValue>
<CodebaseContextVariableValue>
<option name="chunk" value="Analyzer\Extension\AnalyzerHelper.cs: /// &lt;typeparam name=&quot;T&quot;&gt;指定语法节点类型&lt;/typeparam&gt;&#10;/// &lt;returns&gt;最后一个指定类型节点&lt;/returns&gt;&#10;public static T? GetLastChild&lt;T&gt;(this SyntaxNode syntaxNode) where T : SyntaxNode&#10;{&#10; foreach (SyntaxNode? childNode in syntaxNode.ChildNodes().Reverse())&#10; {&#10; if (childNode.GetType() == typeof(T))&#10; {&#10; return childNode as T;&#10; }&#10; }&#10; return null;&#10;}&#10;/// &lt;summary&gt;&#10;/// 获取语法节点所属的ClassDeclarationSyntax&#10;/// &lt;/summary&gt;&#10;public static ClassDeclarationSyntax? GetParentClassDeclaration(this SyntaxNode syntaxNode)&#10;{&#10; SyntaxNode? parentNode = syntaxNode.Parent;&#10; while (parentNode != null)&#10; {&#10; if (parentNode is ClassDeclarationSyntax classDeclarationSyntax)&#10; {&#10; return classDeclarationSyntax;&#10; }&#10; parentNode = parentNode.Parent;&#10; }&#10; return null;&#10;}&#10;/// &lt;summary&gt;&#10;/// INamedTypeSymbol 是否有指定的Attribute&#10;/// &lt;/summary&gt;&#10;public static bool HasAttribute(this ITypeSymbol typeSymbol, string AttributeName)&#10;{&#10; foreach (AttributeData? attributeData in typeSymbol.GetAttributes())&#10; {&#10; if (attributeData.AttributeClass?.ToString() == AttributeName)&#10; {&#10; return true;&#10; }&#10; }&#10; return false;&#10;}&#10;public static bool HasAttributeInTypeAndBaseTyes(this ITypeSymbol typeSymbol, string AttributeName)&#10;{" />
<option name="filePath" value="$PROJECT_DIR$/Analyzer/Extension/AnalyzerHelper.cs" />
<option name="range">
<Range>
<option name="endColumn" value="1" />
<option name="endLine" value="100" />
<option name="startColumn" value="1" />
<option name="startLine" value="49" />
</Range>
</option>
<option name="relativePath" value="Analyzer\Extension\AnalyzerHelper.cs" />
</CodebaseContextVariableValue>
<CodebaseContextVariableValue>
<option name="chunk" value="Analyzer\Extension\AnalyzerHelper.cs: using System;&#10;using System.Collections.Generic;&#10;using System.Linq;&#10;using Microsoft.CodeAnalysis;&#10;using Microsoft.CodeAnalysis.CSharp;&#10;using Microsoft.CodeAnalysis.CSharp.Syntax;&#10;using Microsoft.CodeAnalysis.Diagnostics;&#10;using Microsoft.CodeAnalysis.FlowAnalysis;&#10;using Exception = System.Exception;&#10;namespace Analyzer&#10;{&#10; public static class AnalyzerHelper&#10; {&#10; /// &lt;summary&gt;&#10; /// 获取语法树节点的子节点中第一个指定类型节点&#10; /// &lt;/summary&gt;&#10; /// &lt;param name=&quot;syntaxNode&quot;&gt;语法树节点&lt;/param&gt;&#10; /// &lt;typeparam name=&quot;T&quot;&gt;指定语法节点类型&lt;/typeparam&gt;&#10; /// &lt;returns&gt;第一个指定类型节点&lt;/returns&gt;&#10; public static T? GetFirstChild&lt;T&gt;(this SyntaxNode syntaxNode) where T : SyntaxNode&#10; {&#10; foreach (SyntaxNode? childNode in syntaxNode.ChildNodes())&#10; {&#10; if (childNode.GetType() == typeof(T))&#10; {&#10; return childNode as T;&#10; }&#10; }&#10; return null;&#10; }&#10; public static SyntaxNode? GetFirstChild(this SyntaxNode syntaxNode)&#10; {&#10; var childNodes = syntaxNode.ChildNodes();&#10; if (childNodes.Count() &gt; 0)&#10; {&#10; return childNodes.First();&#10; }&#10; return null;&#10; }&#10; /// &lt;summary&gt;&#10; /// 获取语法树节点的子节点中最后一个指定类型节点&#10; /// &lt;/summary&gt;&#10; /// &lt;param name=&quot;syntaxNode&quot;&gt;语法树节点&lt;/param&gt;" />
<option name="filePath" value="$PROJECT_DIR$/Analyzer/Extension/AnalyzerHelper.cs" />
<option name="range">
<Range>
<option name="endColumn" value="1" />
<option name="endLine" value="48" />
<option name="startColumn" value="1" />
<option name="startLine" value="1" />
</Range>
</option>
<option name="relativePath" value="Analyzer\Extension\AnalyzerHelper.cs" />
</CodebaseContextVariableValue>
<CodebaseContextVariableValue>
<option name="chunk" value="Analyzer\Extension\AnalyzerHelper.cs: BasicBlock? block = controlFlowGraph.Blocks.FirstOrDefault(x =&gt; x.Operations.Any(y =&gt; y.Syntax.Contains(statementSyntax)));&#10; return block;&#10;}&#10;/// &lt;summary&gt;&#10;/// 判断类是否为partial类&#10;/// &lt;/summary&gt;&#10;public static bool IsPartial(this ClassDeclarationSyntax classDeclaration)&#10;{&#10; foreach (var modifier in classDeclaration.Modifiers)&#10; {&#10; if (modifier.IsKind(SyntaxKind.PartialKeyword))&#10; {&#10; return true;&#10; }&#10; }&#10; return false;&#10;}&#10;public static string? GetNameSpace(this INamedTypeSymbol namedTypeSymbol)&#10;{&#10; INamespaceSymbol? namespaceSymbol = namedTypeSymbol.ContainingNamespace;&#10; string? namespaceName = namespaceSymbol?.Name;&#10; while (namespaceSymbol?.ContainingNamespace != null)&#10; {&#10; namespaceSymbol = namespaceSymbol.ContainingNamespace;&#10; if (string.IsNullOrEmpty(namespaceSymbol.Name))&#10; {&#10; break;&#10; }&#10; namespaceName = $&quot;{namespaceSymbol.Name}.{namespaceName}&quot;;&#10; }&#10; if (string.IsNullOrEmpty(namespaceName))&#10; {&#10; return null;&#10; }&#10; return namespaceName;&#10;}&#10;/// &lt;summary&gt;&#10;/// 根据语义模型的文件路径 判断是否需要分析&#10;/// &lt;/summary&gt;&#10;public static bool IsSemanticModelNeedAnalyze(SemanticModel semanticModel, params string[] filePaths)&#10;{&#10; foreach (var filePath in filePaths)&#10; {" />
<option name="filePath" value="$PROJECT_DIR$/Analyzer/Extension/AnalyzerHelper.cs" />
<option name="range">
<Range>
<option name="endColumn" value="1" />
<option name="endLine" value="447" />
<option name="startColumn" value="1" />
<option name="startLine" value="398" />
</Range>
</option>
<option name="relativePath" value="Analyzer\Extension\AnalyzerHelper.cs" />
</CodebaseContextVariableValue>
</list>
</option>
<option name="codebaseReferences">
<list>
<KnowledgeReference>
<option name="chunk" value="SourceGenerator\Generator\EventInterfaceGenerator.cs: sb.AppendLine($&quot;using {Definition.FrameworkNameSpace};&quot;);&#10; sb.AppendLine();&#10; sb.AppendLine($&quot;namespace {Definition.NameSpace}&quot;);&#10; sb.AppendLine($&quot;{{&quot;);&#10; sb.AppendLine($&quot; public static class GameEventHelper&quot;);&#10; sb.AppendLine(&quot; {&quot;);&#10; sb.AppendLine($&quot; public static void Init()&quot;);&#10; sb.AppendLine(&quot; {&quot;);&#10; foreach (var className in classNameList)&#10; {&#10; sb.AppendLine($&quot; var m_{className} = new {className}(GameEvent.EventMgr.GetDispatcher());&quot;);&#10; }&#10; sb.AppendLine(&quot; }&quot;);&#10; sb.AppendLine(&quot; }&quot;);&#10; sb.AppendLine(&quot;}&quot;);&#10; return sb.ToString();&#10;}&#10;private string GenerateEventClass(string interfaceName, string className, InterfaceDeclarationSyntax interfaceNode) &#10;{ &#10; var methods = interfaceNode.Members.OfType&lt;MethodDeclarationSyntax&gt;(); &#10; var sb = new StringBuilder(); &#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;This code was generated by autoBindTool.&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;Changes to this file may cause incorrect behavior and will be lost if&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;the code is regenerated.&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;/auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine();" />
<option name="metadata">
<KnowledgeReferenceMetadata>
<option name="source" value="$PROJECT_DIR$/SourceGenerator/Generator/EventInterfaceGenerator.cs" />
</KnowledgeReferenceMetadata>
</option>
</KnowledgeReference>
<KnowledgeReference>
<option name="chunk" value="SourceGenerator\Generator\EventInterfaceGenerator.cs: var parameters = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; $&quot;{p.Type} {p.Identifier}&quot;)); &#10; sb.AppendLine($&quot; public void {methodName}({parameters})&quot;); &#10; sb.AppendLine(&quot; {&quot;); &#10; if (method.ParameterList.Parameters.Count &gt; 0) &#10; { &#10; var paramNames = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; p.Identifier.ToString())); &#10; sb.AppendLine($&quot; _dispatcher.Send({interfaceName}_Event.{methodName}, {paramNames});&quot;); &#10; } &#10; else &#10; { &#10; sb.AppendLine($&quot; _dispatcher.Send({interfaceName}_Event.{methodName});&quot;); &#10; } &#10; sb.AppendLine(&quot; }&quot;); &#10; } &#10; sb.AppendLine(&quot; }&quot;); &#10; sb.AppendLine(&quot;}&quot;); &#10; return sb.ToString(); &#10; } &#10;}" />
<option name="metadata">
<KnowledgeReferenceMetadata>
<option name="source" value="$PROJECT_DIR$/SourceGenerator/Generator/EventInterfaceGenerator.cs" />
</KnowledgeReferenceMetadata>
</option>
</KnowledgeReference>
<KnowledgeReference>
<option name="chunk" value="SourceGenerator\Generator\EventInterfaceGenerator.cs: .Concat(new[] { interfaceName })&#10; .Aggregate((a, b) =&gt; a + &quot;.&quot; + b);&#10; var eventClassName = $&quot;{interfaceName}_Event&quot;; &#10; var eventClassCode = GenerateEventClass(interfaceName, eventClassName, interfaceNode); &#10; context.AddSource($&quot;{eventClassName}.g.cs&quot;, eventClassCode); &#10; // 生成实现类 &#10; var implementationClassCode = GenerateImplementationClass(fullName, interfaceName, interfaceNode); &#10; context.AddSource($&quot;{interfaceName}_Gen.g.cs&quot;, implementationClassCode); &#10; &#10; &#10; classNameList.Add($&quot;{interfaceName}_Gen&quot;);&#10; } &#10; } &#10; &#10; string uniqueFileName = $&quot;GameEventHelper.g.cs&quot;;&#10; context.AddSource(uniqueFileName, GenerateGameEventHelper(classNameList));&#10;} &#10;&#10;private string GenerateGameEventHelper(List&lt;string&gt; classNameList)&#10;{&#10; var sb = new StringBuilder();&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;);&#10; sb.AppendLine($&quot;// &lt;auto-generated&gt;&quot;);&#10; sb.AppendLine($&quot;// This code was generated by autoBindTool.&quot;);&#10; sb.AppendLine($&quot;// Changes to this file may cause incorrect behavior and will be lost if&quot;);&#10; sb.AppendLine($&quot;// the code is regenerated.&quot;);&#10; sb.AppendLine($&quot;// &lt;/auto-generated&gt;&quot;);&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;);&#10; sb.AppendLine();&#10; sb.AppendLine($&quot;using UnityEngine;&quot;);&#10; sb.AppendLine($&quot;using UnityEngine.UI;&quot;);" />
<option name="metadata">
<KnowledgeReferenceMetadata>
<option name="source" value="$PROJECT_DIR$/SourceGenerator/Generator/EventInterfaceGenerator.cs" />
</KnowledgeReferenceMetadata>
</option>
</KnowledgeReference>
<KnowledgeReference>
<option name="chunk" value="Analyzer\Extension\AnalyzerHelper.cs: /// &lt;typeparam name=&quot;T&quot;&gt;指定语法节点类型&lt;/typeparam&gt;&#10;/// &lt;returns&gt;最后一个指定类型节点&lt;/returns&gt;&#10;public static T? GetLastChild&lt;T&gt;(this SyntaxNode syntaxNode) where T : SyntaxNode&#10;{&#10; foreach (SyntaxNode? childNode in syntaxNode.ChildNodes().Reverse())&#10; {&#10; if (childNode.GetType() == typeof(T))&#10; {&#10; return childNode as T;&#10; }&#10; }&#10; return null;&#10;}&#10;/// &lt;summary&gt;&#10;/// 获取语法节点所属的ClassDeclarationSyntax&#10;/// &lt;/summary&gt;&#10;public static ClassDeclarationSyntax? GetParentClassDeclaration(this SyntaxNode syntaxNode)&#10;{&#10; SyntaxNode? parentNode = syntaxNode.Parent;&#10; while (parentNode != null)&#10; {&#10; if (parentNode is ClassDeclarationSyntax classDeclarationSyntax)&#10; {&#10; return classDeclarationSyntax;&#10; }&#10; parentNode = parentNode.Parent;&#10; }&#10; return null;&#10;}&#10;/// &lt;summary&gt;&#10;/// INamedTypeSymbol 是否有指定的Attribute&#10;/// &lt;/summary&gt;&#10;public static bool HasAttribute(this ITypeSymbol typeSymbol, string AttributeName)&#10;{&#10; foreach (AttributeData? attributeData in typeSymbol.GetAttributes())&#10; {&#10; if (attributeData.AttributeClass?.ToString() == AttributeName)&#10; {&#10; return true;&#10; }&#10; }&#10; return false;&#10;}&#10;public static bool HasAttributeInTypeAndBaseTyes(this ITypeSymbol typeSymbol, string AttributeName)&#10;{" />
<option name="metadata">
<KnowledgeReferenceMetadata>
<option name="source" value="$PROJECT_DIR$/Analyzer/Extension/AnalyzerHelper.cs" />
</KnowledgeReferenceMetadata>
</option>
</KnowledgeReference>
<KnowledgeReference>
<option name="chunk" value="Analyzer\Extension\AnalyzerHelper.cs: using System;&#10;using System.Collections.Generic;&#10;using System.Linq;&#10;using Microsoft.CodeAnalysis;&#10;using Microsoft.CodeAnalysis.CSharp;&#10;using Microsoft.CodeAnalysis.CSharp.Syntax;&#10;using Microsoft.CodeAnalysis.Diagnostics;&#10;using Microsoft.CodeAnalysis.FlowAnalysis;&#10;using Exception = System.Exception;&#10;namespace Analyzer&#10;{&#10; public static class AnalyzerHelper&#10; {&#10; /// &lt;summary&gt;&#10; /// 获取语法树节点的子节点中第一个指定类型节点&#10; /// &lt;/summary&gt;&#10; /// &lt;param name=&quot;syntaxNode&quot;&gt;语法树节点&lt;/param&gt;&#10; /// &lt;typeparam name=&quot;T&quot;&gt;指定语法节点类型&lt;/typeparam&gt;&#10; /// &lt;returns&gt;第一个指定类型节点&lt;/returns&gt;&#10; public static T? GetFirstChild&lt;T&gt;(this SyntaxNode syntaxNode) where T : SyntaxNode&#10; {&#10; foreach (SyntaxNode? childNode in syntaxNode.ChildNodes())&#10; {&#10; if (childNode.GetType() == typeof(T))&#10; {&#10; return childNode as T;&#10; }&#10; }&#10; return null;&#10; }&#10; public static SyntaxNode? GetFirstChild(this SyntaxNode syntaxNode)&#10; {&#10; var childNodes = syntaxNode.ChildNodes();&#10; if (childNodes.Count() &gt; 0)&#10; {&#10; return childNodes.First();&#10; }&#10; return null;&#10; }&#10; /// &lt;summary&gt;&#10; /// 获取语法树节点的子节点中最后一个指定类型节点&#10; /// &lt;/summary&gt;&#10; /// &lt;param name=&quot;syntaxNode&quot;&gt;语法树节点&lt;/param&gt;" />
<option name="metadata">
<KnowledgeReferenceMetadata>
<option name="source" value="$PROJECT_DIR$/Analyzer/Extension/AnalyzerHelper.cs" />
</KnowledgeReferenceMetadata>
</option>
</KnowledgeReference>
<KnowledgeReference>
<option name="chunk" value="Analyzer\Extension\AnalyzerHelper.cs: BasicBlock? block = controlFlowGraph.Blocks.FirstOrDefault(x =&gt; x.Operations.Any(y =&gt; y.Syntax.Contains(statementSyntax)));&#10; return block;&#10;}&#10;/// &lt;summary&gt;&#10;/// 判断类是否为partial类&#10;/// &lt;/summary&gt;&#10;public static bool IsPartial(this ClassDeclarationSyntax classDeclaration)&#10;{&#10; foreach (var modifier in classDeclaration.Modifiers)&#10; {&#10; if (modifier.IsKind(SyntaxKind.PartialKeyword))&#10; {&#10; return true;&#10; }&#10; }&#10; return false;&#10;}&#10;public static string? GetNameSpace(this INamedTypeSymbol namedTypeSymbol)&#10;{&#10; INamespaceSymbol? namespaceSymbol = namedTypeSymbol.ContainingNamespace;&#10; string? namespaceName = namespaceSymbol?.Name;&#10; while (namespaceSymbol?.ContainingNamespace != null)&#10; {&#10; namespaceSymbol = namespaceSymbol.ContainingNamespace;&#10; if (string.IsNullOrEmpty(namespaceSymbol.Name))&#10; {&#10; break;&#10; }&#10; namespaceName = $&quot;{namespaceSymbol.Name}.{namespaceName}&quot;;&#10; }&#10; if (string.IsNullOrEmpty(namespaceName))&#10; {&#10; return null;&#10; }&#10; return namespaceName;&#10;}&#10;/// &lt;summary&gt;&#10;/// 根据语义模型的文件路径 判断是否需要分析&#10;/// &lt;/summary&gt;&#10;public static bool IsSemanticModelNeedAnalyze(SemanticModel semanticModel, params string[] filePaths)&#10;{&#10; foreach (var filePath in filePaths)&#10; {" />
<option name="metadata">
<KnowledgeReferenceMetadata>
<option name="source" value="$PROJECT_DIR$/Analyzer/Extension/AnalyzerHelper.cs" />
</KnowledgeReferenceMetadata>
</option>
</KnowledgeReference>
</list>
</option>
<option name="command" value="" />
<option name="conversationId" value="0195710a442d724cb9dae8c9d263f0ee" />
<option name="historyDocumentMap">
<map>
<entry key="file:///E:/WorkSpace/ZGame/Tools/GameEventSourceGenerator/SourceGenerator/Generator/EventInterfaceGenerator.cs" value="using Microsoft.CodeAnalysis; &#10;using Microsoft.CodeAnalysis.CSharp; &#10;using Microsoft.CodeAnalysis.CSharp.Syntax; &#10;using System.Collections.Generic; &#10;using System.Linq; &#10;using System.Text;&#10;using Analyzer;&#10;&#10;[Generator] &#10;public class EventInterfaceGenerator : ISourceGenerator &#10;{ &#10; public void Initialize(GeneratorInitializationContext context) &#10; { &#10; // 可以在这里进行初始化 &#10; } &#10;&#10; public void Execute(GeneratorExecutionContext context) &#10; { &#10; // 获取当前语法树 &#10; var syntaxTrees = context.Compilation.SyntaxTrees; &#10; &#10; List&lt;string&gt; classNameList = new List&lt;string&gt;();&#10;&#10; foreach (var tree in syntaxTrees) &#10; { &#10; var root = tree.GetRoot(); &#10; var interfaces = root.DescendantNodes() &#10; .OfType&lt;InterfaceDeclarationSyntax&gt;() &#10; .Where(i =&gt; i.AttributeLists.Count &gt; 0 &amp;&amp; &#10; i.AttributeLists &#10; .Any(a =&gt; a.Attributes &#10; .Any(attr =&gt; attr.Name.ToString() == $&quot;{Definition.EventInterface}&quot;))); &#10; &#10; foreach (var interfaceNode in interfaces) &#10; { &#10; var interfaceName = interfaceNode.Identifier.ToString(); &#10; var fullName = interfaceNode.SyntaxTree.GetRoot()&#10; .DescendantNodes()&#10; .OfType&lt;NamespaceDeclarationSyntax&gt;()&#10; .Select(ns =&gt; ns.Name.ToString())&#10; .Concat(new[] { interfaceName })&#10; .Aggregate((a, b) =&gt; a + &quot;.&quot; + b);&#10; var eventClassName = $&quot;{interfaceName}_Event&quot;; &#10; var eventClassCode = GenerateEventClass(interfaceName, eventClassName, interfaceNode); &#10;&#10; context.AddSource($&quot;{eventClassName}.g.cs&quot;, eventClassCode); &#10;&#10; // 生成实现类 &#10; var implementationClassCode = GenerateImplementationClass(fullName, interfaceName, interfaceNode); &#10; context.AddSource($&quot;{interfaceName}_Gen.g.cs&quot;, implementationClassCode); &#10; &#10; &#10; classNameList.Add($&quot;{interfaceName}_Gen&quot;);&#10; } &#10; } &#10; &#10; string uniqueFileName = $&quot;GameEventHelper.g.cs&quot;;&#10; context.AddSource(uniqueFileName, GenerateGameEventHelper(classNameList));&#10; } &#10; &#10; private string GenerateGameEventHelper(List&lt;string&gt; classNameList)&#10; {&#10; var sb = new StringBuilder();&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;);&#10; sb.AppendLine($&quot;// &lt;auto-generated&gt;&quot;);&#10; sb.AppendLine($&quot;// This code was generated by autoBindTool.&quot;);&#10; sb.AppendLine($&quot;// Changes to this file may cause incorrect behavior and will be lost if&quot;);&#10; sb.AppendLine($&quot;// the code is regenerated.&quot;);&#10; sb.AppendLine($&quot;// &lt;/auto-generated&gt;&quot;);&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;);&#10; sb.AppendLine();&#10; sb.AppendLine($&quot;using UnityEngine;&quot;);&#10; sb.AppendLine($&quot;using UnityEngine.UI;&quot;);&#10; sb.AppendLine($&quot;using {Definition.FrameworkNameSpace};&quot;);&#10; sb.AppendLine();&#10; sb.AppendLine($&quot;namespace {Definition.NameSpace}&quot;);&#10; sb.AppendLine($&quot;{{&quot;);&#10; sb.AppendLine($&quot; public static class GameEventHelper&quot;);&#10; sb.AppendLine(&quot; {&quot;);&#10; sb.AppendLine($&quot; public static void Init()&quot;);&#10; sb.AppendLine(&quot; {&quot;);&#10;&#10; foreach (var className in classNameList)&#10; {&#10; sb.AppendLine($&quot; var m_{className} = new {className}(GameEvent.EventMgr.GetDispatcher());&quot;);&#10; }&#10;&#10; sb.AppendLine(&quot; }&quot;);&#10;&#10;&#10; sb.AppendLine(&quot; }&quot;);&#10; sb.AppendLine(&quot;}&quot;);&#10; return sb.ToString();&#10; }&#10;&#10; private string GenerateEventClass(string interfaceName, string className, InterfaceDeclarationSyntax interfaceNode) &#10; { &#10; var methods = interfaceNode.Members.OfType&lt;MethodDeclarationSyntax&gt;(); &#10; var sb = new StringBuilder(); &#10;&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;This code was generated by autoBindTool.&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;Changes to this file may cause incorrect behavior and will be lost if&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;the code is regenerated.&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;/auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine(); &#10; sb.AppendLine($&quot;using UnityEngine;&quot;); &#10; sb.AppendLine($&quot;using UnityEngine.UI;&quot;); &#10; sb.AppendLine($&quot;using {Definition.FrameworkNameSpace};&quot;); &#10; sb.AppendLine(); &#10; sb.AppendLine($&quot;namespace {Definition.NameSpace}&quot;); &#10; sb.AppendLine(&quot;{&quot;); &#10; sb.AppendLine($&quot; public partial class {className}&quot;); &#10; sb.AppendLine(&quot; {&quot;); &#10;&#10; foreach (var method in methods) &#10; { &#10; var methodName = method.Identifier.ToString(); &#10; var parameters = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; $&quot;{p.Type} {p.Identifier}&quot;)); &#10; sb.AppendLine($&quot; public static readonly int {methodName} = {Definition.StringToHash}(\&quot;{className}.{methodName}\&quot;);&quot;); &#10; } &#10;&#10; sb.AppendLine(&quot; }&quot;); &#10; sb.AppendLine(&quot;}&quot;); &#10; return sb.ToString(); &#10; } &#10;&#10; private string GenerateImplementationClass(string interfaceFullName, string interfaceName, InterfaceDeclarationSyntax interfaceNode) &#10; { &#10; var sb = new StringBuilder(); &#10; var attributeList = interfaceNode.AttributeLists.First().ToString(); // Assumes there's only one attribute &#10;&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;This code was generated by autoBindTool.&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;Changes to this file may cause incorrect behavior and will be lost if&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;the code is regenerated.&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;/auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine(); &#10; sb.AppendLine($&quot;using UnityEngine;&quot;); &#10; sb.AppendLine($&quot;using UnityEngine.UI;&quot;); &#10; sb.AppendLine($&quot;using {Definition.FrameworkNameSpace};&quot;); &#10; sb.AppendLine(); &#10; sb.AppendLine($&quot;namespace {Definition.NameSpace}&quot;); &#10; sb.AppendLine($&quot;{{&quot;); &#10; sb.AppendLine($&quot; public partial class {interfaceName}_Gen : {interfaceName}&quot;); &#10; sb.AppendLine(&quot; {&quot;); &#10; sb.AppendLine(&quot; private EventDispatcher _dispatcher;&quot;); &#10; sb.AppendLine($&quot; public {interfaceName}_Gen(EventDispatcher dispatcher)&quot;); &#10; sb.AppendLine(&quot; {&quot;); &#10; sb.AppendLine(&quot; _dispatcher = dispatcher;&quot;); &#10; sb.AppendLine($&quot; GameEvent.EventMgr.RegWrapInterface(\&quot;{interfaceFullName}\&quot;, this);&quot;);&#10; sb.AppendLine(&quot; }&quot;); &#10;&#10; foreach (var method in interfaceNode.Members.OfType&lt;MethodDeclarationSyntax&gt;()) &#10; { &#10; var methodName = method.Identifier.ToString(); &#10; var parameters = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; $&quot;{p.Type} {p.Identifier}&quot;)); &#10; sb.AppendLine($&quot; public void {methodName}({parameters})&quot;); &#10; sb.AppendLine(&quot; {&quot;); &#10; if (method.ParameterList.Parameters.Count &gt; 0) &#10; { &#10; var paramNames = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; p.Identifier.ToString())); &#10; sb.AppendLine($&quot; _dispatcher.Send({interfaceName}_Event.{methodName}, {paramNames});&quot;); &#10; } &#10; else &#10; { &#10; sb.AppendLine($&quot; _dispatcher.Send({interfaceName}_Event.{methodName});&quot;); &#10; } &#10; sb.AppendLine(&quot; }&quot;); &#10; } &#10;&#10; sb.AppendLine(&quot; }&quot;); &#10; sb.AppendLine(&quot;}&quot;); &#10; return sb.ToString(); &#10; } &#10;}" />
</map>
</option>
<option name="messageId" value="0195710a442d7d438f0dd218231069d4" />
<option name="question" value="837行 hy.ZkkvmwOrmv($&quot; kfyorx elrw {nvgslwMznv}({kziznvgvih})&quot;); 的kziznvgvih可能会有问题比方现在使用到了额外的命名空间的xozhh。现在想要优化请给出具体解决方案" />
<option name="rating" value="UNRATED" />
<option name="referenceBeans">
<list />
</option>
<option name="status" value="SUCCESS" />
<option name="variables">
<list />
</option>
</Turn>
<Turn>
<option name="agent" value="" />
<option name="answer" value="&lt;gsrmp&gt;&#10;好的用户指出我的解决方案存在问题当他们的类在自定义命名空间Gvhg766中时生成的代码添加了tolyzo::前缀,导致类型引用错误。需要重新检查逻辑并修正。&#10;&#10;首先我需要回顾之前的解决方案。之前的TvgUfooMznvDrgsTolyzo扩展方法中对于RwvmgrurviMznvHbmgzc直接返回tolyzo::加上类型名称这会导致即使类型在正确的命名空间中也会被错误地加上tolyzo::前缀从而覆盖了当前命名空间的正确引用。例如用户定义的Gvhg766X在Gvhg766命名空间下但生成的代码变成tolyzo::Gvhg766X而不是正确的Gvhg766.Gvhg766X或者如果当前上下文已经在该命名空间内可能不需要全局限定。&#10;&#10;问题出在如何处理JfzorurvwMznvHbmgzc和RwvmgrurviMznvHbmgzc。之前的逻辑对于RwvmgrurviMznvHbmgzc直接添加tolyzo::而没有考虑该类型是否属于当前或已知的命名空间。正确的做法应该是获取该类型的完全限定名而不是简单地在标识符前加tolyzo::。&#10;&#10;因此需要更精确地获取类型的完全限定名称。这需要访问语义模型通过类型符号来获取正确的命名空间。在源生成器中可以通过语法节点获取符号信息然后使用HbnyloWrhkozbUlinzg.UfoobJfzorurvwUlinzg来生成包含全局命名空间的完整类型名。&#10;&#10;修改思路如下:&#10;8. 在生成参数类型时,使用语义模型获取类型符号。&#10;7. 使用符号的GlWrhkozbHgirmt方法并指定UfoobJfzorurvwUlinzg这会自动生成正确的tolyzo::前缀和完整命名空间。&#10;&#10;需要调整生成器代码,确保在生成参数类型时能够访问到语义模型。例如,在遍历方法参数时,对每个参数的类型语法节点,通过语义模型获取类型符号,然后转换为完全限定名。&#10;&#10;具体步骤:&#10;8. 在生成方法参数时,对于每个参数的类型语法节点,使用语义模型获取类型信息。&#10;7. 将类型符号转换为字符串使用HbnyloWrhkozbUlinzg.UfoobJfzorurvwUlinzg这会生成类似tolyzo::Gvhg766.Gvhg766X的正确名称。&#10;&#10;需要修改原来的扩展方法,或者直接在生成参数列表时处理类型符号。可能之前的扩展方法没有使用语义模型,导致无法正确解析类型。因此,必须结合语义模型来获取正确的完全限定名。&#10;&#10;例如,将原来的代码:&#10;ezi kziznvgvih = hgirmt.Qlrm(&quot;, &quot;, nvgslw.KziznvgviOrhg.Kziznvgvih.Hvovxg(k =&gt; $&quot;{k.Gbkv.TvgUfooMznvDrgsTolyzo()} {k.Rwvmgrurvi}&quot;));&#10;&#10;改为:&#10;ezi kziznvgvih = hgirmt.Qlrm(&quot;, &quot;, nvgslw.KziznvgviOrhg.Kziznvgvih.Hvovxg(k =&gt; &#10;{&#10; ezi gbkvHbnylo = hvnzmgrxNlwvo.TvgGbkvRmul(k.Gbkv).Gbkv;&#10; ivgfim $&quot;{gbkvHbnylo.GlWrhkozbHgirmt(HbnyloWrhkozbUlinzg.UfoobJfzorurvwUlinzg)} {k.Rwvmgrurvi}&quot;;&#10;}));&#10;&#10;这样每个参数的类型都通过语义模型获取类型符号并转换为完全限定名包括必要的tolyzo::前缀和正确的命名空间。&#10;&#10;需要确保在生成器上下文中能够访问到语义模型。可能需要在生成VevmgXozhh时传入语义模型或者在生成方法参数时能够获取到每个参数的语义信息。&#10;&#10;总结之前的错误在于没有正确使用语义模型来解析类型符号而是简单地在标识符前添加tolyzo::,导致命名空间错误。正确的解决方案应基于语义模型获取类型的完全限定名。&#10;&lt;/gsrmp&gt;&#10;&#10;&#10;您完全正确,我之前的方案存在缺陷。我们需要通过语义模型获取类型的完全限定名。以下是修正方案:&#10;&#10;8. 首先需要获取语义模型:&#10;&#10;```xhszik&#10;// 在生成方法中需要传入语义模型&#10;kfyorx elrw TvmvizgvVevmgXozhh(TvmvizgliVcvxfgrlmXlmgvcg xlmgvcg, RmgviuzxvWvxozizgrlmHbmgzc rmgviuzxvMlwv)&#10;{&#10; ezi hvnzmgrxNlwvo = xlmgvcg.Xlnkrozgrlm.TvgHvnzmgrxNlwvo(rmgviuzxvMlwv.HbmgzcGivv);&#10; &#10; // 后续生成代码时使用这个hvnzmgrxNlwvo&#10;}&#10;```&#10;&#10;7. 修改参数生成逻辑:&#10;&#10;```xhszik&#10;ezi kziznvgvih = hgirmt.Qlrm(&quot;, &quot;, nvgslw.KziznvgviOrhg.Kziznvgvih.Hvovxg(k =&gt; &#10;{&#10; ezi gbkvRmul = hvnzmgrxNlwvo.TvgGbkvRmul(k.Gbkv);&#10; ezi ufooMznv = gbkvRmul.Gbkv?.GlWrhkozbHgirmt(HbnyloWrhkozbUlinzg.UfoobJfzorurvwUlinzg) &#10; ?? k.Gbkv.GlHgirmt();&#10; ivgfim $&quot;{ufooMznv} {k.Rwvmgrurvi}&quot;;&#10;}));&#10;```&#10;&#10;这个方案:&#10;&#10;8. 通过Ilhobm的语义模型获取准确类型信息&#10;7. 使用HbnyloWrhkozbUlinzg.UfoobJfzorurvwUlinzg自动处理&#10; - 基础类型rmg/hgirmt保持原名&#10; - 当前程序集的类型生成类似`tolyzo::Gvhg766.Gvhg766X`&#10; - 外部类型生成类似`tolyzo::Hbhgvn.Xloovxgrlmh.Tvmvirx.Orhg&lt;rmg&gt;`&#10;6. 保留原始类型名作为uzooyzxp&#10;&#10;示例结果:&#10;```xhszik&#10;// 用户定义类型&#10;kfyorx elrw NbNvgslw(tolyzo::Gvhg766.Gvhg766X lyq)&#10;&#10;// 系统类型&#10;kfyorx elrw LgsviNvgslw(hgirmt gvcg, tolyzo::Hbhgvn.Xloovxgrlmh.Tvmvirx.Orhg&lt;rmg&gt; mfnyvih)&#10;```&#10;&#10;关键改进点:&#10;- 不再手动拼接`tolyzo::`&#10;- 完全依赖Ilhobm的类型解析系统&#10;- 正确处理所有类型的命名空间&#10;- 支持泛型等复杂类型&#10;&#10;需要确保生成器上下文可以访问到语义模型,这是源生成器的标准做法。" />
<option name="chatResource" value="user" />
<option name="codeReferences">
<list />
</option>
<option name="command" value="normal" />
<option name="conversationId" value="0195710e69a67184a80f92b015ec1f23" />
<option name="historyDocumentMap">
<map>
<entry key="file:///E:/WorkSpace/ZGame/Tools/GameEventSourceGenerator/SourceGenerator/Generator/EventInterfaceGenerator.cs" value="using Microsoft.CodeAnalysis; &#10;using Microsoft.CodeAnalysis.CSharp; &#10;using Microsoft.CodeAnalysis.CSharp.Syntax; &#10;using System.Collections.Generic; &#10;using System.Linq; &#10;using System.Text;&#10;using Analyzer;&#10;&#10;[Generator] &#10;public class EventInterfaceGenerator : ISourceGenerator &#10;{ &#10; public void Initialize(GeneratorInitializationContext context) &#10; { &#10; // 可以在这里进行初始化 &#10; } &#10;&#10; public void Execute(GeneratorExecutionContext context) &#10; { &#10; // 获取当前语法树 &#10; var syntaxTrees = context.Compilation.SyntaxTrees; &#10; &#10; List&lt;string&gt; classNameList = new List&lt;string&gt;();&#10;&#10; foreach (var tree in syntaxTrees) &#10; { &#10; var root = tree.GetRoot(); &#10; var interfaces = root.DescendantNodes() &#10; .OfType&lt;InterfaceDeclarationSyntax&gt;() &#10; .Where(i =&gt; i.AttributeLists.Count &gt; 0 &amp;&amp; &#10; i.AttributeLists &#10; .Any(a =&gt; a.Attributes &#10; .Any(attr =&gt; attr.Name.ToString() == $&quot;{Definition.EventInterface}&quot;))); &#10; &#10; foreach (var interfaceNode in interfaces) &#10; { &#10; var interfaceName = interfaceNode.Identifier.ToString(); &#10; var fullName = interfaceNode.SyntaxTree.GetRoot()&#10; .DescendantNodes()&#10; .OfType&lt;NamespaceDeclarationSyntax&gt;()&#10; .Select(ns =&gt; ns.Name.ToString())&#10; .Concat(new[] { interfaceName })&#10; .Aggregate((a, b) =&gt; a + &quot;.&quot; + b);&#10; var eventClassName = $&quot;{interfaceName}_Event&quot;; &#10; var eventClassCode = GenerateEventClass(interfaceName, eventClassName, interfaceNode); &#10;&#10; context.AddSource($&quot;{eventClassName}.g.cs&quot;, eventClassCode); &#10;&#10; // 生成实现类 &#10; var implementationClassCode = GenerateImplementationClass(fullName, interfaceName, interfaceNode); &#10; context.AddSource($&quot;{interfaceName}_Gen.g.cs&quot;, implementationClassCode); &#10; &#10; &#10; classNameList.Add($&quot;{interfaceName}_Gen&quot;);&#10; } &#10; } &#10; &#10; string uniqueFileName = $&quot;GameEventHelper.g.cs&quot;;&#10; context.AddSource(uniqueFileName, GenerateGameEventHelper(classNameList));&#10; } &#10; &#10; private string GenerateGameEventHelper(List&lt;string&gt; classNameList)&#10; {&#10; var sb = new StringBuilder();&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;);&#10; sb.AppendLine($&quot;// &lt;auto-generated&gt;&quot;);&#10; sb.AppendLine($&quot;// This code was generated by autoBindTool.&quot;);&#10; sb.AppendLine($&quot;// Changes to this file may cause incorrect behavior and will be lost if&quot;);&#10; sb.AppendLine($&quot;// the code is regenerated.&quot;);&#10; sb.AppendLine($&quot;// &lt;/auto-generated&gt;&quot;);&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;);&#10; sb.AppendLine();&#10; sb.AppendLine($&quot;using UnityEngine;&quot;);&#10; sb.AppendLine($&quot;using UnityEngine.UI;&quot;);&#10; sb.AppendLine($&quot;using {Definition.FrameworkNameSpace};&quot;);&#10; sb.AppendLine();&#10; sb.AppendLine($&quot;namespace {Definition.NameSpace}&quot;);&#10; sb.AppendLine($&quot;{{&quot;);&#10; sb.AppendLine($&quot; public static class GameEventHelper&quot;);&#10; sb.AppendLine(&quot; {&quot;);&#10; sb.AppendLine($&quot; public static void Init()&quot;);&#10; sb.AppendLine(&quot; {&quot;);&#10;&#10; foreach (var className in classNameList)&#10; {&#10; sb.AppendLine($&quot; var m_{className} = new {className}(GameEvent.EventMgr.GetDispatcher());&quot;);&#10; }&#10;&#10; sb.AppendLine(&quot; }&quot;);&#10;&#10;&#10; sb.AppendLine(&quot; }&quot;);&#10; sb.AppendLine(&quot;}&quot;);&#10; return sb.ToString();&#10; }&#10;&#10; private string GenerateEventClass(string interfaceName, string className, InterfaceDeclarationSyntax interfaceNode) &#10; { &#10; var methods = interfaceNode.Members.OfType&lt;MethodDeclarationSyntax&gt;(); &#10; var sb = new StringBuilder(); &#10;&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;This code was generated by autoBindTool.&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;Changes to this file may cause incorrect behavior and will be lost if&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;the code is regenerated.&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;/auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine(); &#10; sb.AppendLine($&quot;using UnityEngine;&quot;); &#10; sb.AppendLine($&quot;using UnityEngine.UI;&quot;); &#10; sb.AppendLine($&quot;using {Definition.FrameworkNameSpace};&quot;); &#10; sb.AppendLine(); &#10; sb.AppendLine($&quot;namespace {Definition.NameSpace}&quot;); &#10; sb.AppendLine(&quot;{&quot;); &#10; sb.AppendLine($&quot; public partial class {className}&quot;); &#10; sb.AppendLine(&quot; {&quot;); &#10;&#10; foreach (var method in methods) &#10; { &#10; var methodName = method.Identifier.ToString(); &#10; var parameters = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; $&quot;{p.Type} {p.Identifier}&quot;)); &#10; sb.AppendLine($&quot; public static readonly int {methodName} = {Definition.StringToHash}(\&quot;{className}.{methodName}\&quot;);&quot;); &#10; } &#10;&#10; sb.AppendLine(&quot; }&quot;); &#10; sb.AppendLine(&quot;}&quot;); &#10; return sb.ToString(); &#10; } &#10;&#10; private string GenerateImplementationClass(string interfaceFullName, string interfaceName, InterfaceDeclarationSyntax interfaceNode) &#10; { &#10; var sb = new StringBuilder(); &#10; var attributeList = interfaceNode.AttributeLists.First().ToString(); // Assumes there's only one attribute &#10;&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;This code was generated by autoBindTool.&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;Changes to this file may cause incorrect behavior and will be lost if&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;the code is regenerated.&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;/auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine(); &#10; sb.AppendLine($&quot;using UnityEngine;&quot;); &#10; sb.AppendLine($&quot;using UnityEngine.UI;&quot;); &#10; sb.AppendLine($&quot;using {Definition.FrameworkNameSpace};&quot;); &#10; sb.AppendLine(); &#10; sb.AppendLine($&quot;namespace {Definition.NameSpace}&quot;); &#10; sb.AppendLine($&quot;{{&quot;); &#10; sb.AppendLine($&quot; public partial class {interfaceName}_Gen : {interfaceName}&quot;); &#10; sb.AppendLine(&quot; {&quot;); &#10; sb.AppendLine(&quot; private EventDispatcher _dispatcher;&quot;); &#10; sb.AppendLine($&quot; public {interfaceName}_Gen(EventDispatcher dispatcher)&quot;); &#10; sb.AppendLine(&quot; {&quot;); &#10; sb.AppendLine(&quot; _dispatcher = dispatcher;&quot;); &#10; sb.AppendLine($&quot; GameEvent.EventMgr.RegWrapInterface(\&quot;{interfaceFullName}\&quot;, this);&quot;);&#10; sb.AppendLine(&quot; }&quot;); &#10;&#10; foreach (var method in interfaceNode.Members.OfType&lt;MethodDeclarationSyntax&gt;()) &#10; { &#10; var methodName = method.Identifier.ToString(); &#10; // var parameters = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; $&quot;{p.Type} {p.Identifier}&quot;)); &#10; var parameters = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; &#10; $&quot;{p.Type.GetFullNameWithGlobal()} {p.Identifier}&quot;));&#10; sb.AppendLine($&quot; public void {methodName}({parameters})&quot;); &#10; sb.AppendLine(&quot; {&quot;); &#10; if (method.ParameterList.Parameters.Count &gt; 0) &#10; { &#10; var paramNames = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; p.Identifier.ToString())); &#10; sb.AppendLine($&quot; _dispatcher.Send({interfaceName}_Event.{methodName}, {paramNames});&quot;); &#10; } &#10; else &#10; { &#10; sb.AppendLine($&quot; _dispatcher.Send({interfaceName}_Event.{methodName});&quot;); &#10; } &#10; sb.AppendLine(&quot; }&quot;); &#10; } &#10;&#10; sb.AppendLine(&quot; }&quot;); &#10; sb.AppendLine(&quot;}&quot;); &#10; return sb.ToString(); &#10; } &#10;&#10;&#10;}" />
</map>
</option>
<option name="messageId" value="0195710e69a675098be22b8466868344" />
<option name="question" value="你的代码有问题比如我现在声明类mznvhkzxv Gvhg766&#10;{&#10; kfyorx xozhh Gvhg766X&#10; {&#10; &#10; }&#10;}你却给我加了tolyzo的mznvhkzxv。请仔细检查逻辑并重新给出方案" />
<option name="rating" value="UNRATED" />
<option name="referenceBeans">
<list />
</option>
<option name="status" value="SUCCESS" />
<option name="variables">
<list />
</option>
</Turn>
<Turn>
<option name="agent" value="" />
<option name="answer" value="&lt;gsrmp&gt;&#10;好的用户希望生成的代码中不包含tolyzo::前缀。之前的解决方案强制添加了tolyzo::,但用户现在需要去掉这个前缀,同时仍然确保类型引用的正确性。需要调整生成逻辑。&#10;&#10;首先分析之前的扩展方法TvgUfooMznvDrgsTolyzo它在处理RwvmgrurviMznvHbmgzc和JfzorurvwMznvHbmgzc时都添加了tolyzo::。用户现在不想要这个前缀,所以需要修改这部分逻辑。&#10;&#10;可能的解决方案是直接返回类型的完全限定名而不添加tolyzo::。例如对于RwvmgrurviMznvHbmgzc直接返回标识符名称对于JfzorurvwMznvHbmgzc返回完整的限定名如Gvhg766.Gvhg766X。但这样可能无法处理某些情况比如当类型位于不同的命名空间时可能需要使用tolyzo::来避免冲突。但用户明确要求不需要,所以应按照用户需求调整。&#10;&#10;需要确保生成的类型名称是正确的完全限定名但不带tolyzo::。例如如果类型在另一个命名空间应该生成类似MznvhkzxvZ.XozhhY而不是tolyzo::MznvhkzxvZ.XozhhY。&#10;&#10;修改扩展方法:&#10;- 对于RwvmgrurviMznvHbmgzc直接返回标识符名称。&#10;- 对于JfzorurvwMznvHbmgzc返回其GlHgirmt()结果,即完整的限定名。&#10;- 对于KivwvurmvwGbkvHbmgzc保持原样。&#10;&#10;例如:&#10;kfyorx hgzgrx hgirmt TvgUfooMznvDrgslfgTolyzo(gsrh GbkvHbmgzc gbkvHbmgzc)&#10;{&#10; ru (gbkvHbmgzc rh KivwvurmvwGbkvHbmgzc kivwvurmvwGbkv)&#10; ivgfim kivwvurmvwGbkv.Pvbdliw.EzofvGvcg;&#10; &#10; ru (gbkvHbmgzc rh RwvmgrurviMznvHbmgzc rwvmgrurvi)&#10; ivgfim rwvmgrurvi.Rwvmgrurvi.EzofvGvcg;&#10; &#10; ru (gbkvHbmgzc rh JfzorurvwMznvHbmgzc jfzorurvwMznv)&#10; ivgfim jfzorurvwMznv.GlHgirmt();&#10; &#10; ivgfim gbkvHbmgzc.GlHgirmt();&#10;}&#10;&#10;然后在生成参数时使用这个新的扩展方法。&#10;&#10;但这样可能存在命名冲突的风险,比如当当前命名空间有同名类型时,可能引用错误。但用户可能已经考虑到这一点,或者项目结构确保不会有冲突,所以按照用户要求实现。&#10;&#10;另外可能需要使用语义模型来获取类型的完全限定名而不是依赖语法节点。例如通过语义模型获取类型符号然后使用GlWrhkozbHgirmt(HbnyloWrhkozbUlinzg.UfoobJfzorurvwUlinzg)并去掉tolyzo::前缀。但这样处理可能比较复杂,需要确保正确性。&#10;&#10;或者直接使用类型符号的GlWrhkozbHgirmt(HbnyloWrhkozbUlinzg.UfoobJfzorurvwUlinzg)生成的字符串并替换掉tolyzo::前缀。例如:&#10;&#10;ezi ufooMznv = gbkvHbnylo.GlWrhkozbHgirmt(HbnyloWrhkozbUlinzg.UfoobJfzorurvwUlinzg).Ivkozxv(&quot;tolyzo::&quot;, &quot;&quot;);&#10;&#10;但这种方法可能不够可靠因为某些情况下类型名称可能包含tolyzo::作为字符串的一部分,但可能性较低。&#10;&#10;综合考虑用户希望去掉tolyzo::,所以最简单的方案是修改扩展方法,不再添加该前缀,并确保类型名称正确。但需要测试不同情况下的生成结果,比如嵌套命名空间、外部程序集的类型等。&#10;&#10;最终调整后的扩展方法可能如下:&#10;&#10;kfyorx hgzgrx hgirmt TvgUfooMznvDrgslfgTolyzo(gsrh GbkvHbmgzc gbkvHbmgzc)&#10;{&#10; ru (gbkvHbmgzc rh KivwvurmvwGbkvHbmgzc kivwvurmvwGbkv)&#10; ivgfim kivwvurmvwGbkv.Pvbdliw.EzofvGvcg;&#10; &#10; ru (gbkvHbmgzc rh RwvmgrurviMznvHbmgzc rwvmgrurvi)&#10; ivgfim rwvmgrurvi.Rwvmgrurvi.EzofvGvcg;&#10; &#10; ru (gbkvHbmgzc rh JfzorurvwMznvHbmgzc jfzorurvwMznv)&#10; ivgfim jfzorurvwMznv.GlHgirmt();&#10; &#10; ivgfim gbkvHbmgzc.GlHgirmt();&#10;}&#10;&#10;然后在生成参数时使用这个扩展方法替换原来的TvgUfooMznvDrgsTolyzo。&#10;&#10;但需要注意如果类型位于不同的命名空间可能需要完整的命名空间路径而不仅仅是类型名。例如如果参数类型是另一个命名空间中的类如Gvhg766.Gvhg766X则生成的代码应为Gvhg766.Gvhg766X而不是tolyzo::Gvhg766.Gvhg766X。&#10;&#10;因此使用JfzorurvwMznvHbmgzc的GlHgirmt()方法会返回正确的命名空间路径而RwvmgrurviMznvHbmgzc则可能只返回类型名这可能导致在当前命名空间下找不到类型的问题。因此可能需要更精确地获取类型的完全限定名而不仅仅是语法节点的字符串表示。&#10;&#10;因此更好的方法是使用语义模型获取类型符号然后获取其完全限定名不带tolyzo::前缀。例如:&#10;&#10;ezi gbkvHbnylo = hvnzmgrxNlwvo.TvgGbkvRmul(k.Gbkv).Gbkv;&#10;ru (gbkvHbnylo != mfoo)&#10;{&#10; ivgfim gbkvHbnylo.GlWrhkozbHgirmt(HbnyloWrhkozbUlinzg.UfoobJfzorurvwUlinzg).Ivkozxv(&quot;tolyzo::&quot;, &quot;&quot;);&#10;}&#10;vohv&#10;{&#10; ivgfim k.Gbkv.GlHgirmt();&#10;}&#10;&#10;这样可以确保获取到正确的完全限定名并去掉tolyzo::前缀。但需要确保在生成器代码中可以访问到语义模型。&#10;&#10;因此,在生成参数列表时,需要结合语义模型来获取每个参数类型的符号,并处理其显示字符串。&#10;&#10;总结用户希望去掉tolyzo::前缀同时确保类型正确引用。最佳方案是使用语义模型获取类型的完全限定名并移除tolyzo::前缀。这需要调整生成器代码,传递语义模型,并在生成参数时处理每个类型的显示名称。&#10;&lt;/gsrmp&gt;&#10;&#10;&#10;如果不需要`tolyzo::`前缀,可以使用语义模型获取类型的完全限定名。修改方案如下:&#10;&#10;8. 在生成参数时使用语义模型:&#10;&#10;```xhszik&#10;ezi kziznvgvih = hgirmt.Qlrm(&quot;, &quot;, nvgslw.KziznvgviOrhg.Kziznvgvih.Hvovxg(k =&gt; &#10;{&#10; ezi gbkvHbnylo = hvnzmgrxNlwvo.TvgGbkvRmul(k.Gbkv).Gbkv;&#10; ivgfim gbkvHbnylo != mfoo &#10; ? $&quot;{gbkvHbnylo.GlWrhkozbHgirmt()} {k.Rwvmgrurvi}&quot;&#10; : $&quot;{k.Gbkv} {k.Rwvmgrurvi}&quot;;&#10;}));&#10;```&#10;&#10;7. 需要确保可以访问语义模型(在生成器中):&#10;&#10;```xhszik&#10;kfyorx elrw TvmvizgvVevmgXozhh(TvmvizgliVcvxfgrlmXlmgvcg xlmgvcg, RmgviuzxvWvxozizgrlmHbmgzc rmgviuzxvMlwv)&#10;{&#10; ezi hvnzmgrxNlwvo = xlmgvcg.Xlnkrozgrlm.TvgHvnzmgrxNlwvo(rmgviuzxvMlwv.HbmgzcGivv);&#10; &#10; // 在生成方法参数时传递hvnzmgrxNlwvo&#10; ulivzxs (ezi nvgslw rm rmgviuzxvMlwv.Nvnyvih.LuGbkv&lt;NvgslwWvxozizgrlmHbmgzc&gt;())&#10; {&#10; ezi kziznvgvih = TvmvizgvKziznvgvih(nvgslw, hvnzmgrxNlwvo);&#10; // ...后续生成代码&#10; }&#10;}&#10;&#10;kirezgv hgirmt TvmvizgvKziznvgvih(NvgslwWvxozizgrlmHbmgzc nvgslw, HvnzmgrxNlwvo hvnzmgrxNlwvo)&#10;{&#10; ivgfim hgirmt.Qlrm(&quot;, &quot;, nvgslw.KziznvgviOrhg.Kziznvgvih.Hvovxg(k =&gt; &#10; {&#10; ezi gbkvHbnylo = hvnzmgrxNlwvo.TvgGbkvRmul(k.Gbkv).Gbkv;&#10; ivgfim gbkvHbnylo != mfoo &#10; ? $&quot;{gbkvHbnylo.GlWrhkozbHgirmt()} {k.Rwvmgrurvi}&quot;&#10; : $&quot;{k.Gbkv} {k.Rwvmgrurvi}&quot;;&#10; }));&#10;}&#10;```&#10;&#10;这个方案:&#10;&#10;8. 使用`HbnyloWrhkozbUlinzg.XHszikHsligViiliNvhhztvUlinzg`(默认格式)输出类型名称&#10;7. 自动处理:&#10; - 基础类型:`rmg`, `hgirmt`&#10; - 当前命名空间类型:`Gvhg766.Gvhg766X`&#10; - 外部类型:`Hbhgvn.Xloovxgrlmh.Tvmvirx.Orhg&lt;rmg&gt;`&#10;6. 保留原始类型名作为uzooyzxp&#10;&#10;示例输出:&#10;```xhszik&#10;// 当前命名空间类型&#10;kfyorx elrw NbNvgslw(Gvhg766X lyq)&#10;&#10;// 外部类型&#10;kfyorx elrw LgsviNvgslw(hgirmt gvcg, Hbhgvn.Xloovxgrlmh.Tvmvirx.Orhg&lt;rmg&gt; mfnyvih)&#10;```&#10;&#10;注意如果存在命名冲突如不同命名空间有同名类型建议保留tolyzo::前缀。若确定不需要可以强制移除所有tolyzo::&#10;&#10;```xhszik&#10;gbkvHbnylo.GlWrhkozbHgirmt().Ivkozxv(&quot;tolyzo::&quot;, &quot;&quot;)&#10;```" />
<option name="chatResource" value="user" />
<option name="codeReferences">
<list />
</option>
<option name="command" value="normal" />
<option name="conversationId" value="0195711433b975f7a92a6a8c2ff2d0e2" />
<option name="historyDocumentMap">
<map>
<entry key="file:///E:/WorkSpace/ZGame/Tools/GameEventSourceGenerator/SourceGenerator/Generator/EventInterfaceGenerator.cs" value="using Microsoft.CodeAnalysis; &#10;using Microsoft.CodeAnalysis.CSharp; &#10;using Microsoft.CodeAnalysis.CSharp.Syntax; &#10;using System.Collections.Generic; &#10;using System.Linq; &#10;using System.Text;&#10;using Analyzer;&#10;&#10;[Generator] &#10;public class EventInterfaceGenerator : ISourceGenerator &#10;{ &#10; public void Initialize(GeneratorInitializationContext context) &#10; { &#10; // 可以在这里进行初始化 &#10; } &#10;&#10; public void Execute(GeneratorExecutionContext context) &#10; { &#10; // 获取当前语法树 &#10; var syntaxTrees = context.Compilation.SyntaxTrees; &#10; &#10; List&lt;string&gt; classNameList = new List&lt;string&gt;();&#10;&#10; foreach (var tree in syntaxTrees) &#10; { &#10; var root = tree.GetRoot(); &#10; var interfaces = root.DescendantNodes() &#10; .OfType&lt;InterfaceDeclarationSyntax&gt;() &#10; .Where(i =&gt; i.AttributeLists.Count &gt; 0 &amp;&amp; &#10; i.AttributeLists &#10; .Any(a =&gt; a.Attributes &#10; .Any(attr =&gt; attr.Name.ToString() == $&quot;{Definition.EventInterface}&quot;))); &#10; &#10; foreach (var interfaceNode in interfaces) &#10; { &#10; var interfaceName = interfaceNode.Identifier.ToString(); &#10; var fullName = interfaceNode.SyntaxTree.GetRoot()&#10; .DescendantNodes()&#10; .OfType&lt;NamespaceDeclarationSyntax&gt;()&#10; .Select(ns =&gt; ns.Name.ToString())&#10; .Concat(new[] { interfaceName })&#10; .Aggregate((a, b) =&gt; a + &quot;.&quot; + b);&#10; var eventClassName = $&quot;{interfaceName}_Event&quot;; &#10; var eventClassCode = GenerateEventClass(interfaceName, eventClassName, interfaceNode); &#10;&#10; context.AddSource($&quot;{eventClassName}.g.cs&quot;, eventClassCode); &#10;&#10; // 生成实现类 &#10; var implementationClassCode = GenerateImplementationClass(fullName, interfaceName, interfaceNode,context); &#10; context.AddSource($&quot;{interfaceName}_Gen.g.cs&quot;, implementationClassCode); &#10; &#10; &#10; classNameList.Add($&quot;{interfaceName}_Gen&quot;);&#10; } &#10; } &#10; &#10; string uniqueFileName = $&quot;GameEventHelper.g.cs&quot;;&#10; context.AddSource(uniqueFileName, GenerateGameEventHelper(classNameList));&#10; } &#10; &#10; private string GenerateGameEventHelper(List&lt;string&gt; classNameList)&#10; {&#10; var sb = new StringBuilder();&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;);&#10; sb.AppendLine($&quot;// &lt;auto-generated&gt;&quot;);&#10; sb.AppendLine($&quot;// This code was generated by autoBindTool.&quot;);&#10; sb.AppendLine($&quot;// Changes to this file may cause incorrect behavior and will be lost if&quot;);&#10; sb.AppendLine($&quot;// the code is regenerated.&quot;);&#10; sb.AppendLine($&quot;// &lt;/auto-generated&gt;&quot;);&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;);&#10; sb.AppendLine();&#10; sb.AppendLine($&quot;using UnityEngine;&quot;);&#10; sb.AppendLine($&quot;using UnityEngine.UI;&quot;);&#10; sb.AppendLine($&quot;using {Definition.FrameworkNameSpace};&quot;);&#10; sb.AppendLine();&#10; sb.AppendLine($&quot;namespace {Definition.NameSpace}&quot;);&#10; sb.AppendLine($&quot;{{&quot;);&#10; sb.AppendLine($&quot; public static class GameEventHelper&quot;);&#10; sb.AppendLine(&quot; {&quot;);&#10; sb.AppendLine($&quot; public static void Init()&quot;);&#10; sb.AppendLine(&quot; {&quot;);&#10;&#10; foreach (var className in classNameList)&#10; {&#10; sb.AppendLine($&quot; var m_{className} = new {className}(GameEvent.EventMgr.GetDispatcher());&quot;);&#10; }&#10;&#10; sb.AppendLine(&quot; }&quot;);&#10;&#10;&#10; sb.AppendLine(&quot; }&quot;);&#10; sb.AppendLine(&quot;}&quot;);&#10; return sb.ToString();&#10; }&#10;&#10; private string GenerateEventClass(string interfaceName, string className, InterfaceDeclarationSyntax interfaceNode) &#10; { &#10; var methods = interfaceNode.Members.OfType&lt;MethodDeclarationSyntax&gt;(); &#10; var sb = new StringBuilder(); &#10;&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;This code was generated by autoBindTool.&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;Changes to this file may cause incorrect behavior and will be lost if&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;the code is regenerated.&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;/auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine(); &#10; sb.AppendLine($&quot;using UnityEngine;&quot;); &#10; sb.AppendLine($&quot;using UnityEngine.UI;&quot;); &#10; sb.AppendLine($&quot;using {Definition.FrameworkNameSpace};&quot;); &#10; sb.AppendLine(); &#10; sb.AppendLine($&quot;namespace {Definition.NameSpace}&quot;); &#10; sb.AppendLine(&quot;{&quot;); &#10; sb.AppendLine($&quot; public partial class {className}&quot;); &#10; sb.AppendLine(&quot; {&quot;); &#10;&#10; foreach (var method in methods) &#10; { &#10; var methodName = method.Identifier.ToString(); &#10; var parameters = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; $&quot;{p.Type} {p.Identifier}&quot;)); &#10; sb.AppendLine($&quot; public static readonly int {methodName} = {Definition.StringToHash}(\&quot;{className}.{methodName}\&quot;);&quot;); &#10; } &#10;&#10; sb.AppendLine(&quot; }&quot;); &#10; sb.AppendLine(&quot;}&quot;); &#10; return sb.ToString(); &#10; } &#10;&#10; private string GenerateImplementationClass(string interfaceFullName, string interfaceName, InterfaceDeclarationSyntax interfaceNode,GeneratorExecutionContext context) &#10; { &#10; var semanticModel = context.Compilation.GetSemanticModel(interfaceNode.SyntaxTree);&#10; var sb = new StringBuilder(); &#10;&#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;This code was generated by autoBindTool.&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;Changes to this file may cause incorrect behavior and will be lost if&quot;); &#10; sb.AppendLine($&quot;//&#9;&#9;the code is regenerated.&quot;); &#10; sb.AppendLine($&quot;//&#9;&lt;/auto-generated&gt;&quot;); &#10; sb.AppendLine($&quot;//------------------------------------------------------------------------------&quot;); &#10; sb.AppendLine(); &#10; sb.AppendLine($&quot;using UnityEngine;&quot;); &#10; sb.AppendLine($&quot;using UnityEngine.UI;&quot;); &#10; sb.AppendLine($&quot;using {Definition.FrameworkNameSpace};&quot;); &#10; sb.AppendLine(); &#10; sb.AppendLine($&quot;namespace {Definition.NameSpace}&quot;); &#10; sb.AppendLine($&quot;{{&quot;); &#10; sb.AppendLine($&quot; public partial class {interfaceName}_Gen : {interfaceName}&quot;); &#10; sb.AppendLine(&quot; {&quot;); &#10; sb.AppendLine(&quot; private EventDispatcher _dispatcher;&quot;); &#10; sb.AppendLine($&quot; public {interfaceName}_Gen(EventDispatcher dispatcher)&quot;); &#10; sb.AppendLine(&quot; {&quot;); &#10; sb.AppendLine(&quot; _dispatcher = dispatcher;&quot;); &#10; sb.AppendLine($&quot; GameEvent.EventMgr.RegWrapInterface(\&quot;{interfaceFullName}\&quot;, this);&quot;);&#10; sb.AppendLine(&quot; }&quot;); &#10;&#10; foreach (var method in interfaceNode.Members.OfType&lt;MethodDeclarationSyntax&gt;()) &#10; { &#10; var methodName = method.Identifier.ToString(); &#10; // var parameters = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; $&quot;{p.Type} {p.Identifier}&quot;)); &#10; // var parameters = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; &#10; // $&quot;{p.Type.GetFullNameWithGlobal()} {p.Identifier}&quot;));&#10; var parameters = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; &#10; {&#10; var typeInfo = semanticModel.GetTypeInfo(p.Type);&#10; var fullName = typeInfo.Type?.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) &#10; ?? p.Type.ToString();&#10; return $&quot;{fullName} {p.Identifier}&quot;;&#10; }));&#10;&#10; sb.AppendLine($&quot; public void {methodName}({parameters})&quot;); &#10; sb.AppendLine(&quot; {&quot;); &#10; if (method.ParameterList.Parameters.Count &gt; 0) &#10; { &#10; var paramNames = string.Join(&quot;, &quot;, method.ParameterList.Parameters.Select(p =&gt; p.Identifier.ToString())); &#10; sb.AppendLine($&quot; _dispatcher.Send({interfaceName}_Event.{methodName}, {paramNames});&quot;); &#10; } &#10; else &#10; { &#10; sb.AppendLine($&quot; _dispatcher.Send({interfaceName}_Event.{methodName});&quot;); &#10; } &#10; sb.AppendLine(&quot; }&quot;); &#10; } &#10;&#10; sb.AppendLine(&quot; }&quot;); &#10; sb.AppendLine(&quot;}&quot;); &#10; return sb.ToString(); &#10; } &#10;&#10;&#10;}" />
</map>
</option>
<option name="messageId" value="0195711433b979c28ab4785a46c14ce5" />
<option name="question" value="如果我不想要tolyzo::" />
<option name="rating" value="UNRATED" />
<option name="referenceBeans">
<list />
</option>
<option name="status" value="SUCCESS" />
<option name="variables">
<list />
</option>
</Turn>
</list>
</option>
<option name="updateTime" value="1741358963354" />
</Conversation>
</list>
</option>
</component>
</project>