Skip to content

Commit ecb3b88

Browse files
committed
Replace class SyntheticInput with enum BuildLocation.
1 parent a49a24d commit ecb3b88

File tree

10 files changed

+219
-378
lines changed

10 files changed

+219
-378
lines changed

README.md

Lines changed: 116 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -46,146 +46,138 @@ be configured (as opposed to using part files).
4646

4747
## Usage
4848

49-
Following the example of [`source_gen`][source_gen], it is common practice to separate *builders* and *generators* from the code using those builders.
49+
Following the example of [`source_gen`][source_gen], it is common practice to
50+
separate *builders* and *generators* from the code using those builders.
5051

51-
In the [example] provided with this library, the package defining a new builder is called `researcher_builder` and the package using this builder is called `researcher`. To set up a build system the following steps are required:
52+
In the [example] provided with this library, the package defining a new
53+
builder is called `researcher_builder` and the package using this builder is called `researcher`.
54+
To set up a build system the following steps are required:
5255

5356
1. Include [`merging_builder`][merging_builder], [`build`][build] as *dependencies* in the file `pubspec.yaml` of the package **defining** the builder. In the [example] mentioned here, the generator also requires the packages [`analyzer`][analyzer] and [`source_gen`][source_gen].
5457

5558
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].
5659

5760

