Skip to content

Commit

Permalink
Merge pull request #1324 from nextcloud/refactor/dynamite/reduce-unus…
Browse files Browse the repository at this point in the history
…ed-generated-code

refactor(dynamite): do not generate _parameters map when not needed
  • Loading branch information
Leptopoda authored Dec 20, 2023
2 parents 96b3d06 + 09194e7 commit 862717d
Show file tree
Hide file tree
Showing 41 changed files with 498 additions and 1,119 deletions.
122 changes: 87 additions & 35 deletions packages/dynamite/dynamite/lib/src/builder/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ Iterable<Class> generateClients(
final openapi.OpenAPI spec,
final State state,
) sync* {
if (spec.paths == null || spec.paths!.isEmpty) {
return;
}

final tags = generateTags(spec);
yield buildRootClient(spec, state, tags);

Expand Down Expand Up @@ -191,6 +195,25 @@ Iterable<Method> buildTags(
]..sort(sortRequiredParameters);
final name = toDartName(filterMethodName(operationName, tag ?? ''));

final hasAuthentication = needsAuthCheck(pathEntry, operation, spec, client);
var hasUriParameters = false;
var hasHeaderParameters = false;
for (final parameter in parameters) {
switch (parameter.$in) {
case openapi.ParameterType.path:
case openapi.ParameterType.query:
hasUriParameters = true;
case openapi.ParameterType.header:
hasHeaderParameters = true;
default:
}

// No need to continue searching.
if (hasHeaderParameters && hasUriParameters) {
break;
}
}

var responses = <openapi.Response, List<String>>{};
if (operation.responses != null) {
for (final responseEntry in operation.responses!.entries) {
Expand All @@ -215,18 +238,32 @@ Iterable<Method> buildTags(
.toSet()
.join(',');

code.writeln('''
final _parameters = <String, dynamic>{};
final _headers = <String, String>{${acceptHeader.isNotEmpty ? "'Accept': '$acceptHeader'," : ''}};
Uint8List? _body;
''');
if (hasUriParameters) {
code.writeln('final _parameters = <String, dynamic>{};');
}
if (acceptHeader.isNotEmpty) {
if (hasHeaderParameters || hasAuthentication) {
code.writeln("final _headers = <String, String>{'Accept': '$acceptHeader',};");
} else {
code.writeln("const _headers = <String, String>{'Accept': '$acceptHeader',};");
}
} else if (acceptHeader.isEmpty) {
code.writeln('final _headers = <String, String>{};');
}
if (operation.requestBody != null) {
code.writeln('Uint8List? _body;');
}
// Separate the declarations from the assignments
code.writeln();

buildAuthCheck(
pathEntry,
operation,
spec,
client,
).forEach(code.writeln);
if (hasAuthentication) {
buildAuthCheck(
pathEntry,
operation,
spec,
client,
).forEach(code.writeln);
}

final operationParameters = ListBuilder<Parameter>();
final annotations = operation.deprecated ? refer('Deprecated').call([refer("''")]) : null;
Expand Down Expand Up @@ -315,36 +352,39 @@ Iterable<Method> buildTags(
toDartName(identifierBuilder.toString(), uppercaseFirstCharacter: true),
);

final queryParams = <String>[];
for (final parameter in parameters) {
if (parameter.$in != openapi.ParameterType.query) {
continue;
}
if (!hasUriParameters) {
code.writeln("const _path = '${pathEntry.key}';");
} else {
final queryParams = <String>[];
for (final parameter in parameters) {
if (parameter.$in != openapi.ParameterType.query) {
continue;
}

// Default to a plain parameter without exploding.
queryParams.add(parameter.uriTemplate(withPrefix: false) ?? parameter.pctEncodedName);
}
// Default to a plain parameter without exploding.
queryParams.add(parameter.uriTemplate(withPrefix: false) ?? parameter.pctEncodedName);
}

final pathBuilder = StringBuffer()..write(pathEntry.key);
final pathBuilder = StringBuffer()..write(pathEntry.key);

if (queryParams.isNotEmpty) {
pathBuilder
..write('{?')
..writeAll(queryParams, ',')
..write('}');
}
if (queryParams.isNotEmpty) {
pathBuilder
..write('{?')
..writeAll(queryParams, ',')
..write('}');
}

final path = pathBuilder.toString();
final path = pathBuilder.toString();
// Sanity check the uri at build time.
try {
UriTemplate(path);
} on ParseException catch (e) {
throw Exception('The resulting uri $path is not a valid uri template according to RFC 6570. $e');
}

// Sanity check the uri at build time.
try {
UriTemplate(path);
} on ParseException catch (e) {
throw Exception('The resulting uri $path is not a valid uri template according to RFC 6570. $e');
code.writeln("final _path = UriTemplate('$path').expand(_parameters);");
}

code.writeln("final _path = UriTemplate('$path').expand(_parameters);");

if (dataType != null) {
returnDataType = dataType.name;
}
Expand All @@ -358,7 +398,7 @@ Iterable<Method> buildTags(
'$httpMethod',
_path,
_headers,
_body,
${operation.requestBody != null ? '_body' : 'null'},
''');

if (responses.values.isNotEmpty) {
Expand Down Expand Up @@ -466,6 +506,18 @@ String buildParameterSerialization(
return buffer.toString();
}

bool needsAuthCheck(
final MapEntry<String, openapi.PathItem> pathEntry,
final openapi.Operation operation,
final openapi.OpenAPI spec,
final String client,
) {
final security = operation.security ?? spec.security ?? BuiltList();
final securityRequirements = security.where((final requirement) => requirement.isNotEmpty);

return securityRequirements.isNotEmpty;
}

Iterable<String> buildAuthCheck(
final MapEntry<String, openapi.PathItem> pathEntry,
final openapi.Operation operation,
Expand Down
20 changes: 0 additions & 20 deletions packages/dynamite/dynamite_end_to_end_test/lib/all_of.openapi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,10 @@ import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
import 'package:dynamite_runtime/built_value.dart';
import 'package:dynamite_runtime/http_client.dart';
import 'package:meta/meta.dart';

part 'all_of.openapi.g.dart';

class Client extends DynamiteClient {
Client(
super.baseURL, {
super.baseHeaders,
super.userAgent,
super.httpClient,
super.cookieJar,
});

Client.fromClient(DynamiteClient client)
: super(
client.baseURL,
baseHeaders: client.baseHeaders,
httpClient: client.httpClient,
cookieJar: client.cookieJar,
authentications: client.authentications,
);
}

@BuiltValue(instantiable: false)
abstract interface class $ObjectAllOf_0Interface {
@BuiltValueField(wireName: 'attribute1-allOf')
Expand Down
20 changes: 0 additions & 20 deletions packages/dynamite/dynamite_end_to_end_test/lib/any_of.openapi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,11 @@ import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
import 'package:dynamite_runtime/built_value.dart';
import 'package:dynamite_runtime/http_client.dart';
import 'package:dynamite_runtime/utils.dart' as dynamite_utils;
import 'package:meta/meta.dart';

part 'any_of.openapi.g.dart';

class Client extends DynamiteClient {
Client(
super.baseURL, {
super.baseHeaders,
super.userAgent,
super.httpClient,
super.cookieJar,
});

Client.fromClient(DynamiteClient client)
: super(
client.baseURL,
baseHeaders: client.baseHeaders,
httpClient: client.httpClient,
cookieJar: client.cookieJar,
authentications: client.authentications,
);
}

typedef OneObjectAnyOf = OneObjectAnyOf0;

typedef OneValueAnyOf = String;
Expand Down
20 changes: 0 additions & 20 deletions packages/dynamite/dynamite_end_to_end_test/lib/enum.openapi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,10 @@ import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
import 'package:dynamite_runtime/built_value.dart';
import 'package:dynamite_runtime/http_client.dart';
import 'package:meta/meta.dart';

part 'enum.openapi.g.dart';

class Client extends DynamiteClient {
Client(
super.baseURL, {
super.baseHeaders,
super.userAgent,
super.httpClient,
super.cookieJar,
});

Client.fromClient(DynamiteClient client)
: super(
client.baseURL,
baseHeaders: client.baseHeaders,
httpClient: client.httpClient,
cookieJar: client.cookieJar,
authentications: client.authentications,
);
}

class EnumString extends EnumClass {
const EnumString._(super.name);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import 'package:dynamite_runtime/built_value.dart';
import 'package:dynamite_runtime/http_client.dart';
import 'package:meta/meta.dart';
import 'package:universal_io/io.dart';
import 'package:uri/uri.dart';

part 'headers.openapi.g.dart';

Expand Down Expand Up @@ -61,17 +60,15 @@ class Client extends DynamiteClient {
/// * [$get] for an operation that returns a [DynamiteResponse] with a stable API.
@experimental
DynamiteRawResponse<void, GetHeaders> $getRaw() {
final _parameters = <String, dynamic>{};
final _headers = <String, String>{};
Uint8List? _body;

final _path = UriTemplate('/').expand(_parameters);
const _path = '/';
return DynamiteRawResponse<void, GetHeaders>(
response: executeRequest(
'get',
_path,
_headers,
_body,
null,
const {200},
),
bodyType: null,
Expand Down Expand Up @@ -106,17 +103,15 @@ class Client extends DynamiteClient {
/// * [withContentOperationId] for an operation that returns a [DynamiteResponse] with a stable API.
@experimental
DynamiteRawResponse<void, WithContentOperationIdHeaders> withContentOperationIdRaw() {
final _parameters = <String, dynamic>{};
final _headers = <String, String>{};
Uint8List? _body;

final _path = UriTemplate('/with_content/operation_id').expand(_parameters);
const _path = '/with_content/operation_id';
return DynamiteRawResponse<void, WithContentOperationIdHeaders>(
response: executeRequest(
'get',
_path,
_headers,
_body,
null,
const {200},
),
bodyType: null,
Expand Down Expand Up @@ -151,19 +146,17 @@ class Client extends DynamiteClient {
/// * [getWithContent] for an operation that returns a [DynamiteResponse] with a stable API.
@experimental
DynamiteRawResponse<Uint8List, GetWithContentHeaders> getWithContentRaw() {
final _parameters = <String, dynamic>{};
final _headers = <String, String>{
const _headers = <String, String>{
'Accept': 'application/octet-stream',
};
Uint8List? _body;

final _path = UriTemplate('/with_content').expand(_parameters);
const _path = '/with_content';
return DynamiteRawResponse<Uint8List, GetWithContentHeaders>(
response: executeRequest(
'get',
_path,
_headers,
_body,
null,
const {200},
),
bodyType: const FullType(Uint8List),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,10 @@ import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
import 'package:dynamite_runtime/built_value.dart';
import 'package:dynamite_runtime/http_client.dart';
import 'package:meta/meta.dart';

part 'interfaces.openapi.g.dart';

class Client extends DynamiteClient {
Client(
super.baseURL, {
super.baseHeaders,
super.userAgent,
super.httpClient,
super.cookieJar,
});

Client.fromClient(DynamiteClient client)
: super(
client.baseURL,
baseHeaders: client.baseHeaders,
httpClient: client.httpClient,
cookieJar: client.cookieJar,
authentications: client.authentications,
);
}

@BuiltValue(instantiable: false)
abstract interface class $BaseInterface {
String? get attribute;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,11 @@ import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
import 'package:dynamite_runtime/built_value.dart';
import 'package:dynamite_runtime/http_client.dart';
import 'package:dynamite_runtime/utils.dart' as dynamite_utils;
import 'package:meta/meta.dart';

part 'nested_ofs.openapi.g.dart';

class Client extends DynamiteClient {
Client(
super.baseURL, {
super.baseHeaders,
super.userAgent,
super.httpClient,
super.cookieJar,
});

Client.fromClient(DynamiteClient client)
: super(
client.baseURL,
baseHeaders: client.baseHeaders,
httpClient: client.httpClient,
cookieJar: client.cookieJar,
authentications: client.authentications,
);
}

@BuiltValue(instantiable: false)
abstract interface class $BaseAllOf_1Interface {
@BuiltValueField(wireName: 'attribute-allOf')
Expand Down
Loading

0 comments on commit 862717d

Please sign in to comment.