Skip to content
This repository was archived by the owner on Sep 16, 2022. It is now read-only.

Commit b81ad86

Browse files
matanlureyalorenzen
authored andcommitted
feat(Compiler): Support MutliToken and *Token<T> in initReflector().
See #782 for limitations of this CL. PiperOrigin-RevId: 182118212
1 parent 2685a5d commit b81ad86

File tree

3 files changed

+101
-2
lines changed

3 files changed

+101
-2
lines changed

angular_compiler/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
* Require `code_builder ^3.0.0`.
1010

11+
* `ReflectorEmitter` now supports `MultiToken` and generic-typed tokens, with
12+
some known limitations. See https://github.com/dart-lang/angular/issues/782.
13+
1114
## 0.4.0-alpha+3
1215

1316
* Added support for recognizing the `MultiToken` type.

angular_compiler/lib/src/emitter/reflector.dart

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'package:build/build.dart';
33

44
import '../analyzer/di/dependencies.dart';
55
import '../analyzer/di/tokens.dart';
6+
import '../analyzer/link.dart';
67
import '../analyzer/reflector.dart';
78

89
/// Generates `.dart` source code given a [ReflectableOutput].
@@ -244,7 +245,23 @@ class ReflectableEmitter {
244245
return 'const _ngRef.Inject(${token.literal})';
245246
}
246247
if (token is OpaqueTokenElement) {
247-
final expression = 'const _ngRef.OpaqueToken(r\'${token.identifier}\')';
248+
// TODO(matanl): Make this more solid.
249+
//
250+
// Ideally we should be using code_builder for this entire class, as it
251+
// would handle import resolution, etc, and make the code more future
252+
// proof.
253+
//
254+
// As-is, this will breakdown if the generic type of an OpaqueToken is
255+
// imported with a prefix, for example:
256+
//
257+
// const fooToken = const OpaqueToken<foo.Foo>('fooToken');
258+
//
259+
// Since this feature is still WIP, this is acceptable, but it should be
260+
// fixed 5.0-beta: https://github.com/dart-lang/angular/issues/782.
261+
final classType = token.isMultiToken ? 'MultiToken' : 'OpaqueToken';
262+
final genericTypeIfAny = _typesAsString([token.typeUrl]);
263+
final expression =
264+
'const _ngRef.$classType$genericTypeIfAny(r\'${token.identifier}\')';
248265
return 'const _ngRef.Inject($expression)';
249266
}
250267
if (token is TypeTokenElement) {
@@ -254,4 +271,11 @@ class ReflectableEmitter {
254271
}
255272
throw new UnsupportedError('Invalid token type: $token.');
256273
}
274+
275+
static String _typesAsString(List<TypeLink> types) {
276+
if (types.isEmpty) {
277+
return '';
278+
}
279+
return '<${types.map((l) => l.symbol + _typesAsString(l.generics)).join(', ')}>';
280+
}
257281
}

angular_compiler/test/emitter/reflector_test.dart

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,79 @@ void main() {
269269
' );\n'
270270
' _ngRef.registerDependencies(\n'
271271
' Example,\n'
272-
' const [const [const _ngRef.Inject(const _ngRef.OpaqueToken(r\'someToken\')),],],\n'
272+
' const [const [const _ngRef.Inject(const _ngRef.OpaqueToken<dynamic>(r\'someToken\')),],],\n'
273+
' );\n'
274+
'\n'
275+
'}\n',
276+
);
277+
});
278+
279+
test('should support MultiToken', () async {
280+
final reflector = new ReflectableReader.noLinking();
281+
final output = await reflector.resolve(await resolveLibrary(r'''
282+
const someToken = const MultiToken('someToken');
283+
@Injectable()
284+
class Example {
285+
final Map<String, Map<int, String>> example;
286+
Example(@Inject(someToken) this.example);
287+
}
288+
'''));
289+
final emitter = new ReflectableEmitter(
290+
output,
291+
reflectorSource: libReflection,
292+
);
293+
expect(
294+
emitter.emitInitReflector(),
295+
''
296+
'var _visited = false;\n'
297+
'void initReflector() {\n'
298+
' if (_visited) {\n'
299+
' return;\n'
300+
' }\n'
301+
' _visited = true;\n'
302+
' _ngRef.registerFactory(\n'
303+
' Example,\n'
304+
' (Map p0) => new Example(p0),\n'
305+
' );\n'
306+
' _ngRef.registerDependencies(\n'
307+
' Example,\n'
308+
' const [const [const _ngRef.Inject(const _ngRef.MultiToken<dynamic>(r\'someToken\')),],],\n'
309+
' );\n'
310+
'\n'
311+
'}\n',
312+
);
313+
});
314+
315+
test('should support generic typed OpaqueToken', () async {
316+
final reflector = new ReflectableReader.noLinking();
317+
final output = await reflector.resolve(await resolveLibrary(r'''
318+
const stringToken = const OpaqueToken<String>('stringToken');
319+
@Injectable()
320+
class Example {
321+
final String example;
322+
Example(@Inject(stringToken) this.example);
323+
}
324+
'''));
325+
final emitter = new ReflectableEmitter(
326+
output,
327+
reflectorSource: libReflection,
328+
);
329+
expect(
330+
emitter.emitInitReflector(),
331+
''
332+
'var _visited = false;\n'
333+
'void initReflector() {\n'
334+
' if (_visited) {\n'
335+
' return;\n'
336+
' }\n'
337+
' _visited = true;\n'
338+
' _ngRef.registerFactory(\n'
339+
' Example,\n'
340+
' (String p0) => new Example(p0),\n'
341+
' );\n'
342+
' _ngRef.registerDependencies(\n'
343+
' Example,\n'
344+
' const [const [const _ngRef.Inject(const _ngRef.OpaqueToken<String>(r\'stringToken\')),],],\n'
273345
' );\n'
274346
'\n'
275347
'}\n',

0 commit comments

Comments
 (0)