swagger_generator_flutter/validate_standards.dart

240 lines
6.8 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env dart
/// Augment 代码生成规范验证脚本
/// 用于验证生成的代码是否符合规范要求
import 'dart:convert';
import 'dart:io';
void main(List<String> args) async {
print('🔍 Augment 代码生成规范验证');
print('=' * 50);
final validator = StandardsValidator();
try {
await validator.validateAll();
print('\n✅ 所有检查通过!代码符合 Augment 规范。');
} catch (e) {
print('\n❌ 验证失败:$e');
exit(1);
}
}
class StandardsValidator {
final List<String> errors = [];
final List<String> warnings = [];
/// 验证所有规范
Future<void> validateAll() async {
print('📋 开始验证...\n');
await _validateSwaggerJson();
await _validateGeneratedFiles();
await _validateCodeQuality();
await _validateNamingConventions();
await _validateTypeConsistency();
_printResults();
if (errors.isNotEmpty) {
throw Exception('发现 ${errors.length} 个错误');
}
}
/// 验证 swagger.json
Future<void> _validateSwaggerJson() async {
print('🔍 验证 swagger.json...');
final swaggerFile = File('swagger.json');
if (!swaggerFile.existsSync()) {
errors.add('swagger.json 文件不存在');
return;
}
try {
final content = await swaggerFile.readAsString();
final swagger = jsonDecode(content) as Map<String, dynamic>;
// 检查 OpenAPI 版本
final openapi = swagger['openapi'] as String?;
if (openapi == null || !openapi.startsWith('3.0')) {
errors.add('OpenAPI 版本必须是 3.0.x当前$openapi');
}
// 检查基本结构
if (!swagger.containsKey('paths')) {
errors.add('swagger.json 缺少 paths 定义');
}
if (!swagger.containsKey('components')) {
warnings.add('swagger.json 缺少 components 定义');
}
// 检查 schemas
final components = swagger['components'] as Map<String, dynamic>?;
if (components != null) {
final schemas = components['schemas'] as Map<String, dynamic>?;
if (schemas == null || schemas.isEmpty) {
warnings.add('components/schemas 为空,可能影响类型生成');
}
}
print(' ✅ swagger.json 格式正确');
} catch (e) {
errors.add('swagger.json 格式错误:$e');
}
}
/// 验证生成的文件
Future<void> _validateGeneratedFiles() async {
print('🔍 验证生成的文件...');
final generatorDir = Directory('generator');
if (!generatorDir.existsSync()) {
errors.add('generator 目录不存在');
return;
}
// 检查目录结构
final apiDir = Directory('generator/api');
final modelsDir = Directory('generator/api_models');
if (!apiDir.existsSync()) {
errors.add('generator/api 目录不存在');
}
if (!modelsDir.existsSync()) {
errors.add('generator/api_models 目录不存在');
}
// 检查 index.dart 文件
final indexFile = File('generator/api_models/index.dart');
if (!indexFile.existsSync()) {
warnings.add('generator/api_models/index.dart 文件不存在');
}
print(' ✅ 文件结构正确');
}
/// 验证代码质量
Future<void> _validateCodeQuality() async {
print('🔍 验证代码质量...');
// 运行 dart analyze
final analyzeResult = await Process.run('dart', ['analyze', 'generator/']);
if (analyzeResult.exitCode != 0) {
final output = analyzeResult.stdout.toString();
final errorOutput = analyzeResult.stderr.toString();
if (output.contains('error') || errorOutput.contains('error')) {
errors.add('dart analyze 发现错误:\n$output\n$errorOutput');
} else if (output.contains('warning') ||
errorOutput.contains('warning')) {
warnings.add('dart analyze 发现警告:\n$output\n$errorOutput');
}
} else {
print(' ✅ 静态分析通过');
}
}
/// 验证命名规范
Future<void> _validateNamingConventions() async {
print('🔍 验证命名规范...');
final apiDir = Directory('generator/api');
if (apiDir.existsSync()) {
await for (final file in apiDir.list()) {
if (file is File && file.path.endsWith('.dart')) {
final fileName = file.path.split('/').last;
// API 文件应该以 _api.dart 结尾
if (!fileName.endsWith('_api.dart')) {
errors.add('API 文件命名不规范:$fileName(应该以 _api.dart 结尾)');
}
// 检查文件名是否为 snake_case
final baseName = fileName.replaceAll('_api.dart', '');
if (!_isSnakeCase(baseName)) {
errors.add('API 文件名不是 snake_case$fileName');
}
}
}
}
final modelsDir = Directory('generator/api_models');
if (modelsDir.existsSync()) {
await for (final file in modelsDir.list()) {
if (file is File &&
file.path.endsWith('.dart') &&
!file.path.endsWith('index.dart')) {
final fileName = file.path.split('/').last;
final baseName = fileName.replaceAll('.dart', '');
// 检查模型文件名是否为 snake_case
if (!_isSnakeCase(baseName)) {
errors.add('模型文件名不是 snake_case$fileName');
}
}
}
}
print(' ✅ 命名规范检查完成');
}
/// 验证类型一致性
Future<void> _validateTypeConsistency() async {
print('🔍 验证类型一致性...');
// 检查是否有硬编码的类型推断
final generatorFile = File('lib/generators/retrofit_api_generator.dart');
if (generatorFile.existsSync()) {
final content = await generatorFile.readAsString();
// 检查是否还有硬编码的类型映射
final hardcodedPatterns = [
'TaskInfoResult',
'if.*contains.*login.*return',
'if.*contains.*task.*return',
'if.*tag.*contains.*return',
];
for (final pattern in hardcodedPatterns) {
final regex = RegExp(pattern, caseSensitive: false);
if (regex.hasMatch(content)) {
errors.add('发现硬编码类型推断:$pattern');
}
}
}
print(' ✅ 类型一致性检查完成');
}
/// 检查是否为 snake_case
bool _isSnakeCase(String name) {
return RegExp(r'^[a-z][a-z0-9_]*$').hasMatch(name);
}
/// 打印验证结果
void _printResults() {
print('\n📊 验证结果:');
print(' 错误:${errors.length}');
print(' 警告:${warnings.length}');
if (errors.isNotEmpty) {
print('\n❌ 错误列表:');
for (int i = 0; i < errors.length; i++) {
print(' ${i + 1}. ${errors[i]}');
}
}
if (warnings.isNotEmpty) {
print('\n⚠️ 警告列表:');
for (int i = 0; i < warnings.length; i++) {
print(' ${i + 1}. ${warnings[i]}');
}
}
}
}