Skip to content

Commit 7c0ec27

Browse files
committed
add a simple observable macro example
1 parent 24ba4b5 commit 7c0ec27

File tree

5 files changed

+72
-2
lines changed

5 files changed

+72
-2
lines changed

analysis_options.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ analyzer:
33
- accepted/2.3/spread-collections/examples/**
44
# TODO: remove these when the analyzer supports macros
55
- working/macros/example/lib/data_class.dart
6+
- working/macros/example/lib/observable.dart
67
- working/macros/example/bin/user_main.dart

working/macros/example/bin/run.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,14 @@ void main() async {
1919
File(dartToolDir.uri.resolve('bootstrap.dart').toFilePath());
2020
log('Bootstrapping macro program (${bootstrapFile.path}).');
2121
var dataClassUri = Uri.parse('package:macro_proposal/data_class.dart');
22+
var observableUri = Uri.parse('package:macro_proposal/observable.dart');
2223
var bootstrapContent = bootstrapMacroIsolate({
2324
dataClassUri.toString(): {
2425
'DataClass': [''],
25-
}
26+
},
27+
observableUri.toString(): {
28+
'Observable': [''],
29+
},
2630
}, SerializationMode.byteDataClient);
2731
bootstrapFile.writeAsStringSync(bootstrapContent);
2832
var bootstrapKernelFile =
@@ -75,9 +79,12 @@ void main() async {
7579
'--source',
7680
Platform.script.resolve('user_main.dart').toFilePath(),
7781
'--packages-file=.dart_tool/package_config.json',
82+
'--enable-experiment=macros',
7883
'--precompiled-macro-format=kernel',
7984
'--precompiled-macro',
8085
'$dataClassUri;${bootstrapKernelFile.path}',
86+
'--precompiled-macro',
87+
'$observableUri;${bootstrapKernelFile.path}',
8188
'--macro-serialization-mode=bytedata',
8289
'--input-linked',
8390
bootstrapKernelFile.path,

working/macros/example/bin/user_main.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'dart:math';
66

77
import 'package:macro_proposal/data_class.dart';
8+
import 'package:macro_proposal/observable.dart';
89

910
void main() {
1011
var rand = Random();
@@ -21,6 +22,11 @@ void main() {
2122
var phoenix =
2223
joe.copyWith(name: 'Phoenix', age: rand.nextInt(100), reports: [joe]);
2324
print(phoenix);
25+
26+
var observableUser = ObservableUser(age: 10, name: 'Georgio');
27+
observableUser
28+
..age = 11
29+
..name = 'Greg';
2430
}
2531

2632
@DataClass()
@@ -34,3 +40,17 @@ class User {
3440
class Manager extends User {
3541
final List<User> reports;
3642
}
43+
44+
class ObservableUser {
45+
@Observable()
46+
int _age;
47+
48+
@Observable()
49+
String _name;
50+
51+
ObservableUser({
52+
required int age,
53+
required String name,
54+
}) : _age = age,
55+
_name = name;
56+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// There is no public API exposed yet, the in progress api lives here.
6+
import 'dart:async';
7+
8+
import 'package:_fe_analyzer_shared/src/macros/api.dart';
9+
10+
macro class Observable implements FieldDeclarationsMacro {
11+
const Observable();
12+
13+
@override
14+
Future<void> buildDeclarationsForField(
15+
FieldDeclaration field, ClassMemberDeclarationBuilder builder) async {
16+
final name = field.identifier.name;
17+
if (!name.startsWith('_')) {
18+
throw ArgumentError(
19+
'@observable can only annotate private fields, and it will create '
20+
'public getters and setters for them, but the public field '
21+
'$name was annotated.');
22+
}
23+
var publicName = name.substring(1);
24+
var getter = DeclarationCode.fromParts(
25+
[field.type.code, ' get $publicName => ', field.identifier, ';']);
26+
builder.declareInClass(getter);
27+
28+
var print =
29+
// ignore: deprecated_member_use
30+
await builder.resolveIdentifier(Uri.parse('dart:core'), 'print');
31+
var setter = DeclarationCode.fromParts([
32+
'set $publicName(',
33+
field.type.code,
34+
' val) {\n',
35+
print,
36+
"('Setting $publicName to \${val}');\n",
37+
field.identifier,
38+
' = val;\n}',
39+
]);
40+
builder.declareInClass(setter);
41+
}
42+
}

working/macros/example/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: macro_proposal
22
publish_to: none
33
environment:
4-
sdk: ">=2.17.0-0 <3.0.0"
4+
sdk: ">=2.18.0-0 <3.0.0"
55
dev_dependencies:
66
args: ^2.3.0
77
dart_style: ^2.2.1

0 commit comments

Comments
 (0)