58-
<details> <summary> Show details. </summary>
59-
60-
```Dart
61-
62-
import 'dart:async';
63-
64-
import 'package:analyzer/dart/element/element.dart';
65-
import 'package:build/build.dart' show BuildStep;
66-
import 'package:merging_builder/merging_builder.dart';
67-
import 'package:quote_buffer/quote_buffer.dart';
68-
69-
import 'package:source_gen/source_gen.dart' show ConstantReader;
70-
71-
import '../annotations/add_names.dart';
72-
73-
74-
/// Reads a field element of type [List<String] and generates the merged content.
75-
class AddNamesGenerator extends MergingGenerator<List<String>, AddNames> {
76-
/// Portion of source code included at the top of the generated file.
77-
/// Should be specified as header when constructing the merging builder.
78-
static String get header {
79-
return '/// Added names.';
80-
}
81-
82-
/// Portion of source code included at the very bottom of the generated file.
83-
/// Should be specified as [footer] when constructing the merging builder.
84-
static String get footer {
85-
return '/// This is the footer.';
86-
}
87-
88-
@override
89-
List<String> generateStreamItemForAnnotatedElement(
90-
Element element,
91-
ConstantReader annotation,
92-
BuildStep buildStep,
93-
) {
94-
final result = <String>[];
95-
if (element is ClassElement) {
96-
final nameObjects =
97-
element.getField('names')?.computeConstantValue()?.toListValue();
98-
for (final nameObj in nameObjects ?? []) {
99-
result.add(nameObj.toStringValue());
100-
}
101-
return result;
102-
}
103-
return <String>['Could not read name'];
104-
}
105-
106-
/// Returns the merged content.
107-
@override
108-
FutureOr<String> generateMergedContent(Stream<List<String>> stream) async {
109-
final b = StringBuffer();
110-
var i = 0;
111-
final allNames = <List<String>>[];
112-
// Iterate over stream:
113-
await for (final names in stream) {
114-
b.write('final name$i = [');
115-
b.writelnAllQ(names, separator2: ',');
116-
b.writeln('];');
117-
++i;
118-
allNames.add(names);
119-
}
120-
121-
b.writeln('');
122-
b.writeln('final List<List<String>> names = [');
123-
for (var names in allNames) {
124-
b.writeln(' [');
125-
b.writelnAllQ(names, separator2: ',');
126-
b.writeln(' ],');
127-
}
128-
b.writeln('];');
129-
return b.toString();
61+
<details> <summary> Show details. </summary>
62+
63+
```Dart
64+
import 'dart:async';
65+
import 'package:analyzer/dart/element/element.dart';
66+
import 'package:build/build.dart' show BuildStep;
67+
import 'package:merging_builder/merging_builder.dart';
68+
import 'package:quote_buffer/quote_buffer.dart';
69+
import 'package:source_gen/source_gen.dart' show ConstantReader;
70+
import '../annotations/add_names.dart';
71+
/// Reads a field element of type [List<String] and generates the merged content.
72+
class AddNamesGenerator extends MergingGenerator<List<String>, AddNames> {
73+
/// Portion of source code included at the top of the generated file.
74+
/// Should be specified as header when constructing the merging builder.
75+
static String get header {
76+
return '/// Added names.';
77+
}
78+
/// Portion of source code included at the very bottom of the generated file.
79+
/// Should be specified as [footer] when constructing the merging builder.
80+
static String get footer {
81+
return '/// This is the footer.';
82+
}
83+
@override
84+
List<String> generateStreamItemForAnnotatedElement(
85+
Element element,
86+
ConstantReader annotation,
87+
BuildStep buildStep,
88+
) {
89+
final result = <String>[];
90+
if (element is ClassElement) {
91+
final nameObjects =
92+
element.getField('names')?.computeConstantValue()?.toListValue();
93+
for (final nameObj in nameObjects ?? []) {
94+
result.add(nameObj.toStringValue());
13095
}
96+
return result;
13197
}
132-
```
98+
return <String>['Could not read name'];
99+
}
100+
/// Returns the merged content.
101+
@override
102+
FutureOr<String> generateMergedContent(Stream<List<String>> stream) async {
103+
final b = StringBuffer();
104+
var i = 0;
105+
final allNames = <List<String>>[];
106+
// Iterate over stream:
107+
await for (final names in stream) {
108+
b.write('final name$i = [');
109+
b.writelnAllQ(names, separator2: ',');
110+
b.writeln('];');
111+
++i;
112+
allNames.add(names);
113+
}
114+
b.writeln('');
115+
b.writeln('final List<List<String>> names = [');
116+
for (var names in allNames) {
117+
b.writeln(' [');
118+
b.writelnAllQ(names, separator2: ',');
119+
b.writeln(' ],');
120+
}
121+
b.writeln('];');
122+
return b.toString();
123+
}
124+
}
133125
134-
</details>
126+
```
127+
</details>
135128

136129
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.
137130
* The generator `AddNamesGenerator` shown below extends `MergingGenerator<List<String>, AddNames>` (see step 2).
138131
* Input sources may be specified using wildcard characters supported by [`Glob`][Glob].
139132
* 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).
140133

141-
```Dart
142-
import 'package:build/build.dart';
143-
import 'package:merging_builder/merging_builder.dart';
144-
145-
import 'src/generators/add_names_generator.dart';
146-
import 'src/generators/assistant_generator.dart';
147-
148-
/// Defines a merging builder.
149-
/// Honours the options: `input_files`, `output_file`, `header`, `footer`,
150-
/// and `sort_assets` that can be set in `build.yaml`.
151-
Builder addNamesBuilder(BuilderOptions options) {
152-
BuilderOptions defaultOptions = BuilderOptions({
153-
'input_files': 'lib/*.dart',
154-
'output_file': 'lib/output.dart',
155-
'header': AddNamesGenerator.header,
156-
'footer': AddNamesGenerator.footer,
157-
'sort_assets': true,
158-
});
159-
160-
// Apply user set options.
161-
options = defaultOptions.overrideWith(options);
162-
return MergingBuilder<List<String>, LibDir>(
163-
generator: AddNamesGenerator(),
164-
inputFiles: options.config['input_files'],
165-
outputFile: options.config['output_file'],
166-
header: options.config['header'],
167-
footer: options.config['footer'],
168-
sortAssets: options.config['sort_assets'],
169-
);
170-
}
171-
172-
/// Defines a standalone builder.
173-
Builder assistantBuilder(BuilderOptions options) {
174-
BuilderOptions defaultOptions = BuilderOptions({
175-
'input_files': 'lib/*.dart',
176-
'output_files': 'lib/output/assistant_(*).dart',
177-
'header': AssistantGenerator.header,
178-
'footer': AssistantGenerator.footer,
179-
'root': ''
180-
});
181-
options = defaultOptions.overrideWith(options);
182-
return StandaloneBuilder<LibDir>(
183-
generator: AssistantGenerator(),
184-
inputFiles: options.config['input_files'],
185-
outputFiles: options.config['output_files'],
186-
root: options.config['root']);
187-
}
188-
```
134+
<details> <summary> Show details. </summary>
135+
136+
```Dart
137+
import 'package:build/build.dart';
138+
import 'package:merging_builder/merging_builder.dart';
139+
import 'src/generators/add_names_generator.dart';
140+
import 'src/generators/assistant_generator.dart';
141+
/// Defines a merging builder.
142+
/// Honours the options: `input_files`, `output_file`, `header`, `footer`,
143+
/// and `sort_assets` that can be set in `build.yaml`.
144+
Builder addNamesBuilder(BuilderOptions options) {
145+
BuilderOptions defaultOptions = BuilderOptions({
146+
'input_files': 'lib/*.dart',
147+
'output_file': 'lib/output.dart',
148+
'header': AddNamesGenerator.header,
149+
'footer': AddNamesGenerator.footer,
150+
'sort_assets': true,
151+
});
152+
// Apply user set options.
153+
options = defaultOptions.overrideWith(options);
154+
return MergingBuilder<List<String>, LibDir>(
155+
generator: AddNamesGenerator(),
156+
inputFiles: options.config['input_files'],
157+
outputFile: options.config['output_file'],
158+
header: options.config['header'],
159+
footer: options.config['footer'],
160+
sortAssets: options.config['sort_assets'],
161+
);
162+
}
163+
/// Defines a standalone builder.
164+
Builder assistantBuilder(BuilderOptions options) {
165+
BuilderOptions defaultOptions = BuilderOptions({
166+
'input_files': 'lib/*.dart',
167+
'output_files': 'lib/output/assistant_(*).dart',
168+
'header': AssistantGenerator.header,
169+
'footer': AssistantGenerator.footer,
170+
'root': ''
171+
});
172+
options = defaultOptions.overrideWith(options);
173+
return StandaloneBuilder<LibDir>(
174+
generator: AssistantGenerator(),
175+
inputFiles: options.config['input_files'],
176+
outputFiles: options.config['output_files'],
177+
root: options.config['root']);
178+
}
179+
```
180+
</details>
189181

190182
4. In the package **defining** the builder, add the builder configuration for the builder `add_names_builder` (see below). The build extensions for
191183
[`MergingBuilder`][MergingBuilder] must be specified using the notation available for **synthetic input**. For example, `"$lib$"` indicates that the
@@ -255,66 +247,8 @@ and [`build_runner`][build_runner] as *dev_dependencies* in the file `pubspec.ya
255247
7. Initiate the build process by using the command:
256248
```console
257249
# dart run build_runner build --delete-conflicting-outputs --verbose
258-
[INFO] Entrypoint:Generating build script...
259-
[INFO] Entrypoint:Generating build script completed, took 802ms
260-
261-
[INFO] BuildDefinition:Initializing inputs
262-
[INFO] BuildDefinition:Reading cached asset graph...
263-
[INFO] BuildDefinition:Reading cached asset graph completed, took 99ms
264-
265-
[INFO] BuildDefinition:Checking for updates since last build...
266-
[INFO] BuildDefinition:Checking for updates since last build completed, took 772ms
267-
268-
[INFO] Build:Running build...
269-
[FINE] researcher_builder:add_names_builder on lib/$lib$:Running AddNamesGenerator on: lib/input/researcher_b.dart.
270-
[FINE] researcher_builder:add_names_builder on lib/$lib$:Running AddNamesGenerator on: lib/input/researcher_a.dart.
271-
[FINE] researcher_builder:assistant_builder on lib/$lib$:Running AssistantGenerator on: lib/input/researcher_b.dart.
272-
[FINE] researcher_builder:assistant_builder on lib/$lib$:Running AssistantGenerator on: lib/input/researcher_a.dart.
273-
[INFO] Build:Running build completed, took 886ms
274-
275-
[INFO] Build:Caching finalized dependency graph...
276-
[INFO] Build:Caching finalized dependency graph completed, took 70ms
277-
278-
[INFO] Build:Succeeded after 973ms with 3 outputs (2 actions)
279250
```
280251

281-
To view the content of the generated files please click below:
282-
<details> <summary> lib/output/assistant_researcher_a.dart </summary>
283-
284-
```Dart
285-
// GENERATED CODE. DO NOT MODIFY. Generated by AssistantGenerator.
286-
final String assistants = 'Thomas, Mayor';
287-
```
288-
289-
</details>
290-
291-
<details> <summary> lib/output/assistant_researcher_b.dart </summary>
292-
293-
```Dart
294-
// GENERATED CODE. DO NOT MODIFY. Generated by AssistantGenerator.
295-
final String assistants = 'Philip, Martens';
296-
```
297-
298-
</details>
299-
<details> <summary> lib/output/researchers.dart </summary>
300-
301-
```Dart
302-
// GENERATED CODE. DO NOT MODIFY. Generated by AddNamesGenerator.
303-
304-
// Header specified in build.yaml.
305-
final name0 = ['Philip', 'Martens'];
306-
final name1 = ['Thomas', 'Mayor'];
307-
308-
final List<List<String>> names = [
309-
['Philip', 'Martens'],
310-
['Thomas', 'Mayor'],
311-
];
312-
313-
// Footer specified in build.yaml.
314-
```
315-
316-
</details>
317-
318252
## Implementation Details
319253

320254
The classes [`MergingBuilder<T, S extends SyntheticInput>`][class-merging-builder]

lib/merging_builder.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export 'src/builders/merging_builder.dart';
2-
export 'src/generators/merging_generator.dart';
32
export 'src/builders/standalone_builder.dart';
43
export 'src/builders/synthetic_builder.dart';
5-
export 'src/builders/synthetic_input.dart';
4+
export 'src/enum/build_location.dart';
5+
export 'src/generators/merging_generator.dart';

0 commit comments

Comments
 (0)