blob: 84ddb7af24d98beabfa7ad247be0a2476fd57b72 [file] [log] [blame]
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'package:_fe_analyzer_shared/src/macros/api.dart';
/// A very simple macro that annotates functions (or getters) with no arguments
/// and adds a print statement to the top of them.
class SimpleMacro implements MethodDefinitionMacro {
final int? x;
final int? y;
SimpleMacro([this.x, this.y]);
SimpleMacro.named({this.x, this.y});
@override
FutureOr<void> buildDefinitionForMethod(
MethodDeclaration method, FunctionDefinitionBuilder builder) async {
if (method.namedParameters
.followedBy(method.positionalParameters)
.isNotEmpty) {
throw ArgumentError(
'This macro can only be run on functions with no arguments!');
}
// Test the type resolver and static type interfaces
var staticReturnType = await builder.resolve(method.returnType);
if (!(await staticReturnType.isExactly(staticReturnType))) {
throw StateError('The return type should be exactly equal to itself!');
}
if (!(await staticReturnType.isSubtypeOf(staticReturnType))) {
throw StateError('The return type should be a subtype of itself!');
}
var classType =
await builder.resolve(method.definingClass) as NamedStaticType;
if (await staticReturnType.isExactly(classType)) {
throw StateError(
'The return type should not be exactly equal to the class type');
}
if (await staticReturnType.isSubtypeOf(classType)) {
throw StateError(
'The return type should not be a subtype of the class type!');
}
// Test the type declaration resolver
var parentClass =
await builder.declarationOf(classType) as ClassDeclaration;
// Test the class introspector
var superClass = (await builder.superclassOf(parentClass))!;
var interfaces = (await builder.interfacesOf(parentClass));
var mixins = (await builder.mixinsOf(parentClass));
var fields = (await builder.fieldsOf(parentClass));
var methods = (await builder.methodsOf(parentClass));
var constructors = (await builder.constructorsOf(parentClass));
builder.augment(FunctionBodyCode.fromParts([
'''{
print('x: $x, y: $y');
print('parentClass: ${parentClass.name}');
print('superClass: ${superClass.name}');''',
for (var interface in interfaces)
"\n print('interface: ${interface.name}');",
for (var mixin in mixins) "\n print('mixin: ${mixin.name}');",
for (var field in fields) "\n print('field: ${field.name}');",
for (var method in methods) "\n print('method: ${method.name}');",
for (var constructor in constructors)
"\n print('constructor: ${constructor.name}');",
'''
\n return augment super();
}''',
]));
}
}