swagger_generator_flutter/lib/validators/rules/path_rules.dart

240 lines
6.0 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.

import 'package:swagger_generator_flutter/core/models.dart';
import 'package:swagger_generator_flutter/validators/core/validation_context.dart';
import 'package:swagger_generator_flutter/validators/core/validation_result.dart';
import 'package:swagger_generator_flutter/validators/core/validation_rule.dart';
/// 路径验证规则
class PathValidationRule extends ValidationRule {
@override
String get id => 'path_validation';
@override
String get name => '路径验证';
@override
ValidationResult validate(ValidationContext context) {
final paths = context.document.paths;
final errors = <ValidationError>[];
final warnings = <ValidationWarning>[];
if (paths.isEmpty) {
errors.add(
const ValidationError(
path: 'paths',
message: 'API 文档必须包含至少一个路径',
type: ValidationErrorType.required,
),
);
return ValidationResult(isValid: false, errors: errors);
}
paths.forEach((routeKey, path) {
final pathKey = 'paths["${routeKey.pattern}"][${routeKey.method.value}]';
_validatePath(path, pathKey, errors, warnings);
});
return ValidationResult(
isValid: errors.isEmpty,
errors: errors,
warnings: warnings,
);
}
void _validatePath(
ApiPath path,
String pathKey,
List<ValidationError> errors,
List<ValidationWarning> warnings,
) {
// 验证操作 ID
if (path.operationId.isEmpty) {
warnings.add(
ValidationWarning(
path: '$pathKey.operationId',
message: '缺少操作 ID',
suggestion: '建议为每个操作添加唯一的 operationId',
),
);
}
// 验证摘要和描述
if (path.summary.isEmpty) {
warnings.add(
ValidationWarning(
path: '$pathKey.summary',
message: '缺少操作摘要',
suggestion: '建议添加简短的操作描述',
),
);
}
// 验证参数
for (var i = 0; i < path.parameters.length; i++) {
_validateParameter(
path.parameters[i],
'$pathKey.parameters[$i]',
errors,
warnings,
);
}
// 验证请求体
if (path.requestBody != null) {
_validateRequestBody(
path.requestBody!,
'$pathKey.requestBody',
errors,
warnings,
);
}
// 验证响应
if (path.responses.isEmpty) {
errors.add(
ValidationError(
path: '$pathKey.responses',
message: '操作必须定义至少一个响应',
type: ValidationErrorType.required,
),
);
} else {
path.responses.forEach((code, response) {
_validateResponse(
response,
'$pathKey.responses["$code"]',
errors,
warnings,
);
});
}
// 验证安全要求
// 安全要求的详细验证可能需要单独的规则或在这里简单检查
}
void _validateParameter(
ApiParameter parameter,
String path,
List<ValidationError> errors,
List<ValidationWarning> warnings,
) {
if (parameter.name.isEmpty) {
errors.add(
ValidationError(
path: '$path.name',
message: '参数名称不能为空',
type: ValidationErrorType.required,
),
);
}
// 验证路径参数必须是必需的
if (parameter.location == ParameterLocation.path && !parameter.required) {
errors.add(
ValidationError(
path: '$path.required',
message: '路径参数必须是必需的',
type: ValidationErrorType.constraint,
),
);
}
// 验证参数类型
if (parameter.type == PropertyType.unknown) {
warnings.add(
ValidationWarning(
path: '$path.type',
message: '参数类型未知',
suggestion: '建议明确指定参数类型',
),
);
}
}
void _validateRequestBody(
ApiRequestBody requestBody,
String path,
List<ValidationError> errors,
List<ValidationWarning> warnings,
) {
if (requestBody.content.isEmpty) {
errors.add(
ValidationError(
path: '$path.content',
message: '请求体必须定义至少一种内容类型',
type: ValidationErrorType.required,
),
);
}
requestBody.content.forEach((mediaType, content) {
_validateMediaType(
content,
'$path.content["$mediaType"]',
mediaType,
errors,
warnings,
);
});
}
void _validateResponse(
ApiResponse response,
String path,
List<ValidationError> errors,
List<ValidationWarning> warnings,
) {
if (response.description.isEmpty) {
warnings.add(
ValidationWarning(
path: '$path.description',
message: '响应缺少描述',
suggestion: '建议为响应添加描述',
),
);
}
response.content.forEach((mediaType, content) {
_validateMediaType(
content,
'$path.content["$mediaType"]',
mediaType,
errors,
warnings,
);
});
}
void _validateMediaType(
ApiMediaType mediaType,
String path,
String contentType,
List<ValidationError> errors,
List<ValidationWarning> warnings,
) {
// 验证 schema
if (mediaType.schema == null) {
warnings.add(
ValidationWarning(
path: '$path.schema',
message: '媒体类型缺少 schema 定义',
suggestion: '建议为媒体类型添加 schema',
),
);
}
// 验证编码(仅适用于 multipart 和 form data
if (contentType.startsWith('multipart/') || contentType.contains('form')) {
if (mediaType.encoding.isEmpty) {
warnings.add(
ValidationWarning(
path: '$path.encoding',
message: '表单数据建议定义编码信息',
suggestion: '为文件上传字段添加 contentType 等编码信息',
),
);
}
}
}
}