33// BSD-style license that can be found in the LICENSE file.
44
55// Run this script to print out the generated augmentation library for an
6- // example class.
6+ // example class, created with fake data, and get some basic timing info:
77//
8- // This is primarily for illustration purposes, so we can get an idea of how
9- // things would work on a real-ish example.
10- library language.working.macros.example.run;
8+ // dart benchmark/simple.dart
9+ //
10+ // You can also compile this benchmark to exe and run it as follows:
11+ //
12+ // dart compile exe benchmark/simple.dart && ./benchmark/simple.exe
13+ //
14+ // Pass `--help` for usage and configuration options.
15+ library language.working.macros.benchmark.simple;
1116
1217import 'dart:io' ;
1318
19+ import 'package:args/args.dart' ;
1420import 'package:dart_style/dart_style.dart' ;
1521
1622// There is no public API exposed yet, the in progress api lives here.
@@ -22,6 +28,8 @@ import 'package:_fe_analyzer_shared/src/macros/executor.dart';
2228import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart' ;
2329import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart' ;
2430import 'package:_fe_analyzer_shared/src/macros/executor/serialization.dart' ;
31+ import 'package:_fe_analyzer_shared/src/macros/executor/isolated_executor.dart'
32+ as isolatedExecutor;
2533import 'package:_fe_analyzer_shared/src/macros/executor/process_executor.dart'
2634 as processExecutor;
2735
@@ -30,22 +38,71 @@ void _log(String message) {
3038 print ('${_watch .elapsed }: $message ' );
3139}
3240
33- const clientSerializationMode = SerializationMode .byteDataClient;
34- const serverSerializationMode = SerializationMode .byteDataServer;
41+ final argParser = ArgParser ()
42+ ..addOption ('serialization-strategy' ,
43+ allowed: ['bytedata' , 'json' ],
44+ defaultsTo: 'bytedata' ,
45+ help: 'The serialization strategy to use when talking to macro programs.' )
46+ ..addOption ('macro-execution-strategy' ,
47+ allowed: ['aot' , 'isolate' ],
48+ defaultsTo: 'aot' ,
49+ help: 'The execution strategy for precompiled macros.' )
50+ ..addFlag ('help' , negatable: false , hide: true );
3551
3652// Run this script to print out the generated augmentation library for an example class.
37- void main () async {
38- _log ('Preparing to run macros.' );
53+ void main (List <String > args) async {
54+ var parsedArgs = argParser.parse (args);
55+
56+ if (parsedArgs['help' ] == true ) {
57+ print (argParser.usage);
58+ return ;
59+ }
60+
61+ // Set up all of our options
62+ var parsedSerializationStrategy =
63+ parsedArgs['serialization-strategy' ] as String ;
64+ SerializationMode clientSerializationMode;
65+ SerializationMode serverSerializationMode;
66+ switch (parsedSerializationStrategy) {
67+ case 'bytedata' :
68+ clientSerializationMode = SerializationMode .byteDataClient;
69+ serverSerializationMode = SerializationMode .byteDataServer;
70+ break ;
71+ case 'json' :
72+ clientSerializationMode = SerializationMode .jsonClient;
73+ serverSerializationMode = SerializationMode .jsonServer;
74+ break ;
75+ default :
76+ throw ArgumentError (
77+ 'Unrecognized serialization mode $parsedSerializationStrategy ' );
78+ }
79+
80+ var macroExecutionStrategy = parsedArgs['macro-execution-strategy' ] as String ;
81+ var hostMode = Platform .script.path.endsWith ('.dart' ) ||
82+ Platform .script.path.endsWith ('.dill' )
83+ ? 'jit'
84+ : 'aot' ;
85+ _log ('''
86+ Running with the following options:
87+
88+ Serialization strategy: $parsedSerializationStrategy
89+ Macro execution strategy: $macroExecutionStrategy
90+ Host app mode: $hostMode
91+ ''' );
92+
3993 // You must run from the `macros` directory, paths are relative to that.
40- var thisFile = File ('example /data_class.dart' );
41- if (! thisFile .existsSync ()) {
94+ var dataClassFile = File ('lib /data_class.dart' );
95+ if (! dataClassFile .existsSync ()) {
4296 print ('This script must be ran from the `macros` directory.' );
4397 exit (1 );
4498 }
45- var executor = await processExecutor.start (serverSerializationMode);
99+ _log ('Preparing to run macros' );
100+ var executor = macroExecutionStrategy == 'aot'
101+ ? await processExecutor.start (serverSerializationMode)
102+ : await isolatedExecutor.start (serverSerializationMode);
46103 var tmpDir = Directory .systemTemp.createTempSync ('data_class_macro_example' );
47104 try {
48- var macroUri = thisFile.absolute.uri ;
105+ var macroUri = Uri . parse ( 'package:macro_proposal/data_class.dart' ) ;
49106 var macroName = 'DataClass' ;
50107
51108 var bootstrapContent = bootstrapMacroIsolate ({
@@ -61,8 +118,9 @@ void main() async {
61118 _log ('Compiling DataClass macro' );
62119 var buildSnapshotResult = await Process .run ('dart' , [
63120 'compile' ,
64- ' exe' ,
121+ macroExecutionStrategy == 'aot' ? ' exe' : 'jit-snapshot ' ,
65122 '--packages=.dart_tool/package_config.json' ,
123+ '--enable-experiment=macros' ,
66124 bootstrapFile.uri.toFilePath (),
67125 '-o' ,
68126 kernelOutputFile.uri.toFilePath (),
@@ -88,26 +146,32 @@ void main() async {
88146 late Duration firstRunEnd;
89147 late Duration first11RunsEnd;
90148 for (var i = 1 ; i <= 111 ; i++ ) {
91- var _shouldLog = i == 1 || i == 10 || i == 100 ;
149+ var _shouldLog = i == 1 || i == 11 || i == 111 ;
92150 if (_shouldLog) _log ('Running DataClass macro for the ${i }th time' );
93151 if (instanceId.shouldExecute (DeclarationKind .clazz, Phase .types)) {
94152 if (_shouldLog) _log ('Running types phase' );
95- var result = await executor.executeTypesPhase (instanceId, myClass);
153+ var result = await executor.executeTypesPhase (
154+ instanceId, myClass, SimpleIdentifierResolver ());
96155 if (i == 1 ) results.add (result);
97156 }
98157 if (instanceId.shouldExecute (DeclarationKind .clazz, Phase .declarations)) {
99158 if (_shouldLog) _log ('Running declarations phase' );
100159 var result = await executor.executeDeclarationsPhase (
101- instanceId, myClass, FakeTypeResolver (), FakeClassIntrospector ());
160+ instanceId,
161+ myClass,
162+ SimpleIdentifierResolver (),
163+ SimpleTypeResolver (),
164+ SimpleClassIntrospector ());
102165 if (i == 1 ) results.add (result);
103166 }
104167 if (instanceId.shouldExecute (DeclarationKind .clazz, Phase .definitions)) {
105168 if (_shouldLog) _log ('Running definitions phase' );
106169 var result = await executor.executeDefinitionsPhase (
107170 instanceId,
108171 myClass,
109- FakeTypeResolver (),
110- FakeClassIntrospector (),
172+ SimpleIdentifierResolver (),
173+ SimpleTypeResolver (),
174+ SimpleClassIntrospector (),
111175 FakeTypeDeclarationResolver ());
112176 if (i == 1 ) results.add (result);
113177 }
@@ -123,10 +187,7 @@ void main() async {
123187
124188 _log ('Building augmentation library' );
125189 var library = executor.buildAugmentationLibrary (results, (identifier) {
126- if (identifier == boolIdentifier ||
127- identifier == objectIdentifier ||
128- identifier == stringIdentifier ||
129- identifier == intIdentifier) {
190+ if (['bool' , 'Object' , 'String' , 'int' ].contains (identifier.name)) {
130191 return ResolvedIdentifier (
131192 kind: IdentifierKind .topLevelMember,
132193 name: identifier.name,
@@ -139,7 +200,7 @@ void main() async {
139200 : IdentifierKind .instanceMember,
140201 name: identifier.name,
141202 staticScope: null ,
142- uri: Platform .script. resolve ( 'data_class .dart' ));
203+ uri: Uri . parse ( 'package:app/main .dart' ));
143204 }
144205 });
145206 executor.close ();
@@ -299,7 +360,8 @@ abstract class Fake {
299360 throw UnimplementedError (invocation.memberName.toString ());
300361}
301362
302- class FakeClassIntrospector extends Fake implements ClassIntrospector {
363+ /// Returns data as if everything was [myClass] .
364+ class SimpleClassIntrospector extends Fake implements ClassIntrospector {
303365 @override
304366 Future <List <ConstructorDeclaration >> constructorsOf (
305367 covariant ClassDeclaration clazz) async =>
@@ -308,23 +370,59 @@ class FakeClassIntrospector extends Fake implements ClassIntrospector {
308370 @override
309371 Future <List <FieldDeclaration >> fieldsOf (
310372 covariant ClassDeclaration clazz) async =>
311- myClassFields;
373+ clazz == myClass ? myClassFields : [] ;
312374
313375 @override
314376 Future <List <MethodDeclaration >> methodsOf (
315377 covariant ClassDeclaration clazz) async =>
316- myClassMethods;
378+ clazz == myClass ? myClassMethods : [] ;
317379
318380 @override
319381 Future <ClassDeclaration ?> superclassOf (
320382 covariant ClassDeclaration clazz) async =>
321383 clazz == myClass ? objectClass : null ;
322384}
323385
386+ /// This is a very basic identifier resolver, it does no actual resolution.
387+ class SimpleIdentifierResolver implements IdentifierResolver {
388+ /// Just returns a new [Identifier] whose name is [name] .
389+ @override
390+ Future <Identifier > resolveIdentifier (Uri library, String name) async =>
391+ IdentifierImpl (id: RemoteInstance .uniqueId, name: name);
392+ }
393+
324394class FakeTypeDeclarationResolver extends Fake
325395 implements TypeDeclarationResolver {}
326396
327- class FakeTypeResolver extends Fake implements TypeResolver {}
397+ /// Only supports named types with no type arguments.
398+ class SimpleTypeResolver implements TypeResolver {
399+ @override
400+ Future <StaticType > resolve (TypeAnnotationCode type) async {
401+ if (type is ! NamedTypeAnnotationCode ) {
402+ throw UnsupportedError ('Only named type annotations are supported' );
403+ }
404+ if (type.typeArguments.isNotEmpty) {
405+ throw UnsupportedError ('Type arguments are not supported' );
406+ }
407+ return SimpleNamedStaticType (type.name.name, isNullable: type.isNullable);
408+ }
409+ }
410+
411+ /// Only supports exact matching, and only goes off of the name and nullability.
412+ class SimpleNamedStaticType implements NamedStaticType {
413+ final bool isNullable;
414+ final String name;
415+
416+ SimpleNamedStaticType (this .name, {this .isNullable = false });
417+
418+ @override
419+ Future <bool > isExactly (covariant SimpleNamedStaticType other) async =>
420+ isNullable == other.isNullable && name == other.name;
421+
422+ @override
423+ Future <bool > isSubtypeOf (covariant StaticType other) =>
424+ throw UnimplementedError ();
425+ }
328426
329427extension _ on Duration {
330428 Duration dividedBy (int amount) =>
0 commit comments