import '../core/config.dart'; import '../core/exceptions.dart'; import '../core/models.dart'; import '../utils/string_utils.dart'; /// 代码生成器基类 /// 定义通用的接口和功能 abstract class BaseGenerator { /// 生成器类型 String get generatorType; /// 生成代码 String generate(); /// 生成文件头注释 String generateFileHeader(String description) { return StringUtils.generateFileHeader( description, SwaggerConfig.swaggerJsonUrl, ); } /// 生成类型安全的代码 String generateTypeCheckedCode(String code) { // 基础类型检查和验证 try { if (code.trim().isEmpty) { throw CodeGenerationException( '生成的代码不能为空', generatorType: generatorType, ); } return code; } catch (e) { throw CodeGenerationException( '代码生成失败', details: e.toString(), generatorType: generatorType, ); } } /// 验证生成的代码是否符合Dart语法规范 bool validateDartCode(String code) { // 基础验证规则 final validationRules = [ // 检查是否有未闭合的大括号 (String code) => _countMatches(code, '{') == _countMatches(code, '}'), // 检查是否有未闭合的小括号 (String code) => _countMatches(code, '(') == _countMatches(code, ')'), // 检查是否有未闭合的方括号 (String code) => _countMatches(code, '[') == _countMatches(code, ']'), // 检查是否有基本的类声明 (String code) => code.contains('class ') || code.contains('enum ') || code.contains('const '), ]; for (final rule in validationRules) { if (!rule(code)) { return false; } } return true; } /// 计算字符出现次数 int _countMatches(String text, String pattern) { return pattern.allMatches(text).length; } } /// 模型代码生成器基类 abstract class ModelGenerator extends BaseGenerator { final SwaggerDocument document; final bool useSimpleModels; ModelGenerator(this.document, {this.useSimpleModels = false}); @override String get generatorType => 'ModelGenerator'; /// 生成单个模型的代码 String generateModelCode(ApiModel model); /// 生成枚举代码 String generateEnumCode(ApiModel model) { if (!model.isEnum) { throw CodeGenerationException('模型不是枚举类型', generatorType: generatorType); } final className = StringUtils.generateClassName(model.name); final enumType = model.enumType?.value ?? 'string'; final buffer = StringBuffer(); // 生成文件头 buffer.writeln(generateFileHeader('${model.name} 枚举定义')); buffer.writeln(''); // 生成枚举类 if (model.description.isNotEmpty) { buffer.writeln(StringUtils.generateComment(model.description)); } buffer.writeln('enum $className {'); // 生成枚举值 for (int i = 0; i < model.enumValues.length; i++) { final value = model.enumValues[i]; final enumName = StringUtils.generateEnumValueName(value, i); if (enumType == 'integer' || enumType == 'number') { buffer.writeln(' $enumName($value),'); } else { buffer.writeln(' $enumName(\'$value\'),'); } } // 移除最后一个逗号 final content = buffer.toString().trimRight(); buffer.clear(); buffer.writeln(content.substring(0, content.lastIndexOf(','))); buffer.writeln(';'); buffer.writeln(''); // 生成构造函数和方法 buffer.writeln(' const $className(this.value);'); buffer.writeln( ' final ${enumType == 'integer' || enumType == 'number' ? 'int' : 'String'} value;', ); buffer.writeln(''); // 生成 fromValue 方法 buffer.writeln(' static $className fromValue(dynamic value) {'); buffer.writeln(' for (final enumValue in $className.values) {'); buffer.writeln(' if (enumValue.value == value) {'); buffer.writeln(' return enumValue;'); buffer.writeln(' }'); buffer.writeln(' }'); buffer.writeln(' throw ArgumentError(\'Unknown enum value: \$value\');'); buffer.writeln(' }'); buffer.writeln(''); // 生成 fromJson 方法 buffer.writeln(' factory $className.fromJson(dynamic json) {'); buffer.writeln(' return fromValue(json);'); buffer.writeln(' }'); buffer.writeln(''); // 生成 toJson 方法 buffer.writeln(' dynamic toJson() => value;'); buffer.writeln(''); buffer.writeln('}'); return generateTypeCheckedCode(buffer.toString()); } // 已移动到 StringUtils.generateEnumValueName /// 获取导入的类型列表 Set getImportedTypes(ApiModel model) { final importedTypes = {}; model.properties.forEach((_, property) { if (property.type == PropertyType.reference && property.reference != null) { importedTypes.add(property.reference!); } else if (property.type == PropertyType.array) { // 处理数组类型的引用 if (property.items != null) { final itemType = _getItemType(property.items!); // 如果是引用类型(不是基本类型),则添加到导入列表 if (itemType != 'String' && itemType != 'int' && itemType != 'double' && itemType != 'bool' && itemType != 'dynamic') { importedTypes.add(property.items!.name); } } } }); return importedTypes; } /// 生成属性的Dart类型 String getDartPropertyType(ApiProperty property) { switch (property.type) { case PropertyType.string: switch (property.format) { case 'date': case 'date-time': return 'DateTime'; default: return 'String'; } case PropertyType.integer: return 'int'; case PropertyType.number: return 'double'; case PropertyType.boolean: return 'bool'; case PropertyType.array: // 根据数组元素类型推导具体类型 if (property.items != null) { final itemType = _getItemType(property.items!); return 'List<$itemType>'; } return 'List'; case PropertyType.object: return 'Map'; case PropertyType.reference: return property.reference != null ? StringUtils.generateClassName(property.reference!) : 'dynamic'; default: return 'dynamic'; } } /// 获取数组元素的类型 String _getItemType(ApiModel items) { // 如果是引用类型,直接返回类名 if (items.name != 'string' && items.name != 'integer' && items.name != 'number' && items.name != 'boolean') { return StringUtils.generateClassName(items.name); } // 如果是基本类型,转换为对应的Dart类型 switch (items.name) { case 'string': return 'String'; case 'integer': return 'int'; case 'number': return 'double'; case 'boolean': return 'bool'; default: return 'dynamic'; } } } /// 选项配置类 class GeneratorOptions { final bool generateEndpoints; final bool generateModels; final bool generateDocs; final bool useSimpleModels; final bool separateModelFiles; final String modelsDirectory; final String outputDirectory; final String endpointsFileName; final String docsFileName; const GeneratorOptions({ this.generateEndpoints = true, this.generateModels = true, this.generateDocs = true, this.useSimpleModels = false, this.separateModelFiles = true, this.modelsDirectory = 'models', this.outputDirectory = 'generator', this.endpointsFileName = 'api_paths.dart', this.docsFileName = 'api_documentation.md', }); /// 从命令行参数创建选项 factory GeneratorOptions.fromArgs(List args) { bool generateEndpoints = false; bool generateModels = false; bool generateDocs = false; bool useSimpleModels = false; bool separateModelFiles = true; String modelsDirectory = 'models'; String outputDirectory = 'generator'; String endpointsFileName = 'api_paths.dart'; String docsFileName = 'api_documentation.md'; bool hasSpecificOption = false; for (int i = 0; i < args.length; i++) { final arg = args[i]; switch (arg) { case '--endpoints': generateEndpoints = true; hasSpecificOption = true; break; case '--models': generateModels = true; hasSpecificOption = true; break; case '--docs': generateDocs = true; hasSpecificOption = true; break; case '--all': generateEndpoints = true; generateModels = true; generateDocs = true; hasSpecificOption = true; break; case '--simple': useSimpleModels = true; break; case '--models-dir': if (i + 1 < args.length) { modelsDirectory = args[i + 1]; i++; // 跳过下一个参数 } break; case '--output-dir': if (i + 1 < args.length) { outputDirectory = args[i + 1]; i++; // 跳过下一个参数 } break; case '--endpoints-file': if (i + 1 < args.length) { endpointsFileName = args[i + 1]; i++; // 跳过下一个参数 } break; case '--docs-file': if (i + 1 < args.length) { docsFileName = args[i + 1]; i++; // 跳过下一个参数 } break; } } // 如果没有指定特定选项,默认生成所有文件 if (!hasSpecificOption) { generateEndpoints = true; generateModels = true; generateDocs = true; } return GeneratorOptions( generateEndpoints: generateEndpoints, generateModels: generateModels, generateDocs: generateDocs, useSimpleModels: useSimpleModels, separateModelFiles: separateModelFiles, modelsDirectory: modelsDirectory, outputDirectory: outputDirectory, endpointsFileName: endpointsFileName, docsFileName: docsFileName, ); } }