Skip to content

Commit

Permalink
Generator - fix headers and required parameters (#239)
Browse files Browse the repository at this point in the history
* Null safety (non stable version) (#219)

* GZip note

* Update faq.md

* CR fixes

* Moved to the faq.md

* HTTP Auth example

* CR fix

* CR fix

* Base url note

Runtime base url note update

Update faq.md

* Packages upgraded (#142)

* Release 3.0.3

* add develop branch to travis

* fix travis badge

* Make code quality improvements in generator.dart (#147)

* Add optionalBody parameter to suppress warnings (#151)

* Add optionalBody parameter to suppress warnings

Fixes #149

* Improve formatting

* Remove redundant _methodWithBody function

Use a single source of truth (the method's optionalBody property)

* Show optional body hint in warning message

* Make optionalBody configurable for all methods

Explicitly set the default value for every method

* Specify type for optionalBody argument

Co-authored-by: Wilko Manger <wilko@pattle.org>

* Fix typo and invalid code sample in documentation (#156)

* Preserve uri current query params in buildUri (#166)

* This allows chopper API methods with generic attributes (#170)

@post(path: URL.DOCUMENT_PRIOR_INFO)
  Future<Response<T>> getPriorInfo<T>(@Body() Params params);

Which is usefull when single API method may respond differently
depending on request parameter values.

Co-authored-by: Aleksandr Malkov <radied@gmail.com>

* Make conversion helpers can be `async` (#175)

#174 
- locally tested

* Dependency update (#178)

Version bumped

Removed Angular / Web examples

With nullability added

Update generator.dart

Dependency cleanup

Update pubspec.yaml

Update pubspec.yaml

* Re-add Angular example and fix travis (#181)

Re add example removed here (https://github.com/lejard-h/chopper/pull/178/files)

Upgrade to Angular 6, but I had to remove jaguar_serializer which is not maintain anymore (last update 1 year ago).

Then use new Dart command to run pub, analyzer and formatter

* Publish package from travis (#182)

* fix

* fix scopes

* allow_failure

* comment override

* Add suport for JsonApi utf8 serialization (#185)

* Add suport for JsonApi utf8 serialization

* Move json api header into a constant

* The Big Public API Documentation update, volume 1. (#189)

* Update converters.md with wording and formatting fixes

* Update the documentation of classes and functions in interceptor.dart

* Update the documentation of classes and functions in base.dart

* Update the documentation of public functions in utils.dart

* Update the documentation of public classes and functions in request.dart

* Update the documentation of public classes and functions in response.dart

* Update the documentation of ConvertRequest, ConvertResponse, and FactoryConverter in annotations.dart

* Fix typos in the documentation in annotations.dart

* Remove TODO from ChopperService.definitionType's documentation

* Add example usage to FactoryConverter's documentation

* Fix accidental typo in ChopperService's class name

* The Big Public API Documentation update, volume 2. (#193)

* Update the documentation of BuiltValueConverter

* Update the documentation and usage guide of BuiltValueConverter

* Update description texts in pubspec.yaml files

* Change homepage tag to documentation in chopper/pubspec.yaml

* Change homepage tag to documentation in chopper_built_value/pubspec.yaml and make it point to its actual documentation page

* Change homepage tag to documentation in chopper_generator/pubspec.yaml

* Change homepage tag to documentation in chopper/example/pubspec.yaml and make it point to the actual documentation

* Fix wording in chopper_generator/README.md

* Fix wording in chopper_built_value/README.md

* Fix HTML escape sequences escaping into markdown and inline docs; Fix code sample syntax errors in some docs

Those pesky escapists.

* Add dynamic version tag to built-value-converter.md

* Fix typo in the package name in the installation section of built-value-converter.md

* Fix typo in built-value-converter.md

* Reorganize and update chopper/README.md

* The Big Public API Documentation Update, volume 3. (#196)

* Rework and update getting-started.md

* Reword parts of the API docs in annotations.dart

* Add description of path resolution behavior in requests.md
This commit addresses issue #195

* Reword parts of the documentations in requests.md

* Reword the error handling description in getting-started.md

* Reword and update most of the documentation in requests.md

* Add missing @s to annotation mentions in getting-started.md

* Remove an unnecessary new line from getting-started.md

* Add further explanation to an example service's create method in getting-started.md

* Update the README of chopper_built_value

* Update the README of chopper_generator

* Update and reword top level README.md and chopper/README.md

* Try to fix text formatting in requests.md

* Fix wording requests.md's form URL encoded section

* Remove unsafe hint on build_runner from getting-started.md

* Implement authenticator (#198)

* Implement authenticator

* Changes for PR

Co-authored-by: Ivan Terekhin <i.terhin@gmail.com>

* Add Flutter Favorite badge (#206)

* feature/updated doc (#214)

* updated doc

* fixed typo

Co-authored-by: dafinrs <dafi@jojonomic.com>

* Feature/support body get (#201)

* Feature/null safety migration (#212)

* Pubspec for ChopperBuiltValue

* Begin resolving null safety dependencies

* Initial change

* Implement null safety on chopper_generator

* Fix comments on PR

* Fixed some comments

* version updates

* fixed issues with versions

* fix comments on chopperClient nullability

* fixed tests

* Fixed issues with nullable client

* Bumped build version to 2.0.0

* updated libs

* made parts not nullable

* Update chopper/README.md

Co-authored-by: Ivan Terekhin <i.terhin@gmail.com>

* Update chopper/README.md

Co-authored-by: Ivan Terekhin <i.terhin@gmail.com>

* Update chopper_generator/pubspec.yaml

Co-authored-by: Ivan Terekhin <i.terhin@gmail.com>

* Fix for null safety in applyHeaders

* More deps upgrade

Co-authored-by: Ivan Terekhin <i.terhin@gmail.com>
Co-authored-by: István Juhos <stewemetal@gmail.com>
Co-authored-by: Uladzimir Paliukhovich <Uladzimir_Paliukhovich@epam.com>
Co-authored-by: Uladzimir_Paliukhovich <Vovanella95@mail.ru>
Co-authored-by: uladzimir_paliukhovich <>

* Add double quotes to Curl print String (#218)

Prints the Curl URL wrapped with double-quotes.
It fixes issues when pasting the resulting log to the command line, where the curl request in some cases would not be closed by the terminal or fail to execute.

* Enable GitHub action (#216)

* github acions with mono_repo

* fail test

* cleanup

* badge

* regenerate

* regenerate

* format

* fix analyzer

* fix analyzer

* fix test

* regenerate

* cleanup badge

* Naming fix

* remove dev chanel

* ignore vscode

* revert readme change

* remove travis

* format

* fix

* fix

* format

* fix tests

Co-authored-by: Ivan Terekhin <i.terhin@gmail.com>

* Add an OPTIONS request type (#215)

* Add an OPTIONS request type

* Null safety fix

Co-authored-by: Ivan Terekhin <i.terhin@gmail.com>

* changelog

* docs: add lejard-h as a contributor (#221)

* docs: update README.md [skip ci]

* docs: create .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* docs: add stewemetal as a contributor (#222)

* docs: update README.md [skip ci]

* docs: create .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Hadrien Lejard <hadrien.lejard@gmail.com>

* docs: add JEuler as a contributor (#223)

* docs: update README.md [skip ci]

* docs: create .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Hadrien Lejard <hadrien.lejard@gmail.com>

* docs: add fryette as a contributor (#224)

* docs: update README.md [skip ci]

* docs: create .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Hadrien Lejard <hadrien.lejard@gmail.com>

* docs: add Vovanella95 as a contributor (#225)

* docs: update README.md [skip ci]

* docs: create .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Hadrien Lejard <hadrien.lejard@gmail.com>

* update Changelog for 4.0.0 release (#220)

* update Changelog

* contributors

* cleanup

* changelog

Co-authored-by: Ivan Terekhin <i.terhin@gmail.com>
Co-authored-by: Juhos István <stewemetal@gmail.com>
Co-authored-by: Louis Matthijssen <louis@u5r.nl>
Co-authored-by: Wilko Manger <wilko@pattle.org>
Co-authored-by: Tamas Balogh <tamas.balogh@bata.dev>
Co-authored-by: Mohammad Omidvar Tehrani <mohammad.omt99@yahoo.com>
Co-authored-by: cpthooch <cpthooch@gmail.com>
Co-authored-by: Aleksandr Malkov <radied@gmail.com>
Co-authored-by: Study-Log <58581613+Study-Log@users.noreply.github.com>
Co-authored-by: Daniel Gomez <danielgomezrico@gmail.com>
Co-authored-by: Graham Smith <graham@wiseman-designs.com>
Co-authored-by: Eugeny Sampir <ysampir@gmail.com>
Co-authored-by: dafi <dafidzeko@gmail.com>
Co-authored-by: dafinrs <dafi@jojonomic.com>
Co-authored-by: Alfredo Bautista <71638694+alfredo-handcash@users.noreply.github.com>
Co-authored-by: Uladzimir Paliukhovich <Uladzimir_Paliukhovich@epam.com>
Co-authored-by: Uladzimir_Paliukhovich <Vovanella95@mail.ru>
Co-authored-by: Alex Queudot <Alqueraf@gmail.com>
Co-authored-by: Shane Farmer <shane@thatch.co>
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix params and headers

* fix

Co-authored-by: Ivan Terekhin <i.terhin@gmail.com>
Co-authored-by: Juhos István <stewemetal@gmail.com>
Co-authored-by: Louis Matthijssen <louis@u5r.nl>
Co-authored-by: Wilko Manger <wilko@pattle.org>
Co-authored-by: Tamas Balogh <tamas.balogh@bata.dev>
Co-authored-by: Mohammad Omidvar Tehrani <mohammad.omt99@yahoo.com>
Co-authored-by: cpthooch <cpthooch@gmail.com>
Co-authored-by: Aleksandr Malkov <radied@gmail.com>
Co-authored-by: Study-Log <58581613+Study-Log@users.noreply.github.com>
Co-authored-by: Daniel Gomez <danielgomezrico@gmail.com>
Co-authored-by: Graham Smith <graham@wiseman-designs.com>
Co-authored-by: Eugeny Sampir <ysampir@gmail.com>
Co-authored-by: dafi <dafidzeko@gmail.com>
Co-authored-by: dafinrs <dafi@jojonomic.com>
Co-authored-by: Alfredo Bautista <71638694+alfredo-handcash@users.noreply.github.com>
Co-authored-by: Uladzimir Paliukhovich <Uladzimir_Paliukhovich@epam.com>
Co-authored-by: Uladzimir_Paliukhovich <Vovanella95@mail.ru>
Co-authored-by: Alex Queudot <Alqueraf@gmail.com>
Co-authored-by: Shane Farmer <shane@thatch.co>
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
  • Loading branch information
21 people committed Apr 10, 2021
1 parent 90b739b commit aa9c58e
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 62 deletions.
5 changes: 4 additions & 1 deletion chopper/example/definition.chopper.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 12 additions & 7 deletions chopper/test/base_test.dart
Expand Up @@ -64,7 +64,7 @@ void main() {
final chopper = buildClient(httpClient);
final service = chopper.getService<HttpTestService>();

final response = await service.getTest('1234');
final response = await service.getTest('1234', dynamicHeader: '');

expect(response.body, equals('get response'));
expect(response.statusCode, equals(200));
Expand Down Expand Up @@ -392,7 +392,7 @@ void main() {

final service = HttpTestService.create(chopper);

await service.getTest('1234');
await service.getTest('1234', dynamicHeader: '');

client.close();
});
Expand Down Expand Up @@ -613,7 +613,7 @@ void main() {
});

final service = HttpTestService.create(chopper);
await service.getTest('1234');
await service.getTest('1234', dynamicHeader: '');

client.close();
chopper.dispose();
Expand All @@ -632,7 +632,7 @@ void main() {
});

final service = HttpTestService.create(chopper);
await service.getTest('1234');
await service.getTest('1234', dynamicHeader: '');

client.close();
chopper.dispose();
Expand All @@ -646,7 +646,7 @@ void main() {
final chopper = buildClient(client);

final service = HttpTestService.create(chopper);
final res = await service.getTest('1234');
final res = await service.getTest('1234', dynamicHeader: '');

expect(res.isSuccessful, isFalse);
expect(res.statusCode, equals(400));
Expand All @@ -665,7 +665,7 @@ void main() {
final chopper = buildClient(client, JsonConverter());

final service = HttpTestService.create(chopper);
final res = await service.getTest('1234');
final res = await service.getTest('1234', dynamicHeader: '');

expect(res.isSuccessful, isFalse);
expect(res.statusCode, equals(400));
Expand Down Expand Up @@ -719,7 +719,12 @@ void main() {
final service = chopper.getService<HttpTestService>();

try {
await service.getTest('1234').timeout(const Duration(seconds: 3));
await service
.getTest(
'1234',
dynamicHeader: '',
)
.timeout(const Duration(seconds: 3));
} catch (e) {
expect(e is TimeoutException, isTrue);
}
Expand Down
2 changes: 1 addition & 1 deletion chopper/test/converter_test.dart
Expand Up @@ -50,7 +50,7 @@ void main() {
final service = HttpTestService.create(chopper);

try {
await service.getTest('1');
await service.getTest('1', dynamicHeader: '');
} catch (e) {
expect(e is Response, isTrue);
expect((e as Response).body is _ConvertedError, isTrue);
Expand Down
30 changes: 24 additions & 6 deletions chopper/test/interceptors_test.dart
Expand Up @@ -36,7 +36,10 @@ void main() {
client: requestClient,
);

await chopper.getService<HttpTestService>().getTest('1234');
await chopper.getService<HttpTestService>().getTest(
'1234',
dynamicHeader: '',
);
});

test('RequestInterceptorFunc', () async {
Expand All @@ -51,7 +54,10 @@ void main() {
client: requestClient,
);

await chopper.getService<HttpTestService>().getTest('1234');
await chopper.getService<HttpTestService>().getTest(
'1234',
dynamicHeader: '',
);
});

test('ResponseInterceptor', () async {
Expand All @@ -63,7 +69,10 @@ void main() {
client: responseClient,
);

await chopper.getService<HttpTestService>().getTest('1234');
await chopper.getService<HttpTestService>().getTest(
'1234',
dynamicHeader: '',
);

expect(ResponseIntercept.intercepted, isA<_Intercepted>());
});
Expand All @@ -84,7 +93,10 @@ void main() {
client: responseClient,
);

await chopper.getService<HttpTestService>().getTest('1234');
await chopper.getService<HttpTestService>().getTest(
'1234',
dynamicHeader: '',
);

expect(intercepted, isA<_Intercepted<dynamic>>());
});
Expand All @@ -105,7 +117,10 @@ void main() {
client: responseClient,
);

await chopper.getService<HttpTestService>().getTest('1234');
await chopper.getService<HttpTestService>().getTest(
'1234',
dynamicHeader: '',
);

expect(intercepted, isA<_Intercepted<String?>>());
});
Expand Down Expand Up @@ -155,7 +170,10 @@ void main() {
client: client,
);

await chopper.getService<HttpTestService>().getTest('1234');
await chopper.getService<HttpTestService>().getTest(
'1234',
dynamicHeader: '',
);
});

final fakeRequest = Request(
Expand Down
17 changes: 13 additions & 4 deletions chopper/test/test_service.chopper.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion chopper/test/test_service.dart
Expand Up @@ -15,7 +15,7 @@ abstract class HttpTestService extends ChopperService {
@Get(path: 'get/{id}')
Future<Response<String>> getTest(
@Path() String id, {
@Header('test') String dynamicHeader = '',
@Header('test') required String dynamicHeader,
});

@Head(path: 'head')
Expand Down
129 changes: 87 additions & 42 deletions chopper_generator/lib/src/generator.dart
Expand Up @@ -132,42 +132,34 @@ class ChopperGenerator extends GeneratorForAnnotation<chopper.ChopperApi> {
return Method((b) {
b.annotations.add(refer('override'));
b.name = m.displayName;
b.returns =
Reference(m.returnType.getDisplayString(withNullability: false));
b.types.addAll(m.typeParameters
.map((t) => Reference(t.getDisplayString(withNullability: false))));
b.requiredParameters.addAll(m.parameters
.where((p) => p.isNotOptional)
.map((p) => Parameter((pb) => pb
..name = p.name
..type = Reference(
p.type.getDisplayString(withNullability: p.type.isNullable)))));

b.optionalParameters.addAll(m.parameters
.where((p) => p.isOptionalPositional)
.map((p) => Parameter((pb) {
pb
..name = p.name
..type = Reference(
p.type.getDisplayString(withNullability: false));

if (p.defaultValueCode != null) {
pb.defaultTo = Code(p.defaultValueCode);
}
})));

// We don't support returning null Type
b.returns = Reference(
m.returnType.getDisplayString(withNullability: false),
);

// And null Typed parameters
b.types.addAll(
m.typeParameters.map(
(t) => Reference(t.getDisplayString(withNullability: false)),
),
);

b.requiredParameters.addAll(
m.parameters
.where((p) => p.isRequiredPositional)
.map(buildRequiredPositionalParam),
);

b.optionalParameters.addAll(
m.parameters.where((p) => p.isNamed).map((p) => Parameter((pb) {
pb
..named = true
..name = p.name
..type = Reference(p.type
.getDisplayString(withNullability: p.type.isNullable));

if (p.defaultValueCode != null) {
pb.defaultTo = Code(p.defaultValueCode);
}
})));
m.parameters
.where((p) => p.isOptionalPositional)
.map(buildOptionalPositionalParam),
);

b.optionalParameters.addAll(
m.parameters.where((p) => p.isNamed).map(buildNamedParam),
);

final blocks = [
url.assignFinal(_urlVar).statement,
Expand Down Expand Up @@ -472,14 +464,20 @@ class ChopperGenerator extends GeneratorForAnnotation<chopper.ChopperApi> {
}

Code? _generateHeaders(MethodElement methodElement, ConstantReader method) {
final headers = {};
final codeBuffer = StringBuffer('')..writeln('{');

// Search for @Header anotation in method parameters
final annotations = _getAnnotations(methodElement, chopper.Header);

annotations.forEach((parameter, ConstantReader annotation) {
final name =
annotation.peek('name')?.stringValue ?? parameter.displayName;
headers[literal(name)] = refer(parameter.displayName);
final paramName = parameter.displayName;
final name = annotation.peek('name')?.stringValue ?? paramName;

if (parameter.type.isNullable) {
codeBuffer.writeln('if ($paramName != null) \'$name\': $paramName,');
} else {
codeBuffer.writeln('\'$name\': $paramName,');
}
});

final headersReader = method.peek('headers');
Expand All @@ -489,16 +487,19 @@ class ChopperGenerator extends GeneratorForAnnotation<chopper.ChopperApi> {

methodAnnotations.forEach((headerName, headerValue) {
if (headerName != null && headerValue != null) {
headers[literal(headerName.toStringValue())] =
literal(headerValue.toStringValue());
codeBuffer.writeln(
'\'${headerName.toStringValue()}\': ${literal(headerValue.toStringValue())},',
);
}
});

if (headers.isEmpty) {
codeBuffer.writeln('};');
final code = codeBuffer.toString();
if (code == '{\n};\n') {
return null;
}

return literalMap(headers).assignFinal(_headersVar).statement;
return Code('final $_headersVar = $code');
}
}

Expand All @@ -519,3 +520,47 @@ String getMethodName(ConstantReader method) =>
extension DartTypeExtension on DartType {
bool get isNullable => nullabilitySuffix != NullabilitySuffix.none;
}

// All positional required params must support nullability
Parameter buildRequiredPositionalParam(ParameterElement p) {
return Parameter(
(pb) => pb
..name = p.name
..type = Reference(
p.type.getDisplayString(withNullability: p.type.isNullable),
),
);
}

// All optional positional params must support nullability
Parameter buildOptionalPositionalParam(ParameterElement p) {
return Parameter((pb) {
pb
..name = p.name
..type = Reference(
p.type.getDisplayString(withNullability: p.type.isNullable),
);

if (p.defaultValueCode != null) {
pb.defaultTo = Code(p.defaultValueCode);
}
});
}

// Named params can be optional or required, they also need to support
// nullability
Parameter buildNamedParam(ParameterElement p) {
return Parameter((pb) {
pb
..named = true
..name = p.name
..required = p.isRequiredNamed
..type = Reference(
p.type.getDisplayString(withNullability: p.type.isNullable),
);

if (p.defaultValueCode != null) {
pb.defaultTo = Code(p.defaultValueCode);
}
});
}

0 comments on commit aa9c58e

Please sign in to comment.