51939f1454
Bug: https://github.com/dart-lang/language/issues/3922 Change-Id: I9d9f6ce898e16e2ed393ae77f0dbcbf9c75fb56d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/372580 Auto-Submit: Jake Macdonald <jakemac@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
704 lines
24 KiB
Dart
704 lines
24 KiB
Dart
// Copyright (c) 2022, 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:test/fake.dart';
|
|
import 'package:test/test.dart';
|
|
|
|
import 'package:_macros/src/api.dart';
|
|
import 'package:_macros/src/executor.dart';
|
|
import 'package:_macros/src/executor/augmentation_library.dart';
|
|
import 'package:_macros/src/executor/introspection_impls.dart';
|
|
import 'package:_macros/src/executor/remote_instance.dart';
|
|
import 'package:_macros/src/executor/response_impls.dart';
|
|
|
|
import '../util.dart';
|
|
|
|
void main() {
|
|
group('AugmentationLibraryBuilder', () {
|
|
final intIdentifier = TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'int',
|
|
kind: IdentifierKind.topLevelMember,
|
|
staticScope: null,
|
|
uri: Uri.parse('dart:core'));
|
|
final objectIdentifier = TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'Object',
|
|
kind: IdentifierKind.topLevelMember,
|
|
staticScope: null,
|
|
uri: Uri.parse('dart:core'));
|
|
final superclassIdentifier = TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'SomeSuperclass',
|
|
kind: IdentifierKind.topLevelMember,
|
|
uri: null,
|
|
staticScope: null);
|
|
final interfaceIdentifiers = [
|
|
for (var i = 0; i < 2; i++)
|
|
TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'I$i',
|
|
kind: IdentifierKind.topLevelMember,
|
|
uri: null,
|
|
staticScope: null),
|
|
];
|
|
final mixinIdentifiers = [
|
|
for (var i = 0; i < 2; i++)
|
|
TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'M$i',
|
|
kind: IdentifierKind.topLevelMember,
|
|
uri: null,
|
|
staticScope: null),
|
|
];
|
|
|
|
test('can combine multiple execution results', () {
|
|
final classes = <IdentifierImpl, ClassDeclaration>{};
|
|
for (var i = 0; i < 2; i++) {
|
|
for (var j = 0; j < 3; j++) {
|
|
final identifier =
|
|
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo$i$j');
|
|
classes[identifier] = ClassDeclarationImpl(
|
|
id: RemoteInstance.uniqueId,
|
|
identifier: identifier,
|
|
library: Fixtures.library,
|
|
metadata: [],
|
|
typeParameters: [],
|
|
interfaces: [],
|
|
hasAbstract: false,
|
|
hasBase: false,
|
|
hasExternal: false,
|
|
hasFinal: false,
|
|
hasInterface: false,
|
|
hasMixin: false,
|
|
hasSealed: false,
|
|
mixins: [],
|
|
superclass: null);
|
|
}
|
|
}
|
|
var results = [
|
|
for (var i = 0; i < 2; i++)
|
|
MacroExecutionResultImpl(
|
|
diagnostics: [],
|
|
enumValueAugmentations: {},
|
|
extendsTypeAugmentations: {
|
|
for (var j in [0, 2])
|
|
classes.keys.firstWhere(
|
|
(identifier) => identifier.name == 'Foo$i$j'):
|
|
NamedTypeAnnotationCode(name: superclassIdentifier),
|
|
},
|
|
interfaceAugmentations: {
|
|
for (var j = 0; j < 3; j++)
|
|
classes.keys
|
|
.firstWhere((identifier) => identifier.name == 'Foo$i$j'): [
|
|
for (var k = 0; k < j; k++)
|
|
NamedTypeAnnotationCode(name: interfaceIdentifiers[k]),
|
|
]
|
|
},
|
|
libraryAugmentations: [
|
|
for (var j = 0; j < 3; j++)
|
|
DeclarationCode.fromParts(
|
|
[intIdentifier, ' get i${i}j$j => ${i + j};\n']),
|
|
],
|
|
mixinAugmentations: {
|
|
for (var j = 0; j < 3; j++)
|
|
classes.keys
|
|
.firstWhere((identifier) => identifier.name == 'Foo$i$j'): [
|
|
for (var k = 0; k < i; k++)
|
|
NamedTypeAnnotationCode(name: mixinIdentifiers[k]),
|
|
]
|
|
},
|
|
newTypeNames: [
|
|
'Foo${i}0',
|
|
'Foo${i}1',
|
|
'Foo${i}2',
|
|
],
|
|
typeAugmentations: {
|
|
for (var j = 0; j < 3; j++)
|
|
classes.keys
|
|
.firstWhere((identifier) => identifier.name == 'Foo$i$j'): [
|
|
DeclarationCode.fromParts([intIdentifier, ' get i => $i;\n']),
|
|
DeclarationCode.fromParts([intIdentifier, ' get j => $j;\n']),
|
|
]
|
|
},
|
|
),
|
|
];
|
|
var library = _TestExecutor().buildAugmentationLibrary(
|
|
Fixtures.library.uri,
|
|
results,
|
|
(Identifier i) => classes[i]!,
|
|
(Identifier i) => (i as TestIdentifier).resolved,
|
|
(OmittedTypeAnnotation i) =>
|
|
(i as TestOmittedTypeAnnotation).inferredType);
|
|
expect(library, equalsIgnoringWhitespace('''
|
|
augment library 'package:foo/bar.dart';
|
|
|
|
import 'dart:core' as prefix0;
|
|
|
|
prefix0.int get i0j0 => 0;
|
|
prefix0.int get i0j1 => 1;
|
|
prefix0.int get i0j2 => 2;
|
|
prefix0.int get i1j0 => 1;
|
|
prefix0.int get i1j1 => 2;
|
|
prefix0.int get i1j2 => 3;
|
|
augment class Foo00 extends SomeSuperclass {
|
|
prefix0.int get i => 0;
|
|
prefix0.int get j => 0;
|
|
}
|
|
augment class Foo02 extends SomeSuperclass implements I0, I1 {
|
|
prefix0.int get i => 0;
|
|
prefix0.int get j => 2;
|
|
}
|
|
augment class Foo10 extends SomeSuperclass with M0 {
|
|
prefix0.int get i => 1;
|
|
prefix0.int get j => 0;
|
|
}
|
|
augment class Foo12 extends SomeSuperclass with M0 implements I0, I1 {
|
|
prefix0.int get i => 1;
|
|
prefix0.int get j => 2;
|
|
}
|
|
augment class Foo01 implements I0 {
|
|
prefix0.int get i => 0;
|
|
prefix0.int get j => 1;
|
|
}
|
|
augment class Foo11 with M0 implements I0 {
|
|
prefix0.int get i => 1;
|
|
prefix0.int get j => 1;
|
|
}
|
|
'''));
|
|
});
|
|
|
|
test('can add imports for identifiers', () {
|
|
var fooIdentifier = TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'Foo',
|
|
kind: IdentifierKind.topLevelMember,
|
|
staticScope: null,
|
|
uri: Uri.parse('package:foo/foo.dart'));
|
|
var barIdentifier = TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'Bar',
|
|
kind: IdentifierKind.topLevelMember,
|
|
staticScope: null,
|
|
uri: Uri.parse('package:bar/bar.dart'));
|
|
var builderIdentifier = TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'Builder',
|
|
kind: IdentifierKind.topLevelMember,
|
|
staticScope: null,
|
|
uri: Uri.parse('package:builder/builder.dart'));
|
|
var barInstanceMember = TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'baz',
|
|
kind: IdentifierKind.instanceMember,
|
|
staticScope: null,
|
|
uri: Uri.parse('package:bar/bar.dart'));
|
|
var barStaticMember = TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'zap',
|
|
kind: IdentifierKind.staticInstanceMember,
|
|
staticScope: 'Bar',
|
|
uri: Uri.parse('package:bar/bar.dart'));
|
|
var results = [
|
|
MacroExecutionResultImpl(
|
|
diagnostics: [],
|
|
enumValueAugmentations: {},
|
|
extendsTypeAugmentations: {},
|
|
interfaceAugmentations: {},
|
|
mixinAugmentations: {},
|
|
typeAugmentations: {},
|
|
libraryAugmentations: [
|
|
DeclarationCode.fromParts([
|
|
'class FooBuilder<T extends ',
|
|
fooIdentifier,
|
|
'> implements ',
|
|
builderIdentifier,
|
|
'<',
|
|
barIdentifier,
|
|
'<T>> {\n',
|
|
'late ',
|
|
intIdentifier,
|
|
' ${barInstanceMember.name};\n',
|
|
barIdentifier,
|
|
'<T> build() => new ',
|
|
barIdentifier,
|
|
'()..',
|
|
barInstanceMember,
|
|
' = ',
|
|
barStaticMember,
|
|
';',
|
|
'\n}',
|
|
]),
|
|
],
|
|
newTypeNames: [
|
|
'FooBuilder',
|
|
],
|
|
)
|
|
];
|
|
var library = _TestExecutor().buildAugmentationLibrary(
|
|
Fixtures.library.uri,
|
|
results,
|
|
(_) => throw UnimplementedError(),
|
|
(Identifier i) => (i as TestIdentifier).resolved,
|
|
(OmittedTypeAnnotation i) =>
|
|
(i as TestOmittedTypeAnnotation).inferredType);
|
|
expect(library, equalsIgnoringWhitespace('''
|
|
augment library 'package:foo/bar.dart';
|
|
|
|
import 'package:foo/foo.dart' as prefix0;
|
|
import 'package:builder/builder.dart' as prefix1;
|
|
import 'package:bar/bar.dart' as prefix2;
|
|
import 'dart:core' as prefix3;
|
|
|
|
class FooBuilder<T extends prefix0.Foo> implements prefix1.Builder<prefix2.Bar<T>> {
|
|
late prefix3.int baz;
|
|
|
|
prefix2.Bar<T> build() => new prefix2.Bar()..baz = prefix2.Bar.zap;
|
|
}
|
|
'''));
|
|
});
|
|
|
|
test('can handle omitted type annotations', () {
|
|
var results = [
|
|
MacroExecutionResultImpl(
|
|
diagnostics: [],
|
|
enumValueAugmentations: {},
|
|
extendsTypeAugmentations: {},
|
|
interfaceAugmentations: {},
|
|
mixinAugmentations: {},
|
|
typeAugmentations: {},
|
|
libraryAugmentations: [
|
|
DeclarationCode.fromParts([
|
|
OmittedTypeAnnotationCode(
|
|
TestOmittedTypeAnnotation(NamedTypeAnnotationImpl(
|
|
id: RemoteInstance.uniqueId,
|
|
identifier: intIdentifier,
|
|
isNullable: false,
|
|
typeArguments: [],
|
|
))),
|
|
' x = 1;',
|
|
]),
|
|
],
|
|
newTypeNames: []),
|
|
];
|
|
var library = _TestExecutor().buildAugmentationLibrary(
|
|
Fixtures.library.uri,
|
|
results,
|
|
(_) => throw UnimplementedError(),
|
|
(Identifier i) => (i as TestIdentifier).resolved,
|
|
(OmittedTypeAnnotation i) =>
|
|
(i as TestOmittedTypeAnnotation).inferredType);
|
|
expect(library, equalsIgnoringWhitespace('''
|
|
augment library 'package:foo/bar.dart';
|
|
|
|
import 'dart:core' as prefix0;
|
|
|
|
prefix0.int x = 1;
|
|
'''));
|
|
});
|
|
|
|
test('can handle name conflicts', () {
|
|
var omittedType0 = TestOmittedTypeAnnotation();
|
|
var omittedType1 = TestOmittedTypeAnnotation();
|
|
|
|
var omittedTypeIdentifier = TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'OmittedType',
|
|
kind: IdentifierKind.topLevelMember,
|
|
staticScope: null,
|
|
uri: Uri.parse('package:foo/foo.dart'));
|
|
var omittedTypeIdentifier0 = TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'OmittedType0',
|
|
kind: IdentifierKind.topLevelMember,
|
|
staticScope: null,
|
|
uri: Uri.parse('package:bar/bar.dart'));
|
|
var prefixInstanceMember = TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'prefix',
|
|
kind: IdentifierKind.instanceMember,
|
|
staticScope: null,
|
|
uri: Uri.parse('package:bar/bar.dart'));
|
|
var prefix0InstanceMember = TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'prefix0',
|
|
kind: IdentifierKind.instanceMember,
|
|
staticScope: null,
|
|
uri: Uri.parse('package:bar/bar.dart'));
|
|
var prefix1StaticMember = TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'prefix1',
|
|
kind: IdentifierKind.staticInstanceMember,
|
|
staticScope: 'OmittedType1',
|
|
uri: Uri.parse('package:bar/bar.dart'));
|
|
var results = [
|
|
MacroExecutionResultImpl(
|
|
diagnostics: [],
|
|
enumValueAugmentations: {},
|
|
extendsTypeAugmentations: {},
|
|
interfaceAugmentations: {},
|
|
mixinAugmentations: {},
|
|
typeAugmentations: {},
|
|
libraryAugmentations: [
|
|
DeclarationCode.fromParts([
|
|
'class OmittedType {\n ',
|
|
omittedType0.code,
|
|
' method(',
|
|
omittedType1.code,
|
|
' o) {\n ',
|
|
intIdentifier,
|
|
' ${prefixInstanceMember.name} = 0;\n ',
|
|
omittedTypeIdentifier,
|
|
' ${prefix0InstanceMember.name} = ',
|
|
'new ',
|
|
omittedTypeIdentifier,
|
|
'();\n ',
|
|
'new ',
|
|
omittedTypeIdentifier0,
|
|
'()..',
|
|
prefixInstanceMember,
|
|
' = ',
|
|
prefix1StaticMember,
|
|
';',
|
|
'\n }',
|
|
'\n}',
|
|
]),
|
|
],
|
|
newTypeNames: [
|
|
'OmittedType',
|
|
],
|
|
)
|
|
];
|
|
var omittedTypes = <OmittedTypeAnnotation, String>{};
|
|
var library = _TestExecutor().buildAugmentationLibrary(
|
|
Fixtures.library.uri,
|
|
results,
|
|
(_) => throw UnimplementedError(),
|
|
(Identifier i) => (i as TestIdentifier).resolved,
|
|
(OmittedTypeAnnotation i) =>
|
|
(i as TestOmittedTypeAnnotation).inferredType,
|
|
omittedTypes: omittedTypes);
|
|
expect(library, equalsIgnoringWhitespace('''
|
|
augment library 'package:foo/bar.dart';
|
|
|
|
import 'dart:core' as prefix2_0;
|
|
import 'package:foo/foo.dart' as prefix2_1;
|
|
import 'package:bar/bar.dart' as prefix2_2;
|
|
|
|
class OmittedType {
|
|
OmittedType2_0 method(OmittedType2_1 o) {
|
|
prefix2_0.int prefix = 0;
|
|
prefix2_1.OmittedType prefix0 = new prefix2_1.OmittedType();
|
|
new prefix2_2.OmittedType0()..prefix = prefix2_2.OmittedType1.prefix1;
|
|
}
|
|
}
|
|
'''));
|
|
expect(omittedTypes[omittedType0], 'OmittedType2_0');
|
|
expect(omittedTypes[omittedType1], 'OmittedType2_1');
|
|
});
|
|
|
|
test('can augment enums and enum values', () async {
|
|
final myEnum = EnumDeclarationImpl(
|
|
id: RemoteInstance.uniqueId,
|
|
identifier: TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'MyEnum',
|
|
kind: IdentifierKind.topLevelMember,
|
|
uri: Uri.parse('a.dart'),
|
|
staticScope: null),
|
|
library: Fixtures.library,
|
|
metadata: [],
|
|
typeParameters: [],
|
|
interfaces: [],
|
|
mixins: [],
|
|
);
|
|
final myField = FieldDeclarationImpl(
|
|
id: RemoteInstance.uniqueId,
|
|
identifier: TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'value',
|
|
kind: IdentifierKind.instanceMember,
|
|
uri: Uri.parse('a.dart'),
|
|
staticScope: null),
|
|
library: Fixtures.library,
|
|
metadata: [],
|
|
definingType: myEnum.identifier,
|
|
hasAbstract: false,
|
|
hasConst: false,
|
|
hasExternal: false,
|
|
hasFinal: true,
|
|
hasInitializer: false,
|
|
hasLate: false,
|
|
hasStatic: false,
|
|
type: NamedTypeAnnotationImpl(
|
|
id: RemoteInstance.uniqueId,
|
|
isNullable: false,
|
|
identifier: intIdentifier,
|
|
typeArguments: []));
|
|
|
|
var results = [
|
|
MacroExecutionResultImpl(diagnostics: [], enumValueAugmentations: {
|
|
myEnum.identifier: [
|
|
DeclarationCode.fromParts(['a(1),\n']),
|
|
],
|
|
}, extendsTypeAugmentations: {}, typeAugmentations: {
|
|
myEnum.identifier: [
|
|
DeclarationCode.fromParts(['MyEnum(', myField.identifier, ');\n']),
|
|
DeclarationCode.fromParts(
|
|
['final ', intIdentifier, ' ', myField.identifier.name, ';\n']),
|
|
],
|
|
}, interfaceAugmentations: {
|
|
myEnum.identifier: [
|
|
NamedTypeAnnotationCode(name: interfaceIdentifiers.first),
|
|
],
|
|
}, mixinAugmentations: {
|
|
myEnum.identifier: [
|
|
NamedTypeAnnotationCode(name: mixinIdentifiers.first),
|
|
],
|
|
}, newTypeNames: [], libraryAugmentations: []),
|
|
];
|
|
var library = _TestExecutor().buildAugmentationLibrary(
|
|
Fixtures.library.uri,
|
|
results,
|
|
(Identifier i) =>
|
|
i == myEnum.identifier ? myEnum : throw UnimplementedError(),
|
|
(Identifier i) => (i as TestIdentifier).resolved,
|
|
(OmittedTypeAnnotation i) =>
|
|
(i as TestOmittedTypeAnnotation).inferredType);
|
|
expect(library, equalsIgnoringWhitespace('''
|
|
augment library 'package:foo/bar.dart';
|
|
|
|
import 'a.dart' as prefix0;
|
|
import 'dart:core' as prefix1;
|
|
|
|
augment enum MyEnum with M0 implements I0 {
|
|
a(1),
|
|
;
|
|
MyEnum(this.value);
|
|
final prefix1.int value;
|
|
}
|
|
'''));
|
|
});
|
|
|
|
test('can augment extensions', () async {
|
|
final myExtension = ExtensionDeclarationImpl(
|
|
id: RemoteInstance.uniqueId,
|
|
identifier: TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'MyExtension',
|
|
kind: IdentifierKind.topLevelMember,
|
|
uri: Uri.parse('a.dart'),
|
|
staticScope: null),
|
|
library: Fixtures.library,
|
|
metadata: [],
|
|
typeParameters: [],
|
|
onType: Fixtures.myClassType,
|
|
);
|
|
final myGetter = MethodDeclarationImpl(
|
|
id: RemoteInstance.uniqueId,
|
|
identifier: TestIdentifier(
|
|
id: RemoteInstance.uniqueId,
|
|
name: 'x',
|
|
kind: IdentifierKind.instanceMember,
|
|
uri: Uri.parse('a.dart'),
|
|
staticScope: null),
|
|
library: Fixtures.library,
|
|
metadata: [],
|
|
definingType: myExtension.identifier,
|
|
hasExternal: false,
|
|
hasStatic: false,
|
|
returnType: NamedTypeAnnotationImpl(
|
|
id: RemoteInstance.uniqueId,
|
|
isNullable: false,
|
|
identifier: intIdentifier,
|
|
typeArguments: []),
|
|
hasBody: true,
|
|
isGetter: true,
|
|
isOperator: false,
|
|
isSetter: false,
|
|
namedParameters: [],
|
|
positionalParameters: [],
|
|
typeParameters: []);
|
|
|
|
var results = [
|
|
MacroExecutionResultImpl(
|
|
diagnostics: [],
|
|
enumValueAugmentations: {},
|
|
extendsTypeAugmentations: {},
|
|
typeAugmentations: {
|
|
myExtension.identifier: [
|
|
DeclarationCode.fromParts([
|
|
intIdentifier,
|
|
' get ',
|
|
myGetter.identifier.name,
|
|
' => 1;\n'
|
|
]),
|
|
],
|
|
},
|
|
interfaceAugmentations: {},
|
|
mixinAugmentations: {},
|
|
newTypeNames: [],
|
|
libraryAugmentations: []),
|
|
];
|
|
var library = _TestExecutor().buildAugmentationLibrary(
|
|
Fixtures.library.uri,
|
|
results,
|
|
(Identifier i) => i == myExtension.identifier
|
|
? myExtension
|
|
: throw UnimplementedError(),
|
|
(Identifier i) => (i as TestIdentifier).resolved,
|
|
(OmittedTypeAnnotation i) =>
|
|
(i as TestOmittedTypeAnnotation).inferredType);
|
|
expect(library, equalsIgnoringWhitespace('''
|
|
augment library 'package:foo/bar.dart';
|
|
|
|
import 'dart:core' as prefix0;
|
|
|
|
augment extension MyExtension {
|
|
prefix0.int get x => 1;
|
|
}
|
|
'''));
|
|
});
|
|
|
|
test('copies keywords for classes', () async {
|
|
for (final hasKeywords in [true, false]) {
|
|
final clazz = ClassDeclarationImpl(
|
|
id: RemoteInstance.uniqueId,
|
|
identifier:
|
|
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'MyClass'),
|
|
library: Fixtures.library,
|
|
metadata: [],
|
|
typeParameters: [],
|
|
interfaces: [],
|
|
hasAbstract: hasKeywords,
|
|
hasBase: hasKeywords,
|
|
hasExternal: hasKeywords,
|
|
hasFinal: hasKeywords,
|
|
hasInterface: hasKeywords,
|
|
hasMixin: hasKeywords,
|
|
hasSealed: hasKeywords,
|
|
mixins: [],
|
|
superclass: null);
|
|
|
|
var results = [
|
|
MacroExecutionResultImpl(
|
|
diagnostics: [],
|
|
enumValueAugmentations: {},
|
|
extendsTypeAugmentations: {},
|
|
typeAugmentations: {
|
|
clazz.identifier: [
|
|
DeclarationCode.fromParts(['']),
|
|
]
|
|
},
|
|
interfaceAugmentations: {},
|
|
mixinAugmentations: {},
|
|
newTypeNames: [],
|
|
libraryAugmentations: []),
|
|
];
|
|
var library = _TestExecutor().buildAugmentationLibrary(
|
|
Fixtures.library.uri,
|
|
results,
|
|
(Identifier i) =>
|
|
i == clazz.identifier ? clazz : throw UnimplementedError(),
|
|
(Identifier i) => (i as TestIdentifier).resolved,
|
|
(OmittedTypeAnnotation i) =>
|
|
(i as TestOmittedTypeAnnotation).inferredType);
|
|
final expectedKeywords = [
|
|
if (hasKeywords) ...[
|
|
'abstract',
|
|
'base',
|
|
'external',
|
|
'final',
|
|
'interface',
|
|
'mixin',
|
|
'sealed'
|
|
]
|
|
];
|
|
// Add extra space after, if we have keywords
|
|
if (expectedKeywords.isNotEmpty) expectedKeywords.add('');
|
|
expect(library, equalsIgnoringWhitespace('''
|
|
augment library 'package:foo/bar.dart';
|
|
|
|
augment ${expectedKeywords.join(' ')}class MyClass {
|
|
}
|
|
'''));
|
|
}
|
|
});
|
|
|
|
test('copies generic types and bounds', () async {
|
|
final clazz = ClassDeclarationImpl(
|
|
id: RemoteInstance.uniqueId,
|
|
identifier:
|
|
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'MyClass'),
|
|
library: Fixtures.library,
|
|
metadata: [],
|
|
typeParameters: [
|
|
TypeParameterDeclarationImpl(
|
|
id: RemoteInstance.uniqueId,
|
|
identifier:
|
|
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'T'),
|
|
library: Fixtures.library,
|
|
metadata: [],
|
|
bound: NamedTypeAnnotationImpl(
|
|
id: RemoteInstance.uniqueId,
|
|
isNullable: false,
|
|
identifier: objectIdentifier,
|
|
typeArguments: [])),
|
|
TypeParameterDeclarationImpl(
|
|
id: RemoteInstance.uniqueId,
|
|
identifier:
|
|
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'S'),
|
|
library: Fixtures.library,
|
|
metadata: [],
|
|
bound: null),
|
|
],
|
|
interfaces: [],
|
|
hasAbstract: false,
|
|
hasBase: false,
|
|
hasExternal: false,
|
|
hasFinal: false,
|
|
hasInterface: false,
|
|
hasMixin: false,
|
|
hasSealed: false,
|
|
mixins: [],
|
|
superclass: null);
|
|
|
|
var results = [
|
|
MacroExecutionResultImpl(
|
|
diagnostics: [],
|
|
enumValueAugmentations: {},
|
|
extendsTypeAugmentations: {},
|
|
typeAugmentations: {
|
|
clazz.identifier: [
|
|
DeclarationCode.fromParts(['']),
|
|
]
|
|
},
|
|
interfaceAugmentations: {},
|
|
mixinAugmentations: {},
|
|
newTypeNames: [],
|
|
libraryAugmentations: []),
|
|
];
|
|
var library = _TestExecutor().buildAugmentationLibrary(
|
|
Fixtures.library.uri,
|
|
results,
|
|
(Identifier i) =>
|
|
i == clazz.identifier ? clazz : throw UnimplementedError(),
|
|
(Identifier i) => (i as TestIdentifier).resolved,
|
|
(OmittedTypeAnnotation i) =>
|
|
(i as TestOmittedTypeAnnotation).inferredType);
|
|
expect(library, equalsIgnoringWhitespace('''
|
|
augment library 'package:foo/bar.dart';
|
|
|
|
import 'dart:core' as prefix0;
|
|
|
|
augment class MyClass<T extends prefix0.Object, S> {
|
|
}
|
|
'''));
|
|
});
|
|
});
|
|
}
|
|
|
|
class _TestExecutor extends MacroExecutor
|
|
with AugmentationLibraryBuilder, Fake {}
|