Skip to content

Commit 0f833d7

Browse files
committed
(WIP) Large refactor to get things moving in a nicer way. Adds ~80 tests.
1 parent a17d7bb commit 0f833d7

24 files changed

+1118
-401
lines changed

openapi-generator-annotations/example/example.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,8 @@ import 'package:openapi_generator_annotations/openapi_generator_annotations.dart
55
AdditionalProperties(pubName: 'petstore_api', pubAuthor: 'Johnny dep'),
66
inputSpecFile: 'example/openapi-spec.yaml',
77
generatorName: Generator.dio,
8-
outputDirectory: 'api/petstore_api')
8+
outputDirectory: 'api/petstore_api',
9+
// useNextGen: true,
10+
cachePath: 'something'
11+
)
912
class Example extends OpenapiGeneratorConfig {}

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

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

57+
5758
/// Tells openapi-generator to always run during the build process
5859
/// if set to false (the default), openapi-generator will skip processing if the [outputDirectory] already exists
5960
final bool? alwaysRun;
@@ -94,8 +95,19 @@ class Openapi {
9495
/// e.g {'inline_object_2': 'SomethingMapped'}
9596
final Map<String, String>? inlineSchemaNameMappings;
9697

98+
/// Use the next generation of the generator.
99+
///
100+
/// Default: false
101+
final bool useNextGen;
102+
103+
/// The path where to store the cached copy of the specification.
104+
///
105+
/// For use with [useNextGen].
106+
final String? cachePath;
107+
97108
const Openapi(
98109
{this.additionalProperties,
110+
@deprecated
99111
this.overwriteExistingFiles,
100112
this.skipSpecValidation = false,
101113
required this.inputSpecFile,
@@ -110,7 +122,10 @@ class Openapi {
110122
this.apiPackage,
111123
this.fetchDependencies = true,
112124
this.runSourceGenOnOutput = true,
113-
this.alwaysRun = false});
125+
@deprecated
126+
this.alwaysRun = false,
127+
this.cachePath,
128+
this.useNextGen = false,}): assert(cachePath != null && !useNextGen, 'useNextGen should be set when providing cachePath');
114129
}
115130

