AngularDart (v1) had a simple meta programming story: it relied on dart:mirrors
at development time (and in certain other aspects, like unit and component tests), and used a simple form of code generation for production, with an interface approximately as follows:
// interface.dart
abstract class MetadataExtractor {
Iterable extractMetadata(Type directiveOrInjectable);
}
// dynamic.dart
import ‘dart:mirrors’;
class DynamicMetadataExtractor {
Iterable extractMetadata(Type directiveOrInjectable) {
reflectType(directiveOrInjectable);
// ...
}
}
// static.dart
class StaticMetadataExtractor {
factory StaticMetadataExtractor(Map<Type, Iterable> metadata) => …
}
That meant that AngularDart (v1) had a whole-program compile-step to generate StaticMetadataExtractor, for example, the following might have been generated for a small application:
final staticMetadata = {
FooComponent: [
new Component(
selector: 'foo',
…
),
],
// For every @Injectable(), @Directive(), and @Component() at minimum.
};
To allow modular [re]-compilation, AngularDart (v2) was built approximately the same way as AngularDart (v1), but instead "shards" the creation of this map of relevant metadata (called reflector now) across generated files. A single .template.dart file shadows every .dart file the Angular compiler runs on. So for example, this is generated:
void initReflector() {
reflector.registerType(Foo, new ComponentFactory(...));
}
And if you import any files, we detect if a *.template.dart *file exists for it, and links together:
// foo.dart
import ‘package:angular2/angular2.dart’;
import ‘bar.dart’;
@Component(...)
class Foo {}
// foo.template.dart
import ‘package:angular2/angular2.template.dart’ as _i1;
import ‘bar.template.dart ‘as _i2;
void initReflector() {
reflector.registerType(Foo, new ComponentFactory(...));
_i1.initReflector();
_i2.initReflector();
}
Today's approach causes a number of issues.
Consider the following import:
// app.dart
import ‘package:angular_components/angular_components.dart’;
// app.template.dart
import ‘package:angular_components/angular_components.template.dart’ as _i1;
void initReflector() {
_i1.initReflector();
}
In this case, we will register type and component information for every component, directive, pipe, and injectable in pkg/angular_components, even if you only use a single component.
Hi Matan.
Is the new compiler preventing this issues?
Or is there a advanced guideline to prevent unused code to be compiled?