Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Commit fab9403

Browse files
committed
Extended parser generator section
1 parent a7592c3 commit fab9403

File tree

1 file changed

+72
-10
lines changed

1 file changed

+72
-10
lines changed

Chapter_07/README.md

Lines changed: 72 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ The generator has to rely on some guidance from the user to mark classes that
129129
injector has to instantiate. There are two ways of doing this: @Injectables
130130
or 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
134134
should 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).
151151
In 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
```
157156
library 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()
170171
class 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
186187
expressions and while invoking the expressions it uses pre-generated code to
187188
access 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+
189251
You can find an example of how to use the parser generator in
190252
`bin/generator.dart` file.
191253

0 commit comments

Comments
 (0)