georgepwall1991/automapper-analyser

GitHub: georgepwall1991/automapper-analyser

基于 Roslyn 的 AutoMapper 编译期静态分析器,能在编码和构建阶段自动检测并修复映射配置错误,避免运行时异常和数据丢失。

Stars: 4 | Forks: 0

# 🎯 AutoMapper Roslyn Analyzer [![NuGet 版本](https://img.shields.io/nuget/v/AutoMapperAnalyzer.Analyzers.svg?style=flat-square&logo=nuget&label=NuGet)](https://www.nuget.org/packages/AutoMapperAnalyzer.Analyzers/) [![NuGet 下载量](https://img.shields.io/nuget/dt/AutoMapperAnalyzer.Analyzers.svg?style=flat-square&logo=nuget&label=Downloads)](https://www.nuget.org/packages/AutoMapperAnalyzer.Analyzers/) [![构建状态](https://img.shields.io/github/actions/workflow/status/georgepwall1991/automapper-analyser/ci.yml?style=flat-square&logo=github&label=Build)](https://github.com/georgepwall1991/automapper-analyser/actions) [![测试](https://img.shields.io/badge/Tests-752%20passing%2C%200%20skipped-success?style=flat-square&logo=checkmarx)](https://github.com/georgepwall1991/automapper-analyser/actions) [![.NET](https://img.shields.io/badge/.NET-4.8+%20%7C%206.0+%20%7C%208.0+%20%7C%209.0+%20%7C%2010.0+-512BD4?style=flat-square&logo=dotnet)](https://dotnet.microsoft.com/) [![许可证](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](LICENSE) [![覆盖率](https://img.shields.io/codecov/c/github/georgepwall1991/automapper-analyser?style=flat-square&logo=codecov&label=Coverage)](https://codecov.io/gh/georgepwall1991/automapper-analyser) ## 🎉 最新版本:v2.30.23 **AM050 代码修复保留同级配置 —— 不再静默丢失 `Condition`/`NullSubstitute`** ✅ **亮点** - 当 `ForMember` 的 options lambda 除了冗余的 `MapFrom` 外还包含同级配置(例如 `Condition`、`NullSubstitute`、`PreCondition`、`UseDestinationValue` 或 `Ignore`)时,现在将不再触发自动移除 `ForMember` 的操作。移除整个 `ForMember` 会静默丢弃该策略。 - 简单的形态(`o => o.MapFrom(s => s.Member)` 或以冗余 `MapFrom` 作为唯一语句的代码块)仍然会应用自动移除 ForMember 的修复。 - 在不安全的情况下,AM050 诊断仍会触发;只是自动操作被抑制,以便用户在保留同级策略的同时手动移除冗余的 `MapFrom`。 🧪 **验证** - 在 `net10.0` 上通过了完整的解决方案测试验证。 - 完整的测试套件已通过,`778` 个通过,`0` 个跳过。 - 发布验证覆盖了针对性的 AM050 和 RuleCatalog 测试,以及 AnalyzerVerifier 目录/快照检查。 ### 近期版本 - **v2.30.23**:当冗余 `MapFrom` 的 `ForMember` lambda 包含否则会被丢弃的同级配置(`Condition`、`NullSubstitute` 等)时,将不触发 AM050 代码修复。 - **v2.30.22**:AM031 规范化链式预终结 LINQ 接收器,以便报告同一根源集合的多次枚举。 - **v2.30.21**:AM050 冗余 `MapFrom` 检测现在也会对带括号和类型化的 lambda 触发,例如 `o.MapFrom((Source s) => s.Name)`。 - **v2.30.20**:AM030 将 `ArgumentNullException.ThrowIfNull`、`ArgumentException.ThrowIfNullOrEmpty` 和 `ArgumentException.ThrowIfNullOrWhiteSpace` 识别为转换器 source 参数的 null 守卫。 - **v2.30.19**:当匹配的 `ITypeConverter` 通过 DI/服务定位器形态传递给 `ConvertUsing` 时,AM030 停止将具体转换器报告为未使用。 - **v2.30.18**:AM031 多重枚举跟踪涵盖 `Min`、`Max`、`Aggregate`、`LongCount`、`Single`、`SingleOrDefault`、`ToHashSet`、`ToDictionary` 和 `ToLookup`,并带有 `System.Linq.Enumerable`/`Queryable` 同名门控。 - **v2.30.17**:当重复的 `CreateMap<>()` 带有链式映射策略时,AM041 保留重复项移除的修复。 - **v2.30.16**:AM002、AM006、AM021、AM031 和 AM041 的分析器精度强化。 - **v2.30.15**:通过特定于描述符的无修复元数据和可执行接口集合重写,强化修复程序 UX 信任度。 - **v2.30.14**:AM021 反向映射集合元素诊断能在没有重复干扰的情况下捕获缺失的反向元素映射。 - **v2.30.13**:AM041 重复映射标签现在保留泛型类型参数和数组秩。 - **v2.30.12**:AM030 接口类型转换器使用和 AM021 字典修复程序安全性。 - **v2.30.11**:针对直接属性不匹配补救的 AM001 枚举/字符串转换修复。 - **v2.30.10**:针对基于字符串的成员和类型安全抑制的 AM050 已验证冗余 `MapFrom` 清理。 - **v2.30.9**:AM004/AM005 严重性文档信任与描述符对齐的规则文档。 - **v2.30.8**:AM030 null 守卫修复程序精度,无需侵入性的 `using System` 编辑。 - **v2.30.7**:针对嵌套映射链和显式递归控制的 AM022 递归边界精度。 - **v2.30.6**:AM031 带有嵌套源路径和 Task 属性 `.Result` 覆盖的源集合缓存精度。 - **v2.30.5**:AM030 针对 `ConvertUsing(typeof(...))` 的基于类型的转换器使用精度。 - **v2.30.4**:AM022 映射递归精度,减少了不相关循环的误报。 - **v2.30.3**:带有显式配置覆盖的 AM011 ForPath 必需成员边界。 - **v2.30.2**:带有针对性回归覆盖的 AM003 可分配集合边界抑制。 - **v2.30.1**:AM002 可空性契约对齐,带有描述符精确的文档和可空上下文回归覆盖。 - **v2.30.0**:针对 AM001、AM005、AM006、AM011 和 AM021 的修复强化,提供更安全的操作选择。 - **v2.29.0**:跨主要数据完整性修复程序的智能主要修复和减少的修复程序噪音。 - **v2.28.2**:减少误报、改进修复程序 UX 以及强化发布工作流。 - **v2.28.1**:区分大小写的 AM021 抑制和修复程序可靠性改进。 - **v2.28.0**:分析器逻辑修复和性能改进。 - **v2.27.0**:AM050 可空安全性修复和广泛的回归覆盖范围扩展。 - **v2.25.0**:代码修复整合和示例验证。 ## 🌟 为什么这很重要 AutoMapper 功能强大,但静默失败是其致命弱点。未映射的属性、在运行时引发的类型不匹配、导致 NullReferenceExceptions 的可空性违规——这些问题通常出现在生产环境中, 而不是在开发期间。 **此分析器彻底改变了这一局面。** ``` // Before: 😰 Runtime surprise! public void MapUserData() { var user = mapper.Map(userEntity); // 💥 NullReferenceException in production // 💥 Data loss from unmapped properties // 💥 Type conversion failures } // After: 🛡️ Compile-time confidence! public void MapUserData() { var user = mapper.Map(userEntity); // ✅ All mapping issues caught at compile-time // ✅ Code fixes suggest proper solutions // ✅ Ship with confidence } ``` ## ⚡ 快速入门 ``` # 通过 .NET CLI 安装 dotnet add package AutoMapperAnalyzer.Analyzers # 或者通过 Package Manager Console Install-Package AutoMapperAnalyzer.Analyzers ``` 就是这样!分析器会自动激活并开始检查您的 AutoMapper 配置。打开任何包含 AutoMapper 映射的文件,即可即时看到诊断信息。 **查看其运行效果:** ``` var config = new MapperConfiguration(cfg => { cfg.CreateMap(); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AM001: Property 'Age' type mismatch // 💡 Press Ctrl+. for code fix suggestions }); ``` ## 🚀 您将获得什么 ### 🛡️ **完整的类型安全** - **AM001**:带有智能转换建议的属性类型不匹配 - **AM002**:带有 null 安全模式的可空到非空映射 - **AM003**:集合类型不兼容检测 ### 🔍 **零数据丢失** - **AM004**:缺失的目标属性(防止静默数据丢失) - **AM006**:未映射的目标属性(检测无意的默认值) - **AM011**:必需属性验证(避免运行时异常) - **AM005**:区分大小写问题(跨平台可靠性) ### 🧩 **复杂映射智能** - **AM020**:带有 CreateMap 建议的嵌套对象映射验证(支持内部属性和跨 Profile 检测) - **AM021**:带有转换策略的集合元素类型分析 - **AM022**:带有 MaxDepth 建议的循环引用检测 - **AM030**:带有 null 安全验证的自定义类型转换器分析 ### ⚡ **即时代码修复** 每个分析器都附带**智能代码修复**,不仅能识别问题,还能解决问题: ``` // Problem detected ⚠️ cfg.CreateMap(); // ~~~~~~~~~~~~~~~~~~~~~~~~~ AM001: Property 'Age' type mismatch // Code fix applied ✨ cfg.CreateMap() .ForMember(dest => dest.Age, opt => opt.MapFrom(src => int.TryParse(src.Age, out var age) ? age : 0)); ``` ## 🎯 实际影响 | | 之前 | 之后 | |----|----------------------------------------|----------------------------------| | 🐛 | 运行时映射失败 | ✅ 编译时验证 | | 🔍 | 手动调试会话 | ✅ 即时错误高亮显示 | | 📝 | 猜测正确的配置 | ✅ 带有最佳实践的代码修复 | | ⚠️ | 生产环境 NullReferenceExceptions | ✅ Null 安全强制执行 | | 📊 | 静默数据丢失 | ✅ 缺失属性检测 | | 🌐 | 跨平台映射不一致 | ✅ 区分大小写验证 | ## 📦 安装 ### .NET CLI (推荐) ``` dotnet add package AutoMapperAnalyzer.Analyzers ``` ### 程序包管理器控制台 ``` Install-Package AutoMapperAnalyzer.Analyzers ``` ### 项目文件 (用于 CI/CD) ``` all runtime; build; native; contentfiles; analyzers ``` ### ⚡ 通用兼容性 | 平台 | 版本 | 支持 | AutoMapper | CI/CD 状态 | |----------------|---------|-------------|------------|--------------| | .NET Framework | 4.8+ | 🟢 **完全** | 10.1.1+ | ✅ **已测试** | | .NET | 6.0+ | 🟢 **完全** | 12.0.1+ | ✅ **已测试** | | .NET | 8.0+ | 🟢 **完全** | 14.0.0+ | ✅ **已测试** | | .NET | 9.0+ | 🟢 **完全** | 14.0.0+ | ✅ **已测试** | | .NET | 10.0+ | 🟢 **完全** | 14.0.0+ | ✅ **已测试** | *分析器目标框架为 .NET Standard 2.0,以实现最大兼容性* *所有平台均在自动化 CI/CD 管道中经过验证* ## 🎨 实际运行效果 ### ❌ **问题** ``` public class UserEntity { public int Id { get; set; } public string? FirstName { get; set; } // Nullable public string LastName { get; set; } public string Email { get; set; } public DateTime CreatedAt { get; set; } public List Tags { get; set; } // Collection type public Address HomeAddress { get; set; } // Complex object } public class UserDto { public int Id { get; set; } public string FirstName { get; set; } // Non-nullable! public string FullName { get; set; } // Different property! public string Age { get; set; } // Different type! public HashSet Tags { get; set; } // Incompatible collection! public AddressDto HomeAddress { get; set; } // Needs explicit mapping! } // This configuration has MULTIPLE issues: cfg.CreateMap(); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // 🚨 AM002: FirstName nullable→non-nullable (NullReferenceException risk) // 🚨 AM004: LastName will not be mapped (data loss) // 🚨 AM001: Age expects int but gets DateTime (runtime exception) // 🚨 AM021: Tags List→HashSet incompatible (mapping failure) // 🚨 AM020: HomeAddress→AddressDto needs CreateMap (runtime exception) ``` ### ✅ **解决方案** (自动生成!) ``` // Code fixes automatically suggest: cfg.CreateMap() .ForMember(dest => dest.FirstName, opt => opt.MapFrom(src => src.FirstName ?? "")) .ForMember(dest => dest.FullName, opt => opt.MapFrom(src => $"{src.FirstName} {src.LastName}")) .ForMember(dest => dest.Age, opt => opt.MapFrom(src => DateTime.Now.Year - src.CreatedAt.Year)) .ForMember(dest => dest.Tags, opt => opt.MapFrom(src => src.Tags.Select((tag, index) => index).ToHashSet())); // Separate mapping for complex types cfg.CreateMap(); ``` ## ⚙️ 精细控制 ### 严重性配置 (.editorconfig) ``` # 将类型安全视为构建错误 dotnet_diagnostic.AM001.severity = error dotnet_diagnostic.AM002.severity = error dotnet_diagnostic.AM011.severity = error # 数据丢失警告 dotnet_diagnostic.AM004.severity = warning dotnet_diagnostic.AM005.severity = warning # 优化建议 dotnet_diagnostic.AM020.severity = suggestion dotnet_diagnostic.AM021.severity = suggestion ``` ### 选择性抑制 ``` // Suppress with clear justification #pragma warning disable AM001 // Custom IValueConverter handles string→int cfg.CreateMap(); #pragma warning restore AM001 // Method-level suppression [SuppressMessage("AutoMapper", "AM004:Missing destination property", Justification = "PII data intentionally excluded for GDPR compliance")] public void ConfigureSafeUserMapping() { } ``` ## 📊 完整分析器覆盖范围 | 规则 | 描述 | 分析器 | 代码修复 | 严重性 | |-------------------------|--------------------------------|----------|----------|----------| | **🔒 类型安全** | | | | | AM001 | 属性类型不匹配 | ✅ | ✅ | Error | | AM002 | 可空→不可空 | ✅ | ✅ | Error / Info | | AM003 | 集合不兼容 | ✅ | ✅ | Error | | **📊 数据完整性** | | | | | AM004 | 缺失目标属性 | ✅ | ✅ | Warning | | AM005 | 区分大小写问题 | ✅ | ✅ | Warning | | AM006 | 未映射目标属性 | ✅ | ✅ | Info | | AM011 | 缺少必需属性 | ✅ | ✅ | Error | | **🧩 复杂映射** | | | | | AM020 | 嵌套对象问题 | ✅ | ✅ | Warning | | AM021 | 集合元素不匹配 | ✅ | ✅ | Warning | | AM022 | 循环引用风险 | ✅ | ✅ | Warning | | AM030 | 自定义类型转换器问题 | ✅ | ✅ | Error / Warning / Info | | **⚡ 性能** | | | | | AM031 | 性能警告 | ✅ | ✅ | Warning / Info | | **⚙️ 配置** | | | | | AM041 | 重复映射注册 | ✅ | ✅ | Warning | | AM050 | 冗余 MapFrom | ✅ | ✅ | Info | | **🚀 未来** | | | | | AM032+ | 高级 Null 传播 | 🔮 | 🔮 | - | | AM040+ | 配置规则 🔮 | 🔮 | - | | AM050+ | 高级优化 | 🔮 | 🔮 | - | ## 🛠️ 开发体验 ### IDE 集成 - **Visual Studio**:完整的 IntelliSense 集成,带有灯泡代码修复 - **VS Code**:通过 OmniSharp 提供丰富的诊断体验 - **JetBrains Rider**:带有快速修复建议的原生分析器支持 - **命令行**:与 `dotnet build` 无缝协作 ### 测试您的配置 ``` # 快速验证 dotnet build # Analyzer runs automatically # 全面测试 git clone https://github.com/georgepwall1991/automapper-analyser.git cd automapper-analyser dotnet run --project samples/AutoMapperAnalyzer.Samples # 查看所有实际运行中的 analyzer 警告 dotnet build samples/ --verbosity normal # 运行带 coverage 的完整测试套件 dotnet test --collect:"XPlat Code Coverage" --settings coverlet.runsettings ``` ### CI/CD 与质量保证 - **🔄 自动化测试**:每次提交均会跨多个 .NET 版本进行测试 - **📊 代码覆盖率**:与 Codecov 集成以进行全面的覆盖率跟踪 - **🛡️ 质量门禁**:构建仅因真正的错误而失败,警告会被保留 - **⚡ 跨平台**:在 Ubuntu (CI) 和 Windows (兼容性测试) 上得到验证 - **📈 性能**:带有分析器缓存的增量构建,以实现最佳速度 ## 🏗️ 架构亮点 这不仅是一个分析器——它专为**企业级可靠性**而构建: - **🏎️ 性能优先**:增量分析,对 IDE 影响极小 - **🔧 可扩展设计**:用于新规则的简洁插件架构 - **🧪 历经实战**:发布验证包括全套覆盖率以及对高风险修复程序的针对性回归测试 - **🌐 跨平台**:在 Windows、macOS、Linux 上表现一致 - **⚡ CI/CD 就绪**:带有 Codecov 集成的自动化 GitHub Actions - **📊 代码覆盖率**:55%+ 的覆盖率,并配有全面的测试 ## 🎯 下一步计划 ### 最近已完成 ✅ - **v2.30.15**:通过特定于描述符的无修复元数据和可执行接口集合重写,强化修复程序 UX 信任度 - **v2.30.14**:AM021 反向映射集合元素诊断能在没有重复干扰的情况下捕获缺失的反向元素映射 - **v2.30.13**:AM041 重复映射标签保留泛型类型参数和数组秩 - **v2.30.12**:AM030 接口类型转换器使用和 AM021 字典修复程序安全性 - **v2.30.11**:针对直接属性不匹配补救的 AM001 枚举/字符串转换修复 - **v2.30.10**:针对基于字符串的成员和类型安全抑制的 AM050 已验证冗余 `MapFrom` 清理 - **v2.30.9**:AM004/AM005 严重性文档信任与描述符对齐的规则文档 - **v2.30.8**:AM030 null 守卫修复程序精度,无需侵入性的 `using System` 编辑 - **v2.30.7**:针对嵌套映射链和显式递归控制的 AM022 递归边界精度 - **v2.30.6**:带有嵌套源路径和 Task 属性 `.Result` 覆盖的 AM031 源集合缓存精度 - **v2.30.5**:AM030 针对 `ConvertUsing(typeof(...))` 的基于类型的转换器使用精度 - **v2.30.4**:AM022 映射递归精度,减少了不相关循环的误报 - **v2.30.3**:带有显式配置回归覆盖的 AM011 ForPath 必需成员边界 - **v2.30.2**:带有针对性回归覆盖的 AM003 可分配集合边界抑制 - **v2.30.1**:AM002 可空性契约对齐,带有描述符精确的文档和可空上下文回归覆盖 - **v2.30.0**:针对 AM001、AM005、AM006、AM011 和 AM021 的修复强化,提供更安全的操作选择 - **v2.29.0**:智能主要修复——将每个诊断的修复噪音减少到最多 2 个灯泡选项 - **v2.28.2**:减少误报、改进修复程序 UX 以及强化发布工作流 - **v2.28.1**:区分大小写的 AM021 抑制和修复程序准确性改进 - **v2.28.0**:分析器逻辑修复和性能改进 - **v2.27.0**:AM050 可空安全性修复和扩展的回归覆盖范围 ### 阶段 5B:增强分析 (即将推出) - **AM032**:带有智能修复的高级 null 传播模式 ### 阶段 6:配置与 Profile 分析 - **AM040**:Profile 注册分析和自动注册修复 ### 超越代码分析 - **NuGet 包模板**:带有预配置分析器的项目模板 - **MSBuild 集成**:用于映射验证的自定义构建目标 - **文档生成**:自动生成映射文档 - **指标仪表板**:构建时分析报告 ## 🤝 贡献 我们正在构建特别的东西,**您的专业知识会让它变得更好**。 **快速开始贡献:** ``` git clone https://github.com/georgepwall1991/automapper-analyser.git cd automapper-analyser dotnet test ``` **我们需要:** - 🧪 更多边缘情况场景 - 📝 文档改进 - 🚀 性能优化 - 💡 新的分析器规则想法 有关详细的指南,请参阅我们的[贡献指南](docs/CONTRIBUTING.md)。 ## 📚 深入资源 - 📖 [**架构指南**](docs/ARCHITECTURE.md) - 底层运作原理 - 🔍 [**诊断规则**](docs/DIAGNOSTIC_RULES.md) - 完整的规则参考 - 🧭 [**生成的规则目录**](docs/RULE_CATALOG.md) - 描述符、修复程序、示例和信任级别的真实来源 - 🧪 [**示例库**](samples/AutoMapperAnalyzer.Samples/README.md) - 真实世界场景 - 🚀 [**CI/CD 管道**](docs/CI-CD.md) - 我们的构建和部署过程 - 📊 [**兼容性矩阵**](docs/COMPATIBILITY.md) - 框架支持详情 ## 💬 社区与支持 **获取帮助:** - 🐛 [**问题**](https://github.com/georgepwall1991/automapper-analyser/issues) - 错误报告和功能请求 - 💬 [**讨论**](https://github.com/georgepwall1991/automapper-analyser/discussions) - 问题和想法 - 📖 [**Wiki**](https://github.com/georgepwall1991/automapper-analyser/wiki) - 综合文档 ## 📄 许可证 **MIT 许可证** - 可随处使用,如果可以的话请贡献回去。
### ⭐ **如果它为您节省了时间,请给此仓库加星!** **由调试过太多 AutoMapper 问题的开发者倾注 ❤️ 构建** [🚀 **立即开始**](#-installation) • [📖 **阅读文档**](docs/) • [💬 **加入讨论**](https://github.com/georgepwall1991/automapper-analyser/discussions)
标签:AutoMapper, IDE插件, LNA, NuGet包, Roslyn, SOC Prime, 代码修复, 代码重构, 多人体追踪, 对象映射映射错误检测, 开发工具, 开发者体验, 开源框架, 持续集成, 编译时检查, 运行时异常预防, 错误基检测, 静态代码分析, 静态分析器