116131
class AdditionalProperties {
Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1+
import 'package:openapi_generator_annotations/src/openapi_generator_annotations_base.dart';
12
import 'package:test/test.dart';
23

34
void main() {
4-
group('A group of tests', () {
5-
// Awesome awesome;
6-
//
7-
// setUp(() {
8-
// awesome = Awesome();
9-
// });
10-
//
11-
// test('First Test', () {
12-
// expect(awesome.isAwesome, isTrue);
13-
// });
5+
group('OpenApi', () {
6+
group('NextGen', (){
7+
8+
test('Sets cachePath',(){
9+
final api =Openapi(inputSpecFile: '', generatorName: Generator.dart, cachePath: 'somePath');
10+
expect(api.cachePath, 'somePath');
11+
});
12+
test('Sets useNextGenFlag',(){
13+
final api =Openapi(inputSpecFile: '', generatorName: Generator.dart, useNextGen: true);
14+
expect(api.useNextGen, isTrue);
15+
});
16+
});
1417
});
1518
}

openapi-generator/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,6 @@ Temporary Items
166166
.apdisk
167167
.idea/
168168
example/.dart_tool
169+
170+
# Generated test output
171+
test/specs/test-cached.json
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import 'dart:async';
2+
import 'dart:io';
3+
4+
import 'package:openapi_generator_annotations/openapi_generator_annotations.dart';
5+
import 'package:yaml/yaml.dart';
6+
7+
/// Determines whether a project has a dependency on the Flutter sdk.
8+
///
9+
/// If a wrapper annotation is provided that is not null or [Wrapper.none] and
10+
/// is one of [Wrapper.flutterw] or [Wrapper.fvm] it is safe to assume the project
11+
/// requires the Flutter sdk.
12+
///
13+
/// As a fallback we check the pubspec at the root of the current directory, which
14+
/// will be where the build_runner command will have been called from, and check
15+
/// the Pubspec's dependency list for the 'flutter' key.
16+
///
17+
/// Note: This has support for providing a custom path to a pubspec but there isn't
18+
/// any current implementation to receive it via the generator itself.
19+
FutureOr<bool> checkPubspecAndWrapperForFlutterSupport(
20+
{Wrapper? wrapper = Wrapper.none, String? providedPubspecPath}) async {
21+
if ([Wrapper.flutterw, Wrapper.fvm].contains(wrapper)) {
22+
return true;
23+
} else {
24+
// Use the path provided or default the directory the command was called from.
25+
final pubspecPath = providedPubspecPath ??
26+
'${Directory.current.path}${Platform.pathSeparator}pubspec.yaml';
27+
28+
final pubspecFile = File(pubspecPath);
29+
30+
if (!pubspecFile.existsSync()) {
31+
return Future.error('Pubspec doesn\'t exist at path: $pubspecPath');
32+
}
33+
34+
final contents = await pubspecFile.readAsString();
35+
if (contents.isEmpty) {
36+
return Future.error('Invalid pubspec.yaml');
37+
}
38+
39+
final pubspec = loadYaml(contents) as YamlMap;
40+
41+
return pubspec.containsKey('dependencies') &&
42+
(pubspec.nodes['dependencies'] as YamlMap).containsKey('flutter');
43+
}
44+
}

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import 'dart:mirrors';
22

3+
import 'package:analyzer/dart/ast/ast.dart';
4+
import 'package:analyzer/dart/constant/value.dart';
35
import 'package:analyzer/dart/element/type.dart';
46
import 'package:source_gen/source_gen.dart' show ConstantReader, TypeChecker;
57

@@ -71,3 +73,38 @@ extension TypeMethods on ConstantReader {
7173
return values[enumIndex];
7274
}
7375
}
76+
77+
extension ReadProperty on ConstantReader {
78+
T readPropertyOrDefault<T>(String name, T defaultValue) {
79+
final v = peek(name);
80+
if (v == null) {
81+
return defaultValue;
82+
}
83+
84+
// TODO: This may be way too naive
85+
if (defaultValue is Map<String, DartObject>) {
86+
return v.revive().namedArguments as T;
87+
}
88+
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;
108+
}
109+
}
110+
}

openapi-generator/lib/src/gen_on_spec_changes.dart

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import 'dart:io';
66
import 'package:yaml/yaml.dart';
77

88
// .json
9-
final jsonRegex = RegExp(r'.*.json$');
9+
final jsonRegex = RegExp(r'^.*.json$');
1010
// .yml & .yaml
11-
final yamlRegex = RegExp(r'.*(.ya?ml)$');
11+
final yamlRegex = RegExp(r'^.*(.ya?ml)$');
1212

1313
final _supportedRegexes = [jsonRegex, yamlRegex];
1414

@@ -21,12 +21,14 @@ final _supportedRegexes = [jsonRegex, yamlRegex];
2121
/// - yml
2222
///
2323
/// It also throws an error when the specification doesn't exist on disk.
24+
///
25+
/// WARNING: THIS DOESN'T VALIDATE THE SPECIFICATION CONTENT
2426
FutureOr<Map<String, dynamic>> loadSpec(
2527
{required String specPath, bool isCached = false}) async {
2628
// If the spec file doesn't match any of the currently supported spec formats
2729
// reject the request.
2830
if (!_supportedRegexes.any((fileEnding) => fileEnding.hasMatch(specPath))) {
29-
return Future.error('Invalid spec format');
31+
return Future.error('Invalid spec file format');
3032
}
3133

3234
final file = File(specPath);
@@ -210,9 +212,29 @@ List<dynamic> convertYamlListToDartList({required YamlList yamlList}) {
210212

211213
/// Caches the updated [spec] to disk for use in future comparisons.
212214
///
213-
/// Caches the [spec] to the given [outputDirectory]. By default this will be likely
214-
/// be the .dart_tool or build directory.
215+
/// Caches the [spec] to the given [outputLocation]. By default this will be likely
216+
/// be the .dart_tool/openapi-generator-cache.json
215217
Future<void> cacheSpec({
216-
required String outputDirectory,
218+
required String outputLocation,
217219
required Map<String, dynamic> spec,
218-
}) async {}
220+
}) async {
221+
final outputPath = outputLocation;
222+
final outputFile = File(outputPath);
223+
if (outputFile.existsSync()) {
224+
log('Found cached asset updating');
225+
} else {
226+
log('No previous openapi-generated cache found. Creating cache');
227+
}
228+
229+
return await outputFile.writeAsString(jsonEncode(spec)).then(
230+
(_) => log('Successfully wrote cache.'),
231+
onError: (e, st) {
232+
log(
233+
'Failed to write cache',
234+
error: e,
235+
stackTrace: st,
236+
);
237+
return Future.error('Failed to write cache');
238+
},
239+
);
240+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import 'package:openapi_generator_annotations/openapi_generator_annotations.dart';
2+
3+
/// Creates a representation of a cli request for Flutter or Dart.
4+
class Command {
5+
final String _executable;
6+
final List<String> _arguments;
7+
8+
String get executable => _executable;
9+
10+
List<String> get arguments => _arguments;
11+
12+
Command._(this._executable, this._arguments);
13+
14+
/// Provides an in memory representation of the Dart of Flutter cli command.
15+
///
16+
/// If [executable] is the Dart executable or the [wrapper] is [Wrapper.none]
17+
/// it provides the raw executable. Otherwise it wraps it in the appropriate
18+
/// wrapper, flutterw and fvm respectively.
19+
Command({
20+
Wrapper wrapper = Wrapper.none,
21+
required String executable,
22+
required List<String> arguments,
23+
}) : this._(
24+
executable == 'dart' || wrapper == Wrapper.none
25+
? executable
26+
: wrapper == Wrapper.flutterw
27+
? './flutterw'
28+
: 'fvm',
29+
[if (wrapper != Wrapper.none) executable, ...arguments],
30+
);
31+
}

0 commit comments

Comments
 (0)