Skip to content

Commit 985de8b

Browse files
committed
(WIP) FMT, fix up remaining tests for Generator Arguments. TODO: Tweak the classes from annotations to have the toMap call, Look into why inline schema name mappings failing to produce first entry
1 parent 0f833d7 commit 985de8b

File tree

14 files changed

+400
-251
lines changed

14 files changed

+400
-251
lines changed

.github/workflows/code_quality.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,29 @@ on:
1111
workflow_dispatch:
1212

1313
jobs:
14+
ci:
15+
name: Dart CI Checks
16+
runs-on: ubuntu-latest
17+
strategy:
18+
fail-fast: false
19+
matrix:
20+
work_dir: [openapi-generator, openapi-generator-annotations]
21+
steps:
22+
- name: Checkout
23+
uses: actions/checkout@v3
24+
- name: Setup Dart
25+
uses: dart-lang/[email protected]
26+
with:
27+
sdk: stable
28+
- name: Install Dependencies
29+
run: dart pub get
30+
- name: Validate formatting
31+
run: dart format --set-exit-if-changed
32+
- name: Run analyzer
33+
run: dart analyze
34+
- name: Run tests
35+
run: dart test
36+
1437
build:
1538
name: Build example project 🛠️
1639
runs-on: ubuntu-latest

openapi-generator-annotations/example/example.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,5 @@ import 'package:openapi_generator_annotations/openapi_generator_annotations.dart
77
generatorName: Generator.dio,
88
outputDirectory: 'api/petstore_api',
99
// useNextGen: true,
10-
cachePath: 'something'
11-
)
10+
cachePath: 'something')
1211
class Example extends OpenapiGeneratorConfig {}

openapi-generator-annotations/lib/src/openapi_generator_annotations_base.dart

