From a758d6ada58a136d074349d5a54b4b390b46eb6b Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Sat, 4 Nov 2023 14:13:31 +0100 Subject: [PATCH] feat(dynamite): allow per spec configuration Signed-off-by: Nikolas Rimikis --- packages/dynamite/dynamite/README.md | 5 ++ .../src/models/dynamite_config/config.dart | 60 +++++++++++++++++ .../src/models/dynamite_config/config.g.dart | 65 +++++++++++++++++-- .../dynamite/lib/src/openapi_builder.dart | 17 ++--- 4 files changed, 132 insertions(+), 15 deletions(-) diff --git a/packages/dynamite/dynamite/README.md b/packages/dynamite/dynamite/README.md index fd7d03a0647..a9616f86679 100644 --- a/packages/dynamite/dynamite/README.md +++ b/packages/dynamite/dynamite/README.md @@ -26,5 +26,10 @@ targets: - 'factory .*\.fromJson\(Map json\) => _jsonSerializers\.deserializeWith\(serializer, json\)!;' - 'Map toJson\(\) => _jsonSerializers\.serializeWith\(serializer, this\)! as Map;' - 'static BuiltSet<.*> get values => _\$.*Values;' + overrides: + # Tighten linting rules for specific specs + lib/my_spec.openapi.json: + analyzer_ignores: + - camel_case_types ``` diff --git a/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.dart b/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.dart index 6c6439087e4..07aaf31a5a0 100644 --- a/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.dart +++ b/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.dart @@ -33,6 +33,66 @@ abstract class DynamiteConfig implements Built? get overrides; + + /// Whether to apply code optimizations. + /// + /// The built code will adhere more to the dart code style but is equally as valid. + bool get applyOptimizations; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(final DynamiteConfigBuilder b) { + b.applyOptimizations = true; + } + + /// Gets the config for the given [uri]. + /// + /// Returns this if no override is set. + DynamiteConfig configFor(final String uri) { + if (overrides == null) { + return this; + } + + DynamiteConfig? override; + for (final entry in overrides!.entries) { + if (RegExp(entry.key).hasMatch(uri)) { + override = entry.value; + break; + } + } + + if (override == null) { + return this; + } + + return merge(override); + } + + /// Merges `this` config with the given [override]. + /// + /// Throws a [ArgumentError] if the override has overrides itself. + DynamiteConfig merge(final DynamiteConfig other) { + if (other.overrides != null) { + throw ArgumentError('Configs can only be merged with a config that does not have further overrides'); + } + + return rebuild((final b) { + final analyzerIgnores = other.analyzerIgnores; + if (analyzerIgnores != null) { + b.analyzerIgnores.replace(analyzerIgnores); + } + + final coverageIgnores = other.coverageIgnores; + if (coverageIgnores != null) { + b.coverageIgnores.replace(coverageIgnores); + } + }); + } } @SerializersFor([ diff --git a/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.g.dart b/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.g.dart index 0903b8d2fc2..839d0746add 100644 --- a/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.g.dart +++ b/packages/dynamite/dynamite/lib/src/models/dynamite_config/config.g.dart @@ -9,7 +9,9 @@ part of 'config.dart'; Serializers _$_serializers = (Serializers().toBuilder() ..add(DynamiteConfig.serializer) ..addBuilderFactory(const FullType(BuiltSet, [FullType(String)]), () => SetBuilder()) - ..addBuilderFactory(const FullType(BuiltSet, [FullType(String)]), () => SetBuilder())) + ..addBuilderFactory(const FullType(BuiltSet, [FullType(String)]), () => SetBuilder()) + ..addBuilderFactory(const FullType(BuiltMap, [FullType(String), FullType(DynamiteConfig)]), + () => MapBuilder())) .build(); Serializer _$dynamiteConfigSerializer = _$DynamiteConfigSerializer(); @@ -22,7 +24,10 @@ class _$DynamiteConfigSerializer implements StructuredSerializer @override Iterable serialize(Serializers serializers, DynamiteConfig object, {FullType specifiedType = FullType.unspecified}) { - final result = []; + final result = [ + 'applyOptimizations', + serializers.serialize(object.applyOptimizations, specifiedType: const FullType(bool)), + ]; Object? value; value = object.analyzerIgnores; if (value != null) { @@ -42,6 +47,13 @@ class _$DynamiteConfigSerializer implements StructuredSerializer ..add('pageWidth') ..add(serializers.serialize(value, specifiedType: const FullType(int))); } + value = object.overrides; + if (value != null) { + result + ..add('overrides') + ..add(serializers.serialize(value, + specifiedType: const FullType(BuiltMap, [FullType(String), FullType(DynamiteConfig)]))); + } return result; } @@ -67,6 +79,13 @@ class _$DynamiteConfigSerializer implements StructuredSerializer case 'pageWidth': result.pageWidth = serializers.deserialize(value, specifiedType: const FullType(int)) as int?; break; + case 'overrides': + result.overrides.replace(serializers.deserialize(value, + specifiedType: const FullType(BuiltMap, [FullType(String), FullType(DynamiteConfig)]))!); + break; + case 'applyOptimizations': + result.applyOptimizations = serializers.deserialize(value, specifiedType: const FullType(bool))! as bool; + break; } } @@ -81,11 +100,19 @@ class _$DynamiteConfig extends DynamiteConfig { final BuiltSet? coverageIgnores; @override final int? pageWidth; + @override + final BuiltMap? overrides; + @override + final bool applyOptimizations; factory _$DynamiteConfig([void Function(DynamiteConfigBuilder)? updates]) => (DynamiteConfigBuilder()..update(updates))._build(); - _$DynamiteConfig._({this.analyzerIgnores, this.coverageIgnores, this.pageWidth}) : super._(); + _$DynamiteConfig._( + {this.analyzerIgnores, this.coverageIgnores, this.pageWidth, this.overrides, required this.applyOptimizations}) + : super._() { + BuiltValueNullFieldError.checkNotNull(applyOptimizations, r'DynamiteConfig', 'applyOptimizations'); + } @override DynamiteConfig rebuild(void Function(DynamiteConfigBuilder) updates) => (toBuilder()..update(updates)).build(); @@ -99,7 +126,9 @@ class _$DynamiteConfig extends DynamiteConfig { return other is DynamiteConfig && analyzerIgnores == other.analyzerIgnores && coverageIgnores == other.coverageIgnores && - pageWidth == other.pageWidth; + pageWidth == other.pageWidth && + overrides == other.overrides && + applyOptimizations == other.applyOptimizations; } @override @@ -108,6 +137,8 @@ class _$DynamiteConfig extends DynamiteConfig { _$hash = $jc(_$hash, analyzerIgnores.hashCode); _$hash = $jc(_$hash, coverageIgnores.hashCode); _$hash = $jc(_$hash, pageWidth.hashCode); + _$hash = $jc(_$hash, overrides.hashCode); + _$hash = $jc(_$hash, applyOptimizations.hashCode); _$hash = $jf(_$hash); return _$hash; } @@ -117,7 +148,9 @@ class _$DynamiteConfig extends DynamiteConfig { return (newBuiltValueToStringHelper(r'DynamiteConfig') ..add('analyzerIgnores', analyzerIgnores) ..add('coverageIgnores', coverageIgnores) - ..add('pageWidth', pageWidth)) + ..add('pageWidth', pageWidth) + ..add('overrides', overrides) + ..add('applyOptimizations', applyOptimizations)) .toString(); } } @@ -137,7 +170,17 @@ class DynamiteConfigBuilder implements Builder _$this._pageWidth; set pageWidth(int? pageWidth) => _$this._pageWidth = pageWidth; - DynamiteConfigBuilder(); + MapBuilder? _overrides; + MapBuilder get overrides => _$this._overrides ??= MapBuilder(); + set overrides(MapBuilder? overrides) => _$this._overrides = overrides; + + bool? _applyOptimizations; + bool? get applyOptimizations => _$this._applyOptimizations; + set applyOptimizations(bool? applyOptimizations) => _$this._applyOptimizations = applyOptimizations; + + DynamiteConfigBuilder() { + DynamiteConfig._defaults(this); + } DynamiteConfigBuilder get _$this { final $v = _$v; @@ -145,6 +188,8 @@ class DynamiteConfigBuilder implements Builder build(final BuildStep buildStep) async { - try { - final inputId = buildStep.inputId; - final outputId = inputId.changeExtension('.dart'); + final inputId = buildStep.inputId; + final outputId = inputId.changeExtension('.dart'); - final emitter = DartEmitter( - orderDirectives: true, - useNullSafetySyntax: true, - ); + final emitter = DartEmitter( + orderDirectives: true, + useNullSafetySyntax: true, + ); + try { final spec = switch (inputId.extension) { '.json' => openapi.serializers.deserializeWith( openapi.OpenAPI.serializer, @@ -62,7 +62,8 @@ class OpenAPIBuilder implements Builder { throw Exception('Only OpenAPI between $minSupportedVersion and $maxSupportedVersion are supported.'); } - final state = State(buildConfig); + final config = buildConfig.configFor(inputId.path); + final state = State(config); // Imports need to be generated after everything else so we know if we need the local part directive, // but they need to be added to the beginning of the output.