blob: fa15633c3cc5a684bb40eff7b4f7fb1b04db34c2 [file] [edit]
// Copyright (c) 2024, 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 'package:expect/expect.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/transformations/track_widget_constructor_locations.dart';
void main() {
final Uri developerUri = Uri.parse('dart:developer');
final Library developerLib = new Library(developerUri, fileUri: developerUri);
final Class hasCreationLocationClass = new Class(
name: '_HasCreationLocation',
isAbstract: true,
fileUri: developerUri,
);
developerLib.addClass(hasCreationLocationClass);
final Class creationLocationClass = new Class(
name: 'CreationLocation',
fileUri: developerUri,
);
final Constructor creationLocationConstructor = new Constructor(
new FunctionNode(
null,
namedParameters: [
new VariableDeclaration('file', type: const DynamicType()),
new VariableDeclaration('line', type: const DynamicType()),
new VariableDeclaration('column', type: const DynamicType()),
new VariableDeclaration('name', type: const DynamicType()),
],
),
name: new Name('_', developerLib),
fileUri: developerUri,
);
creationLocationClass.addConstructor(creationLocationConstructor);
developerLib.addClass(creationLocationClass);
final Uri coreUri = Uri.parse('dart:core');
final Library coreLib = new Library(coreUri, fileUri: coreUri);
final Class pragmaClass = new Class(name: 'pragma', fileUri: coreUri);
coreLib.addClass(pragmaClass);
final Field pragmaNameField = new Field.immutable(
new Name('name'),
fileUri: coreUri,
);
pragmaClass.addField(pragmaNameField);
final Uri testUri = Uri.parse('package:test/test.dart');
final Library testLib = new Library(testUri, fileUri: testUri);
final Class myWidgetClass = new Class(name: 'MyWidget', fileUri: testUri);
myWidgetClass.addAnnotation(
new ConstantExpression(
new InstanceConstant(
pragmaClass.reference,
<DartType>[],
<Reference, Constant>{
pragmaNameField.fieldReference: new StringConstant(
'track-creation-locations',
),
},
),
),
);
myWidgetClass.addConstructor(
new Constructor(
new FunctionNode(new Block([])),
name: new Name(''),
fileUri: testUri,
),
);
testLib.addClass(myWidgetClass);
const int fileOffset = 100;
final Procedure mainProcedure = new Procedure(
new Name('main'),
ProcedureKind.Method,
new FunctionNode(
new Block([
new ExpressionStatement(
new ConstructorInvocation(
myWidgetClass.constructors.first,
new Arguments([]),
)..fileOffset = fileOffset,
),
]),
),
isStatic: true,
fileUri: testUri,
);
testLib.addProcedure(mainProcedure);
final WidgetCreatorTracker tracker = new WidgetCreatorTracker();
tracker.transform([testLib], [developerLib, testLib], null);
// Verification
Expect.isTrue(
myWidgetClass.implementedTypes.any(
(s) => s.classNode == hasCreationLocationClass,
),
);
Expect.isTrue(myWidgetClass.fields.any((f) => f.name.text == '_location'));
final Constructor constructor = myWidgetClass.constructors.first;
const String creationLocationPrefix = r'$creationLocation';
Expect.isTrue(
constructor.function.namedParameters.any(
(p) => p.name!.startsWith(creationLocationPrefix),
),
);
final Block body = mainProcedure.function.body as Block;
final ExpressionStatement stmt = body.statements.first as ExpressionStatement;
final ConstructorInvocation invocation =
stmt.expression as ConstructorInvocation;
Expect.isTrue(
invocation.arguments.named.any(
(n) => n.name.startsWith(creationLocationPrefix),
),
);
final NamedExpression namedArg = invocation.arguments.named.firstWhere(
(n) => n.name.startsWith(creationLocationPrefix),
);
Expect.isTrue(namedArg.value is ConstructorInvocation);
final ConstructorInvocation locInvocation =
namedArg.value as ConstructorInvocation;
Expect.equals(creationLocationClass, locInvocation.target.enclosingClass);
}