Lines changed: 121 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ class Openapi {
5454
/// --reserved-words-mappings
5555
final Map<String, String>? reservedWordsMappings;
5656

57-
5857
/// Tells openapi-generator to always run during the build process
5958
/// if set to false (the default), openapi-generator will skip processing if the [outputDirectory] already exists
6059
final bool? alwaysRun;
@@ -105,27 +104,29 @@ class Openapi {
105104
/// For use with [useNextGen].
106105
final String? cachePath;
107106

108-
const Openapi(
109-
{this.additionalProperties,
110-
@deprecated
111-
this.overwriteExistingFiles,
112-
this.skipSpecValidation = false,
113-
required this.inputSpecFile,
114-
this.templateDirectory,
115-
required this.generatorName,
116-
this.outputDirectory,
117-
this.typeMappings,
118-
this.importMappings,
119-
this.reservedWordsMappings,
120-
this.inlineSchemaNameMappings,
121-
// this.inlineSchemaOptions,
122-
this.apiPackage,
123-
this.fetchDependencies = true,
124-
this.runSourceGenOnOutput = true,
125-
@deprecated
126-
this.alwaysRun = false,
127-
this.cachePath,
128-
this.useNextGen = false,}): assert(cachePath != null && !useNextGen, 'useNextGen should be set when providing cachePath');
107+
const Openapi({
108+
this.additionalProperties,
109+
@deprecated this.overwriteExistingFiles,
110+
this.skipSpecValidation = false,
111+
required this.inputSpecFile,
112+
this.templateDirectory,
113+
required this.generatorName,
114+
this.outputDirectory,
115+
this.typeMappings,
116+
this.importMappings,
117+
this.reservedWordsMappings,
118+
this.inlineSchemaNameMappings,
119+
// this.inlineSchemaOptions,
120+
this.apiPackage,
121+
this.fetchDependencies = true,
122+
this.runSourceGenOnOutput = true,
123+
@deprecated this.alwaysRun = false,
124+
this.cachePath,
125+
this.useNextGen = false,
126+
});
127+
// TODO: Enable assertion error
128+
// : assert(cachePath != null && !useNextGen,
129+
// 'useNextGen should be set when providing cachePath');
129130
}
130131

131132
class AdditionalProperties {
@@ -186,22 +187,43 @@ class AdditionalProperties {
186187
/// an error if the discriminator is missing.
187188
final bool legacyDiscriminatorBehavior;
188189

189-
const AdditionalProperties(
190-
{this.allowUnicodeIdentifiers = false,
191-
this.ensureUniqueParams = true,
192-
this.useEnumExtension = false,
193-
this.prependFormOrBodyParameters = false,
194-
this.pubAuthor,
195-
this.pubAuthorEmail,
196-
this.pubDescription,
197-
this.pubHomepage,
198-
this.legacyDiscriminatorBehavior = true,
199-
this.pubName,
200-
this.pubVersion,
201-
this.sortModelPropertiesByRequiredFlag = true,
202-
this.sortParamsByRequiredFlag = true,
203-
this.sourceFolder,
204-
this.wrapper = Wrapper.none});
190+
const AdditionalProperties({
191+
this.allowUnicodeIdentifiers = false,
192+
this.ensureUniqueParams = true,
193+
this.useEnumExtension = false,
194+
this.prependFormOrBodyParameters = false,
195+
this.pubAuthor,
196+
this.pubAuthorEmail,
197+
this.pubDescription,
198+
this.pubHomepage,
199+
this.legacyDiscriminatorBehavior = true,
200+
this.pubName,
201+
this.pubVersion,
202+
this.sortModelPropertiesByRequiredFlag = true,
203+
this.sortParamsByRequiredFlag = true,
204+
this.sourceFolder,
205+
this.wrapper = Wrapper.none,
206+
});
207+
208+
/// Produces an [AdditionalProperties] object from the [ConstantReader] [map].
209+
AdditionalProperties.fromMap(Map<String, dynamic> map)
210+
: this(
211+
allowUnicodeIdentifiers: map['allowUnicodeIdentifiers'] ?? false,
212+
ensureUniqueParams: map['ensureUniqueParams'] ?? true,
213+
useEnumExtension: map['useEnumExtension'] ?? true,
214+
prependFormOrBodyParameters: map['prependFormOrBodyParameters'] ?? false,
215+
pubAuthor: map['pubAuthor'],
216+
pubAuthorEmail: map['pubAuthorEmail'],
217+
pubDescription: map['pubDescription'],
218+
pubHomepage: map['pubHomepage'],
219+
pubName: map['pubName'],
220+
pubVersion: map['pubVersion'],
221+
legacyDiscriminatorBehavior: map['legacyDiscriminatorBehavior'] ?? true,
222+
sortModelPropertiesByRequiredFlag: map['sortModelPropertiesByRequiredFlag'] ?? true,
223+
sortParamsByRequiredFlag: map['sortParamsByRequiredFlag'] ?? true,
224+
sourceFolder: map['sourceFolder'],
225+
wrapper: EnumTransformer.wrapper(map['wrapper']),
226+
);
205227
}
206228

207229
/// Allows you to customize how inline schemas are handled or named
@@ -216,10 +238,10 @@ class InlineSchemaOptions {
216238
final bool skipSchemaReuse;
217239

218240
/// will restore the 6.x (or below) behaviour to refactor allOf inline schemas
219-
///into $ref. (v7.0.0 will skip the refactoring of these allOf inline schmeas by default)
241+
///into $ref. (v7.0.0 will skip the refactoring of these allOf inline schemas by default)
220242
final bool refactorAllofInlineSchemas;
221243

222-
/// Email address of the author in generated pubspec
244+
/// Email address of the author in generated pubspec
223245
final bool resolveInlineEnums;
224246

225247
const InlineSchemaOptions(
@@ -228,6 +250,16 @@ class InlineSchemaOptions {
228250
this.skipSchemaReuse = true,
229251
this.refactorAllofInlineSchemas = true,
230252
this.resolveInlineEnums = true});
253+
254+
/// Produces an [InlineSchemaOptions] that is easily consumable from the [ConstantReader].
255+
InlineSchemaOptions.fromMap(Map<String, dynamic> map)
256+
: this(
257+
arrayItemSuffix: map['arrayItemSuffix'],
258+
mapItemSuffix: map['mapItemSuffix'],
259+
skipSchemaReuse: map['skipSchemaReuse'] ?? true,
260+
refactorAllofInlineSchemas: map['refactorAllofInlineSchemas'] ?? true,
261+
resolveInlineEnums: map['resolveInlineEnums'] ?? true,
262+
);
231263
}
232264

233265
class DioProperties extends AdditionalProperties {
@@ -270,6 +302,12 @@ class DioProperties extends AdditionalProperties {
270302
sortParamsByRequiredFlag: sortParamsByRequiredFlag,
271303
sourceFolder: sourceFolder,
272304
useEnumExtension: useEnumExtension);
305+
306+
DioProperties.fromMap(Map<String, dynamic> map)
307+
: dateLibrary = map['dateLibrary'],
308+
nullableFields = map['nullableFields'] as bool?,
309+
serializationLibrary = map['serializationLibrary'],
310+
super.fromMap(map);
273311
}
274312

275313
class DioAltProperties extends AdditionalProperties {
@@ -326,6 +364,14 @@ class DioAltProperties extends AdditionalProperties {
326364
sortParamsByRequiredFlag: sortParamsByRequiredFlag,
327365
sourceFolder: sourceFolder,
328366
useEnumExtension: useEnumExtension);
367+
368+
DioAltProperties.fromMap(Map<String, dynamic> map)
369+
: nullSafe = map['nullSafe'] as bool?,
370+
nullSafeArrayDefault = map['nullSafeArrayDefault'] as bool?,
371+
listAnyOf = map['listAnyOf'] as bool?,
372+
pubspecDependencies = map['pubspecDependencies'],
373+
pubspecDevDependencies = map['pubspecDevDependencies'],
374+
super.fromMap(map);
329375
}
330376

331377
enum DioDateLibrary {
@@ -341,6 +387,7 @@ enum DioSerializationLibrary { built_value, json_serializable }
341387

342388
enum SerializationFormat { JSON, PROTO }
343389

390+
344391
/// The name of the generator to use
345392
enum Generator {
346393
/// This generator uses the default http package that comes with dart
@@ -361,4 +408,38 @@ enum Generator {
361408
dioAlt,
362409
}
363410

411+
// TODO: Upon release of NextGen as default migrate to sdk 2.17 for enhanced enums
412+
// remove this work around.
413+
/// Transforms the enums used with the [Openapi] annotation.
414+
class EnumTransformer {
415+
/// Converts the given [name] to the matching [Generator] name.
416+
///
417+
/// Defaults to [Generator.dart];
418+
static Generator generator(String? name) {
419+
print(name);
420+
switch(name) {
421+
case 'dio':
422+
return Generator.dio;
423+
case 'dioAlt':
424+
return Generator.dioAlt;
425+
default:
426+
return Generator.dart;
427+
}
428+
}
429+
430+
/// Converts the given [name] to the matching [Wrapper] name.
431+
///
432+
/// Defaults to [Wrapper.none];
433+
static Wrapper wrapper(String? name) {
434+
switch(name) {
435+
case 'fvm':
436+
return Wrapper.fvm;
437+
case 'flutterw':
438+
return Wrapper.flutterw;
439+
default:
440+
return Wrapper.none;
441+
}
442+
}
443+
}
444+
364445
enum Wrapper { fvm, flutterw, none }

openapi-generator-annotations/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ environment:
88
sdk: '>=2.12.0 <3.0.0'
99

1010
dev_dependencies:
11-
pedantic:
1211
test:
12+
source_gen_test: ^1.0.6

openapi-generator-annotations/test/openapi_generator_annotations_test.dart

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,19 @@ import 'package:test/test.dart';
33

44
void main() {
55
group('OpenApi', () {
6-
group('NextGen', (){
7-
8-
test('Sets cachePath',(){
9-
final api =Openapi(inputSpecFile: '', generatorName: Generator.dart, cachePath: 'somePath');
6+
group('NextGen', () {
7+
test('Sets cachePath', () {
8+
final api = Openapi(
9+
inputSpecFile: '',
10+
generatorName: Generator.dart,
11+
cachePath: 'somePath');
1012
expect(api.cachePath, 'somePath');
1113
});
12-
test('Sets useNextGenFlag',(){
13-
final api =Openapi(inputSpecFile: '', generatorName: Generator.dart, useNextGen: true);
14+
test('Sets useNextGenFlag', () {
15+
final api = Openapi(
16+
inputSpecFile: '', generatorName: Generator.dart, useNextGen: true);
1417
expect(api.useNextGen, isTrue);
15-
});
18+
});
1619
});
1720
});
1821
}

openapi-generator/lib/src/extensions/type_methods.dart

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import 'dart:mirrors';
22

3-
import 'package:analyzer/dart/ast/ast.dart';
4-
import 'package:analyzer/dart/constant/value.dart';
53
import 'package:analyzer/dart/element/type.dart';
4+
import 'package:openapi_generator/src/utils.dart';
5+
import 'package:openapi_generator_annotations/openapi_generator_annotations.dart';
66
import 'package:source_gen/source_gen.dart' show ConstantReader, TypeChecker;
77

88
/// Extension adding the type methods to `ConstantReader`.
@@ -81,30 +81,47 @@ extension ReadProperty on ConstantReader {
8181
return defaultValue;
8282
}
8383

84-
// TODO: This may be way too naive
85-
if (defaultValue is Map<String, DartObject>) {
86-
return v.revive().namedArguments as T;
84+
if (defaultValue is AdditionalProperties ||
85+
defaultValue is InlineSchemaOptions) {
86+
final mapping = v
87+
.revive()
88+
.namedArguments
89+
.map((key, value) => MapEntry(key, convertToPropertyValue(value)));
90+
if (defaultValue is AdditionalProperties) {
91+
if (defaultValue is DioProperties) {
92+
return DioProperties.fromMap(mapping) as T;
93+
} else if (defaultValue is DioAltProperties) {
94+
return DioAltProperties.fromMap(mapping) as T;
95+
} else {
96+
return AdditionalProperties.fromMap(mapping) as T;
97+
}
98+
} else {
99+
return InlineSchemaOptions.fromMap(mapping) as T;
100+
}
87101
}
88102

89-
switch (T) {
90-
case Map:
91-
return v.mapValue as T;
92-
case bool:
93-
return v.boolValue as T;
94-
case int:
95-
return v.intValue as T;
96-
case List:
97-
return v.listValue as T;
98-
case double:
99-
return v.doubleValue as T;
100-
case String:
101-
return v.stringValue as T;
102-
case Set:
103-
return v.setValue as T;
104-
case Literal:
105-
return v.literalValue as T;
106-
default:
107-
return defaultValue;
103+
if (isA(v, Map)) {
104+
return v.mapValue.map((key, value) => MapEntry(
105+
convertToPropertyValue(key!), convertToPropertyValue(value!))) as T;
106+
} else if (isA(v, bool)) {
107+
return v.boolValue as T;
108+
} else if (isA(v, double)) {
109+
return v.doubleValue as T;
110+
} else if (isA(v, int)) {
111+
return v.intValue as T;
112+
} else if (isA(v, String)) {
113+
return v.stringValue as T;
114+
} else if (isA(v, Set)) {
115+
return v.setValue as T;
116+
} else if (isA(v, List)) {
117+
return v.listValue as T;
118+
} else if (isA(v, Enum)) {
119+
return v.enumValue();
120+
} else {
121+
return defaultValue;
108122
}
109123
}
110124
}
125+
126+
bool isA(ConstantReader? v, Type t) =>
127+
v?.instanceOf(TypeChecker.fromRuntime(t)) ?? false;

0 commit comments

Comments
 (0)