swagger_generator_flutter/lib/utils/reference_resolver.dart

307 lines
9.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.

/// 引用解析器
/// 处理复杂嵌套类型和循环引用检测
library;
import 'package:logging/logging.dart';
import 'package:swagger_generator_flutter/core/models.dart';
/// 引用解析器
/// 负责处理 OpenAPI 文档中的复杂引用关系
class ReferenceResolver {
ReferenceResolver({this.maxDepth = 50});
static final Logger _logger = Logger('ReferenceResolver');
/// 已解析的模型缓存
final Map<String, ApiModel> _resolvedModels = {};
/// 当前解析路径(用于循环引用检测)
final Set<String> _resolutionPath = {};
/// 原始 JSON 数据缓存
final Map<String, Map<String, dynamic>> _rawSchemas = {};
/// 最大解析深度(防止过深的嵌套)
final int maxDepth;
/// 当前解析深度
int _currentDepth = 0;
/// 解析所有模型,处理复杂引用关系
Map<String, ApiModel> resolveModels(Map<String, dynamic> componentsJson) {
final schemasJson =
componentsJson['schemas'] as Map<String, dynamic>? ?? {};
// 第一步:缓存所有原始 schema 数据
_cacheRawSchemas(schemasJson);
// 第二步:解析所有模型
final resolvedModels = <String, ApiModel>{};
for (final schemaName in schemasJson.keys) {
try {
final model = resolveModel(schemaName);
if (model != null) {
resolvedModels[schemaName] = model;
}
} on Object catch (e) {
_logger.warning('⚠️ 解析模型 $schemaName 时发生错误: $e');
// 创建一个基本的模型作为后备
resolvedModels[schemaName] = ApiModel(
name: schemaName,
description: '解析失败的模型',
properties: {},
required: [],
);
}
}
return resolvedModels;
}
/// 缓存原始 schema 数据
void _cacheRawSchemas(Map<String, dynamic> schemasJson) {
schemasJson.forEach((name, schemaData) {
if (schemaData is Map<String, dynamic>) {
_rawSchemas[name] = schemaData;
}
});
}
/// 解析单个模型
ApiModel? resolveModel(String modelName) {
// 检查是否已经解析过
if (_resolvedModels.containsKey(modelName)) {
return _resolvedModels[modelName];
}
// 检查循环引用
if (_resolutionPath.contains(modelName)) {
_logger
.warning('🔄 检测到循环引用: ${_resolutionPath.join(' -> ')} -> $modelName');
return _createCircularReferenceModel(modelName);
}
// 检查解析深度
if (_currentDepth >= maxDepth) {
_logger.warning('⚠️ 达到最大解析深度 $maxDepth,停止解析 $modelName');
return _createDepthLimitModel(modelName);
}
// 获取原始数据
final schemaData = _rawSchemas[modelName];
if (schemaData == null) {
_logger.warning('⚠️ 未找到模型定义: $modelName');
return null;
}
// 开始解析
_resolutionPath.add(modelName);
_currentDepth++;
try {
final model = _parseModelWithContext(modelName, schemaData);
_resolvedModels[modelName] = model;
return model;
} finally {
_resolutionPath.remove(modelName);
_currentDepth--;
}
}
/// 在上下文中解析模型
ApiModel _parseModelWithContext(String name, Map<String, dynamic> json) {
// 检查是否是枚举类型
final isEnum = json['enum'] != null;
if (isEnum) {
return _parseEnumModel(name, json);
}
// 检查组合模式
if (json['allOf'] != null ||
json['oneOf'] != null ||
json['anyOf'] != null) {
return _parseCompositionModel(name, json);
}
// 解析普通对象模型
return _parseObjectModel(name, json);
}
/// 解析枚举模型
ApiModel _parseEnumModel(String name, Map<String, dynamic> json) {
final enumValues = List<dynamic>.from((json['enum'] as List?) ?? []);
final enumType =
PropertyType.fromString(json['type'] as String? ?? 'string');
return ApiModel(
name: name,
description: json['description'] as String? ?? '',
properties: {},
required: [],
isEnum: true,
enumValues: enumValues,
enumType: enumType,
);
}
/// 解析组合模式模型
ApiModel _parseCompositionModel(String name, Map<String, dynamic> json) {
// 解析组合模式
final allOf = _parseSchemaList(json['allOf'] as List<dynamic>? ?? []);
final oneOf = _parseSchemaList(json['oneOf'] as List<dynamic>? ?? []);
final anyOf = _parseSchemaList(json['anyOf'] as List<dynamic>? ?? []);
final notJson = json['not'] as Map<String, dynamic>?;
final not = notJson != null ? ApiSchema.fromJson(notJson) : null;
// 解析 discriminator
final discriminatorJson = json['discriminator'] as Map<String, dynamic>?;
final discriminator = discriminatorJson != null
? ApiDiscriminator.fromJson(discriminatorJson)
: null;
// 对于组合模式,我们需要合并属性
final mergedProperties = <String, ApiProperty>{};
final mergedRequired = <String>[];
// 从 allOf 中合并属性
for (final schema in allOf) {
_mergeSchemaProperties(schema, mergedProperties, mergedRequired);
}
// 如果有直接的 properties也要合并
if (json['properties'] != null) {
final directProperties = _parseProperties(
json['properties'] as Map<String, dynamic>,
List<String>.from((json['required'] as List?) ?? []),
);
mergedProperties.addAll(directProperties);
mergedRequired
.addAll(List<String>.from((json['required'] as List?) ?? []));
}
return ApiModel(
name: name,
description: json['description'] as String? ?? '',
properties: mergedProperties,
required: mergedRequired.toSet().toList(),
allOf: allOf,
oneOf: oneOf,
anyOf: anyOf,
not: not,
discriminator: discriminator,
);
}
/// 解析对象模型
ApiModel _parseObjectModel(String name, Map<String, dynamic> json) {
final properties = _parseProperties(
json['properties'] as Map<String, dynamic>? ?? {},
List<String>.from((json['required'] as List?) ?? []),
);
final required = List<String>.from((json['required'] as List?) ?? []);
return ApiModel(
name: name,
description: json['description'] as String? ?? '',
properties: properties,
required: required,
);
}
/// 解析 schema 列表
List<ApiSchema> _parseSchemaList(List<dynamic> schemaList) {
return schemaList
.map((schema) => ApiSchema.fromJson(schema as Map<String, dynamic>))
.toList();
}
/// 合并 schema 的属性
void _mergeSchemaProperties(
ApiSchema schema,
Map<String, ApiProperty> targetProperties,
List<String> targetRequired,
) {
// 如果是引用,解析引用的模型
if (schema.isReference && schema.reference != null) {
final referencedModel = resolveModel(schema.reference!);
if (referencedModel != null) {
targetProperties.addAll(referencedModel.properties);
targetRequired.addAll(referencedModel.required);
}
} else {
// 直接合并属性
targetProperties.addAll(schema.properties);
targetRequired.addAll(schema.required);
}
}
/// 解析属性
Map<String, ApiProperty> _parseProperties(
Map<String, dynamic> propertiesJson,
List<String> requiredFields,
) {
final properties = <String, ApiProperty>{};
propertiesJson.forEach((propName, propData) {
if (propData is Map<String, dynamic>) {
try {
final property =
_parsePropertyWithContext(propName, propData, requiredFields);
properties[propName] = property;
} on Object catch (e) {
_logger.warning('⚠️ 解析属性 $propName 时发生错误: $e');
// 创建一个基本属性作为后备
properties[propName] = ApiProperty(
name: propName,
type: PropertyType.string,
description: '解析失败的属性',
required: requiredFields.contains(propName),
);
}
}
});
return properties;
}
/// 在上下文中解析属性
ApiProperty _parsePropertyWithContext(
String name,
Map<String, dynamic> json,
List<String> requiredFields,
) {
// 使用现有的 ApiProperty.fromJson但在循环引用检测的上下文中
return ApiProperty.fromJson(name, json, requiredFields);
}
/// 创建循环引用模型
ApiModel _createCircularReferenceModel(String modelName) {
return ApiModel(
name: modelName,
description: '循环引用模型 - 为避免无限递归而创建的占位符',
properties: {},
required: [],
);
}
/// 创建深度限制模型
ApiModel _createDepthLimitModel(String modelName) {
return ApiModel(
name: modelName,
description: '深度限制模型 - 达到最大解析深度而创建的占位符',
properties: {},
required: [],
);
}
/// 清理缓存
void clearCache() {
_resolvedModels.clear();
_resolutionPath.clear();
_rawSchemas.clear();
_currentDepth = 0;
}
}