using System; using System.IO; using System.Linq; using System.Reflection; using System.Text.RegularExpressions; using SKIT.FlurlHttpClient.Tools.CodeAnalyzer; using Xunit; namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests { public class CodeAnalyzeTests { [Fact(DisplayName = "代码质量分析")] public void CodeAnalyze() { // NOTICE: // 如果 Visual Studio 遇到 “缺少 SKIT.FlurlHttpClient.Tools.CodeAnalyzer 包” 的错误, // 请参考此 Issue:https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient/issues/8 Assert.Null(Record.Exception(() => { var options = new TypeDeclarationAnalyzerOptions() { SdkAssembly = Assembly.GetAssembly(typeof(WechatApiClient))!, SdkRequestModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.Api.Models", SdkResponseModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.Api.Models", SdkExecutingExtensionDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.Api", SdkWebhookEventDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.Api.Events", ThrowOnNotFoundRequestModelTypes = true, ThrowOnNotFoundResponseModelTypes = true, ThrowOnNotFoundExecutingExtensionTypes = true, ThrowOnNotFoundWebhookEventTypes = true }; new TypeDeclarationAnalyzer(options) .AddRule((_, _, cur) => { if (cur.MemberKind != TypeDeclarationMemberKinds.RequestModelClass) return; string reqTypeName = cur.MemberAsType.GetNameWithoutGenerics(); string respTypeName = Regex.Replace(cur.MemberAsType.GetNameWithoutGenerics(), "Request$", "Response"); Type? inferType = cur.MemberAsType.GetInterfaces() .Where(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Models.IInferable<,>)) .Where(t => t.GenericTypeArguments[0].GetNameWithoutGenerics() == reqTypeName) .Where(t => t.GenericTypeArguments[1].GetNameWithoutGenerics() == respTypeName) .FirstOrDefault(); if (inferType is null) throw new AnalysisException($"类型 \"{cur.MemberAsType.Name}\" 是一个请求模型,但未正确未实现 IInferable 接口。"); }) .AssertNoIssues(); })); Assert.Null(Record.Exception(() => { string workdir = Environment.CurrentDirectory; string projdir = Path.Combine(workdir, "../../../../../"); var options = new SourceFileAnalyzerOptions() { SdkAssembly = Assembly.GetAssembly(typeof(WechatApiClient))!, SdkRequestModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.Api.Models", SdkResponseModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.Api.Models", SdkWebhookEventDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.Api.Events", ProjectSourceRootDirectory = Path.Combine(projdir, "./src/SKIT.FlurlHttpClient.Wechat.Api/"), ProjectTestRootDirectory = Path.Combine(projdir, "./test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/"), ThrowOnNotFoundRequestModelClassCodeFiles = true, ThrowOnNotFoundResponseModelClassCodeFiles = true, ThrowOnNotFoundExecutingExtensionClassCodeFiles = true, ThrowOnNotFoundWebhookEventClassCodeFiles = true, ThrowOnNotFoundRequestModelSerializationSampleFiles = true, ThrowOnNotFoundResponseModelSerializationSampleFiles = true, ThrowOnNotFoundWebhookEventSerializationSampleFiles = true }; new SourceFileAnalyzer(options).AssertNoIssues(); })); } } }