import 'package:swagger_generator_flutter/core/config.dart'; import 'package:swagger_generator_flutter/core/exceptions.dart'; import 'package:swagger_generator_flutter/core/models.dart'; import 'package:swagger_generator_flutter/utils/string_utils.dart'; /// 代码生成器基类 /// 定义通用的接口和功能 abstract class BaseGenerator { /// 生成器类型 String get generatorType; /// 生成代码 String generate(); /// 生成文件头注释 /// [description] 文件描述 /// [fileName] 文件名(可选) String generateFileHeader(String description, {String? fileName}) { final header = StringUtils.generateFileHeader( description, SwaggerConfig.swaggerJsonUrls.isNotEmpty ? SwaggerConfig.swaggerJsonUrls.first : '', fileName: fileName, fileType: description, ); // 添加 lint 忽略注释 return '$header\n// ignore_for_file: type=lint, invalid_annotation_target\n'; } /// 生成类型安全的代码 String generateTypeCheckedCode(String code) { // 基础类型检查和验证 try { if (code.trim().isEmpty) { throw CodeGenerationException( '生成的代码不能为空', generatorType: generatorType, ); } // 确保文件以换行符结尾 if (!code.endsWith('\n')) { return '$code\n'; } 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 { ModelGenerator(this.document, {this.useSimpleModels = false}); final SwaggerDocument document; final bool useSimpleModels; @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 valueType = enumType == 'integer' || enumType == 'number' ? 'int' : 'String'; final buffer = StringBuffer() // 生成文件头 ..writeln(generateFileHeader('${model.name} 枚举定义')) ..writeln(); // 生成枚举类 if (model.description.isNotEmpty) { buffer.writeln(StringUtils.generateComment(model.description)); } buffer.writeln('enum $className {'); // 生成枚举值 for (var i = 0; i < model.enumValues.length; i++) { final value = model.enumValues[i]; final enumName = StringUtils.generateEnumValueName(value, i); final enumLine = enumType == 'integer' || enumType == 'number' ? ' $enumName($value),' : " $enumName('$value'),"; buffer.writeln(enumLine); } // 移除最后一个逗号 final content = buffer.toString().trimRight(); buffer ..clear() ..writeAll( [ content.substring(0, content.lastIndexOf(',')), ';', '', ' const $className(this.value);', ' final $valueType value;', '', ' static $className fromValue(dynamic value) {', ' for (final enumValue in $className.values) {', ' if (enumValue.value == value) {', ' return enumValue;', ' }', ' }', r" throw ArgumentError('Unknown enum value: $value');", ' }', '', ' factory $className.fromJson(dynamic json) {', ' return fromValue(json);', ' }', '', ' dynamic toJson() => value;', '', '}', ], '\n', ); 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.enumType: return 'String'; 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'; case PropertyType.file: return 'dynamic'; case PropertyType.date: return 'DateTime'; case PropertyType.dateTime: return 'DateTime'; case PropertyType.unknown: 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 { const GeneratorOptions({ this.generateEndpoints = true, this.generateModels = true, this.generateDocs = true, this.useSimpleModels = false, this.modelsDirectory = 'models', this.outputDirectory = 'generator', this.endpointsFileName = 'api_paths.dart', this.docsFileName = 'api_documentation.md', }); /// 从命令行参数创建选项 factory GeneratorOptions.fromArgs(List args) { var generateEndpoints = false; var generateModels = false; var generateDocs = false; var useSimpleModels = false; var modelsDirectory = 'models'; var outputDirectory = 'generator'; var endpointsFileName = 'api_paths.dart'; var docsFileName = 'api_documentation.md'; var hasSpecificOption = false; for (var i = 0; i < args.length; i++) { final arg = args[i]; switch (arg) { case '--endpoints': generateEndpoints = true; hasSpecificOption = true; case '--models': generateModels = true; hasSpecificOption = true; case '--docs': generateDocs = true; hasSpecificOption = true; case '--all': generateEndpoints = true; generateModels = true; generateDocs = true; hasSpecificOption = true; case '--simple': useSimpleModels = true; case '--models-dir': if (i + 1 < args.length) { modelsDirectory = args[i + 1]; i++; // 跳过下一个参数 } case '--output-dir': if (i + 1 < args.length) { outputDirectory = args[i + 1]; i++; // 跳过下一个参数 } case '--endpoints-file': if (i + 1 < args.length) { endpointsFileName = args[i + 1]; i++; // 跳过下一个参数 } case '--docs-file': if (i + 1 < args.length) { docsFileName = args[i + 1]; i++; // 跳过下一个参数 } } } // 如果没有指定特定选项,默认生成所有文件 if (!hasSpecificOption) { generateEndpoints = true; generateModels = true; generateDocs = true; } return GeneratorOptions( generateEndpoints: generateEndpoints, generateModels: generateModels, generateDocs: generateDocs, useSimpleModels: useSimpleModels, modelsDirectory: modelsDirectory, outputDirectory: outputDirectory, endpointsFileName: endpointsFileName, docsFileName: docsFileName, ); } final bool generateEndpoints; final bool generateModels; final bool generateDocs; final bool useSimpleModels; final String modelsDirectory; final String outputDirectory; final String endpointsFileName; final String docsFileName; }