Description
This issue supersedes #29643 and would close angulardart/angular#930.
AngularDart requires all methods and fields in a class
annotated with @Component()
are public
, so that the corresponding (generated) <file>.template.dart
can access those methods and fields.
For example:
// hello.dart
@Component(
selector: 'my-comp',
template: 'Hello {{name}}!',
)
class MyComp {
String name;
}
... generates, approximately the following ...
// hello.template.dart
class _ViewMyComp extends View {
Element _rootEl;
MyComp _context;
@override
void build() {
_rootEl = new Element.tagName('my-comp');
_rootEl.append(new Text(_context.name));
}
}
This is the only intended use of the String name
field. For example, it could be tightly bound to other state, it isn't valid to be changed outside of the class's knowledge. If we made name
private (_name
), it would satisfy that requirement, but then could not be used from .template.dart
.
So, this should lint:
// not_hello.dart
void withHelloComponent(MyComp comp) {
// LINT: visible_for_template
comp.name = 'Haha!';
}
Specification
- An annotated class, field, or method may be referenced in the same Dart library.
- An annotated class, field, or method may be referenced in
<file>.template.dart
for<file>.dart
- Any other usage of the annotated member should lint
FAQ
Can't you just make .template.dart
a part file?
Theoretically. This would take multiple man years, which is much higher than the cost of adding this lint. It's possible we might go down this route eventually, but it should be considered at this point functionally impossible.
Can't this just live in the angular_analyzer_plugin
Theoretically. We haven't found a good mechanism to run this, at build-time, in google3. Also not all users use the angular_analyzer_plugin
(@MichaelRFairhurst should know precise numbers), so we'd need everyone to be able to see the impact of this (similar to Flutter's @required
).
What about more "general" lints
If we ever implemented visibility keywords, or something like @internal
or @visibleForCodegen
, or @friend[ly]
, and it would be able to at least mostly match the semantics expressed above then we would use them instead, and happily delete this lint or the request for this lint.
Why is this important
For one, AngularDart currently heavily collides with "Effective Dart" (/cc @munificent). We're working on that - but one of the areas outside of our control this one. We'd much prefer we had an easily understandable standard way of saying "basically private":
@Component(
selector: 'my-comp',
template: 'Hello {{name}}!',
)
class MyComp {
// Does not require explicit, boiler-plate documentation stating why this is public.
@visibleForTemplate
String name;
}
... the alternative, or the status quo, is this:
class MyComp {
/// **WARNING**: Do not use outside the template language.
String name;
}