@@ -129,8 +129,8 @@ The generator has to rely on some guidance from the user to mark classes that
129129injector has to instantiate. There are two ways of doing this: @Injectables
130130or custom class annotation.
131131
132- ` @Injectables ` is an annotation provided by the di package which can be
133- applied on a library definition with a list of types that the generator
132+ ` @Injectables ` is an annotation provided by the di package which can be
133+ applied on a library definition with a list of types that the generator
134134should process.
135135
136136```
@@ -146,12 +146,11 @@ class MyService {
146146}
147147```
148148
149- @Injectables annotation should be mainly used with classes that are out of
150- your control (ex. you can't modify the source code -- third party library).
149+ ` @Injectables ` annotation should be mainly used with classes that are out of
150+ your control (ex. you can't modify the source code -- third party library).
151151In all other cases it's preferable to use custom class annotation(s).
152152
153- You can also define your own custom class annotations and apply them on
154- classes that you need to be instantiated by the injector.
153+ You can define your own custom class annotations
155154
156155```
157156library injectable;
@@ -165,18 +164,20 @@ class InjectableService {
165164}
166165```
167166
167+ and apply them on classes that you need to be instantiated by the injector.
168+
168169```
169170@InjectableService()
170171class QueryService {
171172 // ...
172173}
173174```
174175
175- You can then then configure generator with those annotations.
176+ You can then then configure generator to look for those annotations.
176177
177- When configuring the generator with the custom annotation you need to pass
178- a fully qualified class name (including the library prefix). In case of the
179- above example the fully qualified name of Service annotation would be
178+ When configuring the generator with the custom annotation you need to pass
179+ a fully qualified class name (including the library prefix). In case of the
180+ above example the fully qualified name of Service annotation would be
180181` injectable.InjectableService ` .
181182
182183## AngularDart Parser Generator
@@ -186,6 +187,67 @@ and then compiles them into Dart, so at runtime it doesn't have to parse those
186187expressions and while invoking the expressions it uses pre-generated code to
187188access fields and methods, so it doesn't have to use mirrors.
188189
190+ There are many places in the application where expressions can be used:
191+
192+ 1 . HTML template attributes
193+ 1 . mustaches {{ }} (technically a directive)
194+ 1 . custom syntax directives like ng-repeat
195+ 1 . component/directive attribute mappings
196+ 1 . programmatic calls to Scope.$eval, Scope.$watch/$watchCollection,
197+ Parser.call, etc.
198+
199+ It's not always trivial to tell if element attribute in HTML template contains
200+ an expression or just a string value.
201+
202+ Expression extractor has to:
203+
204+ 1 . find all component/directive definitions in the source code and extract
205+ their metadata (NgAnnotations, field attribute mapping annotations)
206+ 1 . statically "compile" all the templates to identify all directives and
207+ extract all attributes and mustaches that contain expressions
208+
209+ Sometimes directives with attributes mapped with @ spec can subsequently call
210+ ` Scope.$eval ` on the string value of the attribute. In those cases directive
211+ can tell expression extractor that attribute value is used in this way via
212+ ` exportExpressionAttrs ` property on ` NgDirective ` /` NgComponent ` annotation. Ex:
213+
214+ ```
215+ @NgComponent(
216+ selector: 'foo',
217+ map: const {
218+ 'bar': '@bar'
219+ },
220+ exportExpressionAttrs: 'bar'
221+ )
222+ class FooComponent implement NgAttachAware {
223+ String bar;
224+ Scope scope;
225+
226+ FooComponent(Scope this.scope);
227+
228+ attach() {
229+ scope.$watch(bar, _barChanged);
230+ }
231+
232+ _barChanged(val) {}
233+ }
234+ ```
235+
236+ Similarly, if directive programmatically evaluates an expression it can tell
237+ expression extractor which expressions it evaluates:
238+
239+ ```
240+ @NgDirective(
241+ selector: 'foo'
242+ exportExpressions: '1 + 3'
243+ )
244+ class FooDirective {
245+ FooComponent(Scope scope) {
246+ _showResult(scope.$eval('1 + 2'));
247+ }
248+ }
249+ ```
250+
189251You can find an example of how to use the parser generator in
190252` bin/generator.dart ` file.
191253
0 commit comments