You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Source code generation has become an important software development tool
9
9
when building and maintaining a large number of data models,
10
-
data access object, widgets, etc.
11
-
12
-
The premise of *source code generation* is that we can specify
10
+
data access object, widgets, etc. The premise of *source code generation* is that we can specify
13
11
(hopefully few) details and flesh out the rest of the classes,
14
12
and methods during the build process.
15
13
16
-
The build process consists of scannig the appropriate files,
17
-
extracting the required information,
18
-
generating the source code, and writing the source code to certain files.
19
-
The build process
20
-
also entails keeping track of files changes,
21
-
delete conflicting files, reporting issues and progress.
22
-
23
-
Source code generation using Dart relies heavily on *constants* known at compile time.
24
-
Dart's static [`analyzer`][analyzer] provides access to libraries, classes,
25
-
class fields, class methods, functions, variables, etc in the form of [`Elements`][Elements].
26
-
Compile-time constant expressions are represented by a [`DartObject`][DartObject]
27
-
and can be accessed by using [`computeConstantValue()`][computeConstantValue()] a method available for elements representing a variable.
28
-
29
-
In practice, we mark constant constant classes with annotations and instruct
30
-
the builder to processes only the annotated objects.
31
-
32
-
33
14
The library [`merging_builder`][merging_builder] includes the following (synthetic input) builder classes:
34
15
35
16
*[`MergingBuilder`][class-merging-builder] reads **several input files** and writes
@@ -57,134 +38,15 @@ To set up a build system the following steps are required:
57
38
58
39
2. In the package **defining** the custom builder, create a custom generator that extends [`MergingGenerator`][MergingGenerator]. Users will have to implement the methods `generateItemForAnnotatedElement` and `generateMergedContent`. In the example shown below `generateItemForAnnotatedElement` reads a list of strings while `generateMergedContent` merges the data and generates output that is written to [researchers.dart].
3. Create an instance of [`MergingBuilder`][MergingBuilder]. Following the example of [`source_gen`][source_gen], builders are typically placed in a file called: `builder.dart` located in the `lib` folder of the builder package.
130
42
* The generator `AddNamesGenerator` shown below extends `MergingGenerator<List<String>, AddNames>` (see step 2).
131
43
* Input sources may be specified using wildcard characters supported by [`Glob`][Glob].
132
44
* The builder definition shown below honours the *options*`input_files`, `output_file`, `header`, `footer`, and `sort_assets` that can be set in the file `build.yaml` located in the package `researcher` (see step 5).
4. In the package **defining** the builder, add the builder configuration for the builder `add_names_builder` (see below). The build extensions for
183
-
[`MergingBuilder`][MergingBuilder] must be specified using the notation available for **synthetic input**. For example, `"$lib$"` indicates that the
47
+
[`MergingBuilder`][MergingBuilder] must be specified using the notation
48
+
available for **synthetic input**. For example, `"$lib$"` indicates that the
184
49
input files are located in the folder `lib` or a subfolder thereof.
185
-
For more information consult the section: [Writing a Builder using a synthetic input]
186
-
found in the documentation of the Dart package [`build`][build].
187
-
188
50
```Yaml
189
51
builders:
190
52
add_names_builder:
@@ -201,7 +63,9 @@ found in the documentation of the Dart package [`build`][build].
201
63
build_to: source
202
64
```
203
65
204
-
5. In the package **using** the custom builder, `researcher`, add `add_names_builder` to the list of known builders. The file `build.yaml` is shown below.
66
+
5. In the package **using** the custom builder, `researcher`,
67
+
add `add_names_builder` to the list of known builders.
68
+
The file `build.yaml` is shown below.
205
69
206
70
```Yaml
207
71
targets:
@@ -230,19 +94,6 @@ found in the documentation of the Dart package [`build`][build].
230
94
6. In the package **using** the builder, `researcher`, add `researcher_builder`
231
95
and [`build_runner`][build_runner] as *dev_dependencies* in the file `pubspec.yaml`.
232
96
233
-
```Yaml
234
-
name: researcher
235
-
description:
236
-
Example demonstrating how to use the library merging_builder.
237
-
238
-
environment:
239
-
sdk: '>=2.17.0 <3.0.0'
240
-
241
-
dev_dependencies:
242
-
build_runner: ^1.10.0
243
-
researcher_builder:
244
-
path: ../researcher_builder
245
-
```
246
97
247
98
7. Initiate the build process by using the command:
248
99
```console
@@ -251,24 +102,22 @@ and [`build_runner`][build_runner] as *dev_dependencies* in the file `pubspec.ya
251
102
252
103
## Implementation Details
253
104
254
-
The classes [`MergingBuilder<T, S extends SyntheticInput>`][class-merging-builder]
255
-
and [`StandaloneBuilder<S extends SyntheticInput>`][class-standalone-builder]
256
-
use *synthetic input* which must be specified
257
-
by choosing either [`LibDir`][LibDir] or [`PackageDir`][PackageDir] as type parameter `S`.
258
-
259
-
[`LibDir`][LibDir] indicates that input and output files are located in the package directory `lib` or a subfolder thereof. For more information
260
-
about *synthetic input* see:
261
-
[Writing an Aggregate Builder](https://github.com/dart-lang/build/blob/master/docs/writing_an_aggregate_builder.md#writing-the-builder-using-a-synthetic-input).
105
+
The classes [`MergingBuilder`][class-merging-builder]
106
+
and [`StandaloneBuilder`][class-standalone-builder]
107
+
use *synthetic input*.
262
108
263
-
### Class - Merging Builder
109
+
### Merging Builder
264
110
265
111
[`MergingBuilder`][MergingBuilder] reads **several input files** and writes merged output to **one output file**.
266
-
The builder provides the option to sort the input files in reverse topological order. If the input file `a.dart` includes file `b.dart` then `a.dart` will be listed *after* `b.dart`. This option may be useful when
267
-
generating code that needs to list variables or call functions in order of dependence. To enable topological sorting set the constructor parameter `sortAsset: true`. Note: If sorting of input assets is enabled, input files must not include each other directly or indirectly.
112
+
The builder provides the option to sort the input files in reverse topological order.
113
+
If the input file `a.dart` includes file `b.dart` then `a.dart` will be listed *after*`b.dart`. This option may be useful when
114
+
generating code that needs to list variables or call functions in order of dependence.
115
+
To enable topological sorting set the constructor parameter `sortAsset: true`. Note: If sorting of input assets is enabled, input files must not include each other directly or indirectly.
116
+
268
117
269
118
A conventional builder typically calls the generator method `generate` from within its `build` method to retrieve the generated source-code. [`MergingBuilder`][MergingBuilder] calls the [`MergingGenerator`][MergingGenerator] method `generateStream`. It allows the generator to pass a stream of data-type `T` to the builder, one stream item for each annotated element processed to the generator method `generateStreamItemForAnnotatedElement`.
270
119
271
-
The private builder method `_combineStreams` combines the streams received for each processed input file and calls the generator method `generateMergedContent`. As a result, this method has access to all stream items of type `T` generated for each annotated element in each input file. It is the task of this method to generate the merged source-code output.
120
+
The private builder method `_combineStreams` combines the streams received for each processed input file and calls the generator method `generateMergedContent`. As a result, this method has access to all stream items of type `T` generated for each annotated element in each input file. It is the task of this method to generate the *merged* source-code output.
272
121
273
122
The figure below shows the flow of data between the builder and the generator. The data type is indicated by the starting point of the connectors. Dotted connectors represent a stream of data.
274
123
@@ -277,8 +126,10 @@ The figure below shows the flow of data between the builder and the generator. T
277
126
278
127
### Class - Standalone Builder
279
128
280
-
[`StandaloneBuilder`][StandaloneBuilder] reads one or several input files and writes standalone files to a custom location.
281
-
*Standalone* means the output files may be written to a custom folder and not only the extension but the
129
+
[`StandaloneBuilder`][StandaloneBuilder] reads input files and writes
130
+
corresponding output files to a custom location.
131
+
*Standalone* means the output files may be written to a custom folder and
132
+
not only the extension but the
282
133
name of the output file can be configured.
283
134
284
135
The input file path (constructor parameter `inputFiles`) may include
0 commit comments