blob: 81f33e1c0c8d94518ab7a6639de6830f2a168554 [file] [log] [blame]
// 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:analyzer/src/error/codes.dart';
import 'package:analyzer/src/summary2/macro_application.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../../generated/test_support.dart';
import '../../summary/macros_environment.dart';
import 'context_collection_resolution.dart';
import 'resolution.dart';
main() {
try {
MacrosEnvironment.instance;
} catch (_) {
print('Cannot initialize environment. Skip macros tests.');
return;
}
defineReflectiveSuite(() {
defineReflectiveTests(MacroResolutionTest);
});
}
@reflectiveTest
class MacroResolutionTest extends PubPackageResolutionTest {
@override
void setUp() {
super.setUp();
writeTestPackageConfig(
PackageConfigFileBuilder(),
macrosEnvironment: MacrosEnvironment.instance,
);
newFile(
'$testPackageLibPath/append.dart',
getMacroCode('append.dart'),
);
newFile(
'$testPackageLibPath/diagnostic.dart',
getMacroCode('diagnostic.dart'),
);
newFile(
'$testPackageLibPath/order.dart',
getMacroCode('order.dart'),
);
newFile(
'$testPackageLibPath/json_serializable.dart',
getMacroCode('example/json_serializable.dart'),
);
}
test_declareType_class() async {
await assertNoErrorsInCode(r'''
import 'append.dart';
@DeclareType('B', 'class B {}')
class A {}
void f(B b) {}
''');
}
test_diagnostic_compilesWithError() async {
newFile('$testPackageLibPath/a.dart', r'''
import 'package:macros/macros.dart';
macro class MyMacro implements ClassTypesMacro {
const MyMacro();
buildTypesForClass(clazz, builder) {
unresolved;
}
}
''');
await assertErrorsInCode('''
import 'a.dart';
@MyMacro()
class A {}
''', [
error(
CompileTimeErrorCode.MACRO_ERROR,
18,
10,
messageContains: [
'Macro application failed due to a bug in the macro.',
],
contextMessages: [
ExpectedContextMessage(testFile, 18, 10, textContains: [
'package:test/a.dart',
'MyMacro',
'unresolved',
]),
],
),
]);
}
test_diagnostic_cycle_class_constructorsOf() async {
// Note, the errors are also reported when introspecting `A1` and `A2`
// during running macro applications on `A3`, because we know that
// `A1` and `A2` declarations are incomplete.
await assertErrorsInCode('''
import 'order.dart';
@DeclarationsIntrospectConstructors('A2')
class A1 {}
@DeclarationsIntrospectConstructors('A1')
class A2 {}
@DeclarationsIntrospectConstructors('A1')
@DeclarationsIntrospectConstructors('A2')
class A3 {}
''', [
error(
CompileTimeErrorCode.MACRO_DECLARATIONS_PHASE_INTROSPECTION_CYCLE,
23,
34,
messageContains: ["'A2'"],
contextMessages: [message(testFile, 23, 34), message(testFile, 78, 34)],
),
error(
CompileTimeErrorCode.MACRO_DECLARATIONS_PHASE_INTROSPECTION_CYCLE,
78,
34,
messageContains: ["'A1'"],
contextMessages: [message(testFile, 23, 34), message(testFile, 78, 34)],
),
error(
CompileTimeErrorCode.MACRO_DECLARATIONS_PHASE_INTROSPECTION_CYCLE,
133,
34,
messageContains: ["'A1'"],
contextMessages: [message(testFile, 23, 34), message(testFile, 78, 34)],
),
error(
CompileTimeErrorCode.MACRO_DECLARATIONS_PHASE_INTROSPECTION_CYCLE,
175,
34,
messageContains: ["'A2'"],
contextMessages: [message(testFile, 23, 34), message(testFile, 78, 34)],
),
]);
}
test_diagnostic_cycle_class_fieldsOf() async {
// Note, the errors are also reported when introspecting `A1` and `A2`
// during running macro applications on `A3`, because we know that
// `A1` and `A2` declarations are incomplete.
await assertErrorsInCode('''
import 'order.dart';
@DeclarationsIntrospectFields('A2')
class A1 {}
@DeclarationsIntrospectFields('A1')
class A2 {}
@DeclarationsIntrospectFields('A1')
@DeclarationsIntrospectFields('A2')
class A3 {}
''', [
error(
CompileTimeErrorCode.MACRO_DECLARATIONS_PHASE_INTROSPECTION_CYCLE,
23,
28,
messageContains: ["'A2'"],
contextMessages: [message(testFile, 23, 28), message(testFile, 72, 28)],
),
error(
CompileTimeErrorCode.MACRO_DECLARATIONS_PHASE_INTROSPECTION_CYCLE,
72,
28,
messageContains: ["'A1'"],
contextMessages: [message(testFile, 23, 28), message(testFile, 72, 28)],
),
error(
CompileTimeErrorCode.MACRO_DECLARATIONS_PHASE_INTROSPECTION_CYCLE,
121,
28,
messageContains: ["'A1'"],
contextMessages: [message(testFile, 23, 28), message(testFile, 72, 28)],
),
error(
CompileTimeErrorCode.MACRO_DECLARATIONS_PHASE_INTROSPECTION_CYCLE,
157,
28,
messageContains: ["'A2'"],
contextMessages: [message(testFile, 23, 28), message(testFile, 72, 28)],
),
]);
}
test_diagnostic_cycle_class_methodsOf() async {
// Note, the errors are also reported when introspecting `A1` and `A2`
// during running macro applications on `A3`, because we know that
// `A1` and `A2` declarations are incomplete.
await assertErrorsInCode('''
import 'order.dart';
@DeclarationsIntrospectMethods('A2')
class A1 {}
@DeclarationsIntrospectMethods('A1')
class A2 {}
@DeclarationsIntrospectMethods('A1')
@DeclarationsIntrospectMethods('A2')
class A3 {}
''', [
error(
CompileTimeErrorCode.MACRO_DECLARATIONS_PHASE_INTROSPECTION_CYCLE,
23,
29,
messageContains: ["'A2'"],
contextMessages: [message(testFile, 23, 29), message(testFile, 73, 29)],
),
error(
CompileTimeErrorCode.MACRO_DECLARATIONS_PHASE_INTROSPECTION_CYCLE,
73,
29,
messageContains: ["'A1'"],
contextMessages: [message(testFile, 23, 29), message(testFile, 73, 29)],
),
error(
CompileTimeErrorCode.MACRO_DECLARATIONS_PHASE_INTROSPECTION_CYCLE,
123,
29,
messageContains: ["'A1'"],
contextMessages: [message(testFile, 23, 29), message(testFile, 73, 29)],
),
error(
CompileTimeErrorCode.MACRO_DECLARATIONS_PHASE_INTROSPECTION_CYCLE,
160,
29,
messageContains: ["'A2'"],
contextMessages: [message(testFile, 23, 29), message(testFile, 73, 29)],
),
]);
}
test_diagnostic_definitionApplication_sameLibrary() async {
await assertErrorsInCode('''
import 'package:macros/macros.dart';
macro class MyMacro implements ClassDefinitionMacro {
const MyMacro();
@override
buildDefinitionForClass(declaration, builder) async {}
}
@MyMacro()
class A {}
''', [
error(
CompileTimeErrorCode.MACRO_DEFINITION_APPLICATION_SAME_LIBRARY_CYCLE,
185,
7),
]);
}
test_diagnostic_definitionApplication_sameLibraryCycle() async {
newFile('$testPackageLibPath/a.dart', r'''
import 'package:macros/macros.dart';
import 'test.dart';
macro class MyMacro implements ClassDefinitionMacro {
const MyMacro();
@override
buildDefinitionForClass(declaration, builder) async {}
}
''');
await assertErrorsInCode('''
import 'a.dart';
@MyMacro()
class A {}
''', [
error(
CompileTimeErrorCode.MACRO_DEFINITION_APPLICATION_SAME_LIBRARY_CYCLE,
19,
7),
]);
}
test_diagnostic_invalidTarget_wantsClassOrMixin_hasFunction() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@TargetClassOrMixinMacro()
void f() {}
''', [
error(CompileTimeErrorCode.INVALID_MACRO_APPLICATION_TARGET, 27, 26),
]);
}
test_diagnostic_invalidTarget_wantsClassOrMixin_hasLibrary() async {
await assertErrorsInCode('''
@TargetClassOrMixinMacro()
library;
import 'diagnostic.dart';
''', [
error(CompileTimeErrorCode.INVALID_MACRO_APPLICATION_TARGET, 0, 26),
]);
}
test_diagnostic_notAllowedDeclaration_declarations_class() async {
await assertErrorsInCode('''
import 'append.dart';
class A {
@DeclareInLibrary('class B {}')
void foo() {}
}
''', [
error(CompileTimeErrorCode.MACRO_NOT_ALLOWED_DECLARATION, 35, 31),
]);
}
test_diagnostic_notSupportedArgument() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
class A {
@ReportAtTargetDeclaration()
void foo() {}
}
''', [
error(WarningCode.MACRO_WARNING, 75, 3),
]);
}
test_diagnostic_report_argumentError_instanceCreation() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@MacroWithArguments(0, const Object())
class A {}
''', [
error(CompileTimeErrorCode.MACRO_APPLICATION_ARGUMENT_ERROR, 50, 14),
]);
}
test_diagnostic_report_atDeclaration_class_error() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportErrorAtTargetDeclaration()
class A {}
''', [
error(CompileTimeErrorCode.MACRO_ERROR, 67, 1,
correctionContains: 'Correction message'),
]);
}
test_diagnostic_report_atDeclaration_class_info() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportInfoAtTargetDeclaration()
class A {}
''', [
error(HintCode.MACRO_INFO, 66, 1,
correctionContains: 'Correction message'),
]);
}
test_diagnostic_report_atDeclaration_class_warning() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTargetDeclaration()
class A {}
''', [
error(WarningCode.MACRO_WARNING, 62, 1,
correctionContains: 'Correction message'),
]);
}
test_diagnostic_report_atDeclaration_constructor() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
class A {
@ReportAtTargetDeclaration()
A.named();
}
''', [
error(WarningCode.MACRO_WARNING, 72, 5),
]);
}
test_diagnostic_report_atDeclaration_field() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
class A {
@ReportAtTargetDeclaration()
final foo = 0;
}
''', [
error(WarningCode.MACRO_WARNING, 76, 3),
]);
}
test_diagnostic_report_atDeclaration_method() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
class A {
@ReportAtTargetDeclaration()
void foo() {}
}
''', [
error(WarningCode.MACRO_WARNING, 75, 3),
]);
}
test_diagnostic_report_atDeclaration_mixin() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTargetDeclaration()
mixin A {}
''', [
error(WarningCode.MACRO_WARNING, 62, 1),
]);
}
test_diagnostic_report_atTarget_method() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtFirstMethod()
class A {
void foo() {}
void bar() {}
}
''', [
error(WarningCode.MACRO_WARNING, 67, 3),
]);
}
test_diagnostic_report_atTypeAnnotation_class_extends() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTypeAnnotation([
'superclass',
])
class A extends Object {}
''', [
error(WarningCode.MACRO_WARNING, 88, 6),
]);
}
test_diagnostic_report_atTypeAnnotation_field_type() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
class A {
@ReportAtTypeAnnotation([
'variableType',
])
int foo = 0;
}
''', [
error(WarningCode.MACRO_WARNING, 92, 3),
]);
}
test_diagnostic_report_atTypeAnnotation_function_formalParameter_named() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTypeAnnotation([
'namedFormalParameterType 0',
])
void foo(int a, {String? b, bool? c}) {}
''', [
error(WarningCode.MACRO_WARNING, 105, 7),
]);
}
test_diagnostic_report_atTypeAnnotation_function_formalParameter_positional() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTypeAnnotation([
'positionalFormalParameterType 1',
])
void foo(int a, String b) {}
''', [
error(WarningCode.MACRO_WARNING, 109, 6),
]);
}
test_diagnostic_report_atTypeAnnotation_function_returnType() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTypeAnnotation([
'returnType',
])
int foo() => 0;
''', [
error(WarningCode.MACRO_WARNING, 72, 3),
]);
}
test_diagnostic_report_atTypeAnnotation_functionType_formalParameter_named() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTypeAnnotation([
'returnType',
'namedFormalParameterType 1',
])
int Function(bool a, {int b, String c}) foo() => throw 0;
''', [
error(WarningCode.MACRO_WARNING, 133, 6),
]);
}
test_diagnostic_report_atTypeAnnotation_functionType_formalParameter_positional() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTypeAnnotation([
'returnType',
'positionalFormalParameterType 1',
])
int Function(int a, String b) foo() => throw 0;
''', [
error(WarningCode.MACRO_WARNING, 129, 6),
]);
}
test_diagnostic_report_atTypeAnnotation_functionType_formalParameter_positional2() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTypeAnnotation([
'returnType',
'positionalFormalParameterType 1',
])
int Function(int, String) foo() => throw 0;
''', [
error(WarningCode.MACRO_WARNING, 127, 6),
]);
}
test_diagnostic_report_atTypeAnnotation_functionType_returnType() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTypeAnnotation([
'returnType',
'returnType',
])
int Function() foo() => throw 0;
''', [
error(WarningCode.MACRO_WARNING, 88, 3),
]);
}
test_diagnostic_report_atTypeAnnotation_kind_functionType() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTypeAnnotation([
'returnType',
])
void Function() foo() => throw 0;
''', [
error(WarningCode.MACRO_WARNING, 72, 15),
]);
}
test_diagnostic_report_atTypeAnnotation_kind_omittedType_fieldType() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
class A {
@ReportAtTypeAnnotation([
'variableType',
])
final foo = 0;
}
''', [
error(WarningCode.MACRO_WARNING, 98, 3),
]);
}
test_diagnostic_report_atTypeAnnotation_kind_omittedType_formalParameterType() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTypeAnnotation([
'positionalFormalParameterType 0',
])
void foo(a) {}
''', [
error(WarningCode.MACRO_WARNING, 102, 1),
]);
}
test_diagnostic_report_atTypeAnnotation_kind_omittedType_functionReturnType() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTypeAnnotation([
'returnType',
])
foo() => throw 0;
''', [
error(WarningCode.MACRO_WARNING, 72, 3),
]);
}
test_diagnostic_report_atTypeAnnotation_kind_omittedType_methodReturnType() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
class A {
@ReportAtTypeAnnotation([
'returnType',
])
foo() => throw 0;
}
''', [
error(WarningCode.MACRO_WARNING, 90, 3),
]);
}
test_diagnostic_report_atTypeAnnotation_kind_omittedType_topLevelVariableType() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTypeAnnotation([
'variableType',
])
final foo = 0;
''', [
error(WarningCode.MACRO_WARNING, 80, 3),
]);
}
test_diagnostic_report_atTypeAnnotation_kind_recordType() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTypeAnnotation([
'returnType',
])
(int, String) foo() => throw 0;
''', [
error(WarningCode.MACRO_WARNING, 72, 13),
]);
}
test_diagnostic_report_atTypeAnnotation_method_formalParameter_positional() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
class A {
@ReportAtTypeAnnotation([
'positionalFormalParameterType 1',
])
void foo(int a, String b) {}
}
''', [
error(WarningCode.MACRO_WARNING, 127, 6),
]);
}
test_diagnostic_report_atTypeAnnotation_method_returnType() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
class A {
@ReportAtTypeAnnotation([
'returnType',
])
int foo() => 0;
}
''', [
error(WarningCode.MACRO_WARNING, 90, 3),
]);
}
test_diagnostic_report_atTypeAnnotation_namedTypeArgument() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTypeAnnotation([
'returnType',
'namedTypeArgument 1',
])
Map<int, String> foo() => throw 0;
''', [
error(WarningCode.MACRO_WARNING, 106, 6),
]);
}
test_diagnostic_report_atTypeAnnotation_notFileOfMacroApplication() async {
newFile(testFile.path, '''
import 'append.dart';
import 'diagnostic.dart'; // ignore: unused_import
class A {
@DeclareInType("""
@{{package:test/diagnostic.dart@ReportAtTypeAnnotation}}([
'field foo',
])
void starter() {}""")
final int foo = 0;
}
''');
var session = contextFor(testFile).currentSession;
var result = await session.getResolvedLibrary(testFile.path);
// The diagnostic is reported on the field, declared in the user code,
// not on the macro application generated by other macro application
// into a library augmentation.
assertResolvedLibraryResultText(result, configure: (configuration) {
configuration.unitConfiguration.withContentPredicate = (unitResult) {
return unitResult.isAugmentation;
};
}, r'''
ResolvedLibraryResult #0
element: package:test/test.dart
units
ResolvedUnitResult #1
path: /home/test/lib/test.dart
uri: package:test/test.dart
flags: exists isLibrary
errors
220 +3 MACRO_WARNING
ResolvedUnitResult #2
path: /home/test/lib/test.macro.dart
uri: package:test/test.macro.dart
flags: exists isAugmentation isMacroAugmentation
content
---
augment library 'package:test/test.dart';
import 'package:test/diagnostic.dart' as prefix0;
augment class A {
@prefix0.ReportAtTypeAnnotation([
'field foo',
])
void starter() {}
}
---
''');
}
test_diagnostic_report_atTypeAnnotation_record_namedField() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
class A {
@ReportAtTypeAnnotation([
'variableType',
'namedField 1',
])
final (bool, {int a, String b})? foo = null;
}
''', [
error(WarningCode.MACRO_WARNING, 133, 6),
]);
}
test_diagnostic_report_atTypeAnnotation_record_positionalField() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
class A {
@ReportAtTypeAnnotation([
'variableType',
'positionalField 1',
])
final (int, String)? foo = null;
}
''', [
error(WarningCode.MACRO_WARNING, 129, 6),
]);
}
test_diagnostic_report_atTypeAnnotation_typeAlias_aliasedType() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportAtTypeAnnotation([
'aliasedType',
])
typedef A = List<int>;
''', [
error(WarningCode.MACRO_WARNING, 85, 9),
]);
}
test_diagnostic_report_contextMessages_superClassMethods() async {
var a = newFile('$testPackageLibPath/a.dart', r'''
class A {
void foo() {}
void bar() {}
}
''');
await assertErrorsInCode('''
import 'a.dart';
import 'diagnostic.dart';
@ReportWithContextMessages(forSuperClass: true)
class B extends A {}
''', [
error(WarningCode.MACRO_WARNING, 98, 1,
contextMessages: [message(a, 17, 3), message(a, 33, 3)]),
]);
}
test_diagnostic_report_contextMessages_thisClassMethods() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportWithContextMessages()
class A {
void foo() {}
void bar() {}
}
''', [
error(WarningCode.MACRO_WARNING, 62, 1, contextMessages: [
message(testFile, 73, 3),
message(testFile, 89, 3)
]),
]);
}
test_diagnostic_report_contextMessages_thisClassMethods_noTarget() async {
await assertErrorsInCode('''
import 'diagnostic.dart';
@ReportWithContextMessages(withDeclarationTarget: false)
class A {
void foo() {}
void bar() {}
}
''', [
error(
WarningCode.MACRO_WARNING,
27,
56,
contextMessages: [message(testFile, 101, 3), message(testFile, 117, 3)],
correctionContains: 'Correction message',
),
]);
}
test_diagnostic_report_internalException_declarationsPhase() async {
LibraryMacroApplier.testThrowExceptionDeclarations = true;
try {
await assertErrorsInCode('''
import 'diagnostic.dart';
@NothingMacro()
class A {}
''', [
error(CompileTimeErrorCode.MACRO_INTERNAL_EXCEPTION, 27, 15),
]);
} finally {
LibraryMacroApplier.testThrowExceptionDeclarations = false;
}
}
test_diagnostic_report_internalException_definitionsPhase() async {
LibraryMacroApplier.testThrowExceptionDefinitions = true;
try {
await assertErrorsInCode('''
import 'diagnostic.dart';
@NothingMacro()
class A {}
''', [
error(CompileTimeErrorCode.MACRO_INTERNAL_EXCEPTION, 27, 15),
]);
} finally {
LibraryMacroApplier.testThrowExceptionDefinitions = false;
}
}
test_diagnostic_report_internalException_typesPhase() async {
LibraryMacroApplier.testThrowExceptionTypes = true;
try {
await assertErrorsInCode('''
import 'diagnostic.dart';
@NothingMacro()
class A {}
''', [
error(CompileTimeErrorCode.MACRO_INTERNAL_EXCEPTION, 27, 15),
]);
} finally {
LibraryMacroApplier.testThrowExceptionTypes = false;
}
}
test_diagnostic_throwsException() async {
newFile('$testPackageLibPath/a.dart', r'''
import 'package:macros/macros.dart';
macro class MyMacro implements ClassTypesMacro {
const MyMacro();
buildTypesForClass(clazz, builder) {
throw 12345;
}
}
''');
await assertErrorsInCode('''
import 'a.dart';
@MyMacro()
class A {}
''', [
error(
CompileTimeErrorCode.MACRO_ERROR,
18,
10,
messageContains: [
'Macro application failed due to a bug in the macro.'
],
contextMessages: [
ExpectedContextMessage(testFile, 18, 10, textContains: [
'package:test/a.dart',
'12345',
'MyMacro',
]),
],
),
]);
}
test_example_jsonSerializable() async {
newFile(testFile.path, r'''
import 'json_serializable.dart';
void f(Map<String, Object?> json) {
var user = User.fromJson(json);
user.toJson();
}
@JsonSerializable()
class User {
final int age;
final String name;
}
''');
var session = contextFor(testFile).currentSession;
var result = await session.getResolvedLibrary(testFile.path);
assertResolvedLibraryResultText(result, r'''
ResolvedLibraryResult #0
element: package:test/test.dart
units
ResolvedUnitResult #1
path: /home/test/lib/test.dart
uri: package:test/test.dart
flags: exists isLibrary
ResolvedUnitResult #2
path: /home/test/lib/test.macro.dart
uri: package:test/test.macro.dart
flags: exists isAugmentation isMacroAugmentation
''');
}
test_getResolvedLibrary_macroAugmentation_hasErrors() async {
newFile(
'$testPackageLibPath/append.dart',
getMacroCode('append.dart'),
);
newFile('$testPackageLibPath/test.dart', r'''
import 'append.dart';
@DeclareInType(' NotType foo() {}')
class A {}
''');
var session = contextFor(testFile).currentSession;
var result = await session.getResolvedLibrary(testFile.path);
// 1. Has the macro augmentation unit.
// 2. It has an error reported.
assertResolvedLibraryResultText(result, configure: (configuration) {
configuration.unitConfiguration
..nodeSelector = (unitResult) {
if (unitResult.isMacroAugmentation) {
return unitResult.findNode.namedType('NotType');
}
return null;
}
..withContentPredicate = (unitResult) {
return unitResult.isAugmentation;
};
}, r'''
ResolvedLibraryResult #0
element: package:test/test.dart
units
ResolvedUnitResult #1
path: /home/test/lib/test.dart
uri: package:test/test.dart
flags: exists isLibrary
ResolvedUnitResult #2
path: /home/test/lib/test.macro.dart
uri: package:test/test.macro.dart
flags: exists isAugmentation isMacroAugmentation
content
---
augment library 'package:test/test.dart';
augment class A {
NotType foo() {}
}
---
errors
63 +7 UNDEFINED_CLASS
selectedNode: NamedType
name: NotType
element: <null>
type: InvalidType
''');
}
test_getResolvedLibrary_reference_declaredGetter() async {
newFile(
'$testPackageLibPath/append.dart',
getMacroCode('append.dart'),
);
newFile('$testPackageLibPath/test.dart', r'''
import 'append.dart';
@DeclareInLibrary('{{dart:core@int}} get x => 0;')
void f() {
x;
}
''');
var session = contextFor(testFile).currentSession;
var result = await session.getResolvedLibrary(testFile.path);
// 1. `get x` was declared.
// 2. The reference to `x` can be resolved in the library unit.
assertResolvedLibraryResultText(result, configure: (configuration) {
configuration.unitConfiguration
..nodeSelector = (unitResult) {
switch (unitResult.uriStr) {
case 'package:test/test.dart':
return unitResult.findNode.singleBlock;
}
return null;
}
..withContentPredicate = (unitResult) {
return unitResult.isAugmentation;
};
}, r'''
ResolvedLibraryResult #0
element: package:test/test.dart
units
ResolvedUnitResult #1
path: /home/test/lib/test.dart
uri: package:test/test.dart
flags: exists isLibrary
selectedNode: Block
leftBracket: {
statements
ExpressionStatement
expression: SimpleIdentifier
token: x
staticElement: package:test/test.dart::@augmentation::package:test/test.macro.dart::@accessor::x
staticType: int
semicolon: ;
rightBracket: }
ResolvedUnitResult #2
path: /home/test/lib/test.macro.dart
uri: package:test/test.macro.dart
flags: exists isAugmentation isMacroAugmentation
content
---
augment library 'package:test/test.dart';
import 'dart:core' as prefix0;
prefix0.int get x => 0;
---
''');
}
test_macroDiagnostics_report_atAnnotation_identifier() async {
newFile('$testPackageLibPath/a.dart', r'''
const a = 0;
''');
await assertErrorsInCode(r'''
import 'diagnostic.dart';
import 'a.dart';
@ReportAtTargetAnnotation(1)
@a
class X {}
''', [
error(WarningCode.MACRO_WARNING, 73, 2),
]);
}
test_withLints() async {
writeTestPackageAnalysisOptionsFile(AnalysisOptionsFileConfig(
lints: ['unnecessary_this'],
experiments: ['macros'],
));
/// A macro that will produce an augmented class with `unnecessary_this`
/// violations.
var macroFile = newFile(
'$testPackageLibPath/auto_to_string.dart',
getMacroCode('example/auto_to_string.dart'),
);
await assertErrorsInFile2(macroFile, []);
var testFile = newFile('$testPackageLibPath/test.dart', r'''
import 'auto_to_string.dart';
@AutoToString()
class User {
final String name;
final int age;
User(this.name, this.age);
}
''');
await assertErrorsInFile2(testFile, []);
var macroGeneratedFile = getFile('$testPackageLibPath/test.macro.dart');
await assertErrorsInFile2(macroGeneratedFile, [
// No lints.
]);
}
}