using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; namespace JiShe.CollectBus.IncrementalGenerator { /// /// 复杂类型源生成器 /// [Generator(LanguageNames.CSharp)] public class ComplexTypeSourceAnalyzers : IIncrementalGenerator { private const string AttributeFullName = "JiShe.CollectBus.Analyzers.Shared.SourceAnalyzersAttribute"; private const string SourceEntityAccessorFactoryNamespace = "JiShe.CollectBus.Analyzers.Shared"; public void Initialize(IncrementalGeneratorInitializationContext context) { //Debugger.Launch(); // 步骤1:筛选带有 [SourceAnalyzers] 的类 var classDeclarations = context.SyntaxProvider .CreateSyntaxProvider( predicate: static (s, _) => IsClassWithAttribute(s), transform: static (ctx, _) => GetClassDeclaration(ctx)) .Where(static c => c is not null); // 步骤2:合并编译信息 var compilationAndClasses = context.CompilationProvider.Combine(classDeclarations.Collect()); context.RegisterSourceOutput(compilationAndClasses, (spc, source) => GenerateCode(source.Left, source.Right!, spc)); } private static bool IsClassWithAttribute(SyntaxNode node) => node is ClassDeclarationSyntax cds && cds.AttributeLists.Count > 0; private static ClassDeclarationSyntax GetClassDeclaration(GeneratorSyntaxContext context) { var classDecl = (ClassDeclarationSyntax)context.Node; var attributeType = context.SemanticModel.Compilation.GetTypeByMetadataName(AttributeFullName); foreach (var attribute in classDecl.AttributeLists.SelectMany(al => al.Attributes)) { var symbol = context.SemanticModel.GetSymbolInfo(attribute).Symbol; if (symbol is IMethodSymbol ctor && SymbolEqualityComparer.Default.Equals(ctor.ContainingType, attributeType)) { return classDecl; } } return null; } /// /// 递归获取所有层级的属性 /// /// /// private static IEnumerable GetAllPropertiesInHierarchy(INamedTypeSymbol classSymbol) { var currentSymbol = classSymbol; while (currentSymbol != null) { foreach (var prop in currentSymbol.GetMembers().OfType()) { yield return prop; } currentSymbol = currentSymbol.BaseType; // 向上遍历基类 } } /// /// 生成代码 /// /// /// /// private static void GenerateCode( Compilation compilation, IEnumerable classes, SourceProductionContext context) { var processedTypes = new HashSet(SymbolEqualityComparer.Default); if (!classes.Any()) { context.ReportDiagnostic(Diagnostic.Create( new DiagnosticDescriptor("GEN002", "没有目标类", "没有找到SourceAnalyzers标记的类", "Debug", DiagnosticSeverity.Warning, true), Location.None)); } foreach (var classDecl in classes.Distinct()) { var model = compilation.GetSemanticModel(classDecl.SyntaxTree); var classSymbol = model.GetDeclaredSymbol(classDecl) as INamedTypeSymbol; if (classSymbol == null || !processedTypes.Add(classSymbol)) { context.ReportDiagnostic(Diagnostic.Create( new DiagnosticDescriptor("GEN003", "无效符号", $"类名称为{classDecl.Identifier.Text} 符号为空", "Error", DiagnosticSeverity.Error, true), Location.None)); continue; } //context.ReportDiagnostic(Diagnostic.Create( //new DiagnosticDescriptor( // "PA001", // "Generated Accessors", // $"Generating accessors for {classSymbol.Name}", // "Performance", // DiagnosticSeverity.Info, // true), //Location.None)); //// 新增:输出继承链信息 //context.ReportDiagnostic(Diagnostic.Create( // new DiagnosticDescriptor("HIERARCHY", "Class Hierarchy", // $"Processing class: {classSymbol.Name}, BaseType: {classSymbol.BaseType?.Name}", // "Debug", DiagnosticSeverity.Info, true), // Location.None)); //context.ReportDiagnostic(Diagnostic.Create( //new DiagnosticDescriptor("PA002", "Class Found", //$"Processing class: {classSymbol.Name}", "Debug", DiagnosticSeverity.Warning, true), //Location.None)); var code = BuildAccessorsForType(classSymbol, compilation, processedTypes); //System.Diagnostics.Debug.WriteLine($"Generated code for {classSymbol.Name}:\n{code}"); // 调试输出 context.AddSource($"{classSymbol.Name}Extension.g.cs", code); var code3 = BuildAccessorsForType2(classSymbol, compilation, processedTypes); context.AddSource($"{classSymbol.Name}Accessor.g.cs", code3); //code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};"); //if (classSymbol.ContainingNamespace.ToDisplayString() == "JiShe.CollectBus.IoTDB") //{ //} } // 生成工厂注册代码 context.AddSource("SourceEntityAccessorFactory.g.cs", BuildFactoryCode()); } /// /// 构建类的属性访问器代码 /// /// /// /// /// private static string BuildAccessorsForType( INamedTypeSymbol classSymbol, Compilation compilation, HashSet processedTypes) { var code = new StringBuilder(); code.AppendLine("#pragma warning disable CS0419 // 禁用警告"); code.AppendLine("// Generated code for " + classSymbol.Name); code.AppendLine("// "); code.AppendLine("#nullable enable"); code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};"); code.AppendLine(); code.AppendLine($"public static class {classSymbol.Name}Extension{GetGenericParams(classSymbol)}"); code.AppendLine("{"); foreach (var prop in GetAllPropertiesInHierarchy(classSymbol)) { if (prop.IsIndexer) continue; GeneratePropertyAccessorsForType(prop, code, compilation, processedTypes); } code.AppendLine("}"); return code.ToString(); } /// /// 构建类的属性访问器代码 /// /// /// /// /// private static string BuildAccessorsForType2( INamedTypeSymbol classSymbol, Compilation compilation, HashSet processedTypes) { var code = new StringBuilder(); code.AppendLine("#pragma warning disable CS0419 // 禁用警告"); code.AppendLine("// Generated code for " + classSymbol.Name); code.AppendLine("// "); code.AppendLine("#nullable enable"); code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};"); code.AppendLine(); code.AppendLine($"public sealed class {classSymbol.Name}Accessor : ISourceEntityAccessor<{classSymbol.Name}>"); code.AppendLine("{"); foreach (var prop in GetAllPropertiesInHierarchy(classSymbol)) { if (prop.IsIndexer) continue; GeneratePropertyAccessorsForType(prop, code, compilation, processedTypes); } code.AppendLine("}"); //var code3 = $@" // public sealed class {classSymbol.Name}Accessor : ISourceEntityAccessor<{classSymbol.Name}> // {{ // public object GetPropertyValue({classSymbol.Name} entity, string propName) => propName switch // {{ // {GeneratePropertyCases(classSymbol)} // _ => throw new ArgumentException(""无效属性名"") // }}; // {GenerateTupleSupport(classSymbol)} // }}"; return code.ToString(); } /// /// 获取泛型参数 /// /// /// public static string GetGenericParams(INamedTypeSymbol symbol) { if (!symbol.IsGenericType) return ""; var parameters = symbol.TypeParameters.Select(t => t.Name); return $"<{string.Join(", ", parameters)}>"; } /// /// 生成属性访问器代码 /// /// /// /// /// private static void GeneratePropertyAccessorsForType( IPropertySymbol prop, StringBuilder code, Compilation compilation, HashSet processedTypes) { // 安全类型转换 if (prop.Type is not ITypeSymbol propType) return; code.AppendLine($" // Processing property: {prop.Name}"); // 处理元组类型 if (propType is INamedTypeSymbol { IsTupleType: true } tupleType) { GenerateTupleAccessors(prop, tupleType, code); } else if (propType is INamedTypeSymbol namedType) { GenerateStandardAccessors(prop, namedType, code); ProcessNestedType(namedType, compilation, processedTypes); } } /// /// 处理元组类型 /// /// /// /// private static void GenerateTupleAccessors(IPropertySymbol prop, INamedTypeSymbol tupleType, StringBuilder code) { var elements = tupleType.TupleElements; var parentType = prop.ContainingType.ToDisplayString(); for (int i = 0; i < elements.Length; i++) { var element = elements[i]; if (element.Type is not ITypeSymbol elementType) continue; var elementName = element.CorrespondingTupleField?.Name ?? $"Item{i + 1}"; code.AppendLine($" public static {elementType.ToDisplayString()} Get{prop.Name}_{elementName}({parentType} obj) => obj.{prop.Name}.{elementName};"); if (prop.SetMethod != null) { var assignments = elements.Select((e, idx) => idx == i ? "value" : $"obj.{prop.Name}.{e.Name}"); code.AppendLine($" public static void Set{prop.Name}_{elementName}({parentType} obj, {elementType.ToDisplayString()} value) => obj.{prop.Name} = ({string.Join(", ", assignments)});"); } } } /// /// 生成标准属性的访问器 /// /// /// /// private static void GenerateStandardAccessors(IPropertySymbol prop, INamedTypeSymbol propType, StringBuilder code) { var parentType = prop.ContainingType.ToDisplayString(); code.AppendLine($" public static {propType.ToDisplayString()} Get{prop.Name}({parentType} obj) => obj.{prop.Name};"); if (prop.SetMethod != null) { code.AppendLine($" public static void Set{prop.Name}({parentType} obj, {propType.ToDisplayString()} value) => obj.{prop.Name} = value;"); } } /// /// 处理嵌套类型 /// /// /// /// private static void ProcessNestedType(ITypeSymbol typeSymbol, Compilation compilation, HashSet processedTypes) { if (typeSymbol is not INamedTypeSymbol namedType) return; if (!ShouldProcessNestedType(namedType)) return; if (!processedTypes.Add(namedType)) return; var code = BuildAccessorsForType(namedType, compilation, processedTypes); } /// /// 处理嵌套类型 /// /// /// private static bool ShouldProcessNestedType(INamedTypeSymbol symbol) { return symbol.DeclaredAccessibility == Accessibility.Public && !symbol.IsTupleType && !symbol.IsAnonymousType && !symbol.IsImplicitlyDeclared && !symbol.Name.StartsWith("<"); } /// /// 生成扩展类工厂代码 /// /// private static string BuildFactoryCode() { return """ using System; using System.Collections.Concurrent; namespace JiShe.CollectBus.Analyzers.Shared; public static class SourceEntityAccessorFactory { private static readonly ConcurrentDictionary _accessors = new(); public static ISourceEntityAccessor GetAccessor() { if (!_accessors.TryGetValue(typeof(T), out var accessor)) { accessor = Activator.CreateInstance( Type.GetType($"{typeof(T).Namespace}.{typeof(T).Name}Accessor")!)!; _accessors.TryAdd(typeof(T), accessor); } return (ISourceEntityAccessor)accessor!; } } """; } } }