mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 08:24:39 +00:00
Support more parts of ClassDeclaration in DeclarationBuilderFromElement.
Change-Id: I6d6c0344924a19e8b8b01cf54a51b69fd61e0122 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/243849 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
c6173d3686
commit
5a2f5ab33c
|
@ -486,7 +486,7 @@ class _ClassIntrospector implements macro.ClassIntrospector {
|
|||
return null;
|
||||
}
|
||||
|
||||
return declarationBuilder.fromElement.classDeclaration(
|
||||
return declarationBuilder.fromElement.classElement(
|
||||
superType.element,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart'
|
|||
as macro;
|
||||
import 'package:analyzer/dart/ast/ast.dart' as ast;
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/dart/element/nullability_suffix.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
|
||||
class ClassDeclarationImpl extends macro.ClassDeclarationImpl {
|
||||
late final ClassElement element;
|
||||
|
@ -43,7 +45,7 @@ class DeclarationBuilder {
|
|||
/// corresponding elements. So, we can access them uniformly via interfaces,
|
||||
/// mixins, etc.
|
||||
void transferToElements() {
|
||||
for (final entry in fromNode._classNodes.entries) {
|
||||
for (final entry in fromNode._classMap.entries) {
|
||||
final element = entry.key.declaredElement as ClassElement;
|
||||
final declaration = entry.value;
|
||||
declaration.element = element;
|
||||
|
@ -54,51 +56,86 @@ class DeclarationBuilder {
|
|||
|
||||
class DeclarationBuilderFromElement {
|
||||
final Map<ClassElement, ClassDeclarationImpl> _classMap = Map.identity();
|
||||
final Map<TypeParameterElement, macro.TypeParameterDeclarationImpl>
|
||||
_typeParameterMap = Map.identity();
|
||||
|
||||
macro.ClassDeclarationImpl classDeclaration(ClassElement element) {
|
||||
return _classMap[element] ??= _classDeclaration(element);
|
||||
macro.ClassDeclarationImpl classElement(ClassElement element) {
|
||||
return _classMap[element] ??= _classElement(element);
|
||||
}
|
||||
|
||||
ClassDeclarationImpl _classDeclaration(ClassElement element) {
|
||||
macro.TypeParameterDeclarationImpl typeParameter(
|
||||
TypeParameterElement element,
|
||||
) {
|
||||
return _typeParameterMap[element] ??= _typeParameter(element);
|
||||
}
|
||||
|
||||
ClassDeclarationImpl _classElement(ClassElement element) {
|
||||
assert(!_classMap.containsKey(element));
|
||||
return ClassDeclarationImpl._(
|
||||
id: macro.RemoteInstance.uniqueId,
|
||||
identifier: _identifierFromName(element.name),
|
||||
typeParameters: [], // TODO _buildTypeParameters(node.typeParameters),
|
||||
interfaces: [], // TODO _buildTypeAnnotations(node.implementsClause?.interfaces),
|
||||
isAbstract: false, // TODO node.abstractKeyword != null,
|
||||
identifier: _identifier(element.name),
|
||||
typeParameters: element.typeParameters.map(_typeParameter).toList(),
|
||||
interfaces: element.interfaces.map(_dartType).toList(),
|
||||
isAbstract: element.isAbstract,
|
||||
isExternal: false,
|
||||
mixins: [], // TODO _buildTypeAnnotations(node.withClause?.mixinTypes),
|
||||
superclass: null,
|
||||
// TODO(scheglov) implement
|
||||
// superclass: node.extendsClause?.superclass.mapOrNull(
|
||||
// _buildTypeAnnotation,
|
||||
// ),
|
||||
mixins: element.mixins.map(_dartType).toList(),
|
||||
superclass: element.supertype.mapOrNull(_dartType),
|
||||
)..element = element;
|
||||
}
|
||||
|
||||
macro.IdentifierImpl _identifierFromName(String name) {
|
||||
macro.TypeAnnotationImpl _dartType(DartType type) {
|
||||
if (type is InterfaceType) {
|
||||
return macro.NamedTypeAnnotationImpl(
|
||||
id: macro.RemoteInstance.uniqueId,
|
||||
isNullable: type.nullabilitySuffix == NullabilitySuffix.question,
|
||||
identifier: _identifier(type.element.name),
|
||||
typeArguments: type.typeArguments.map(_dartType).toList(),
|
||||
);
|
||||
} else if (type is TypeParameterType) {
|
||||
return macro.NamedTypeAnnotationImpl(
|
||||
id: macro.RemoteInstance.uniqueId,
|
||||
isNullable: type.nullabilitySuffix == NullabilitySuffix.question,
|
||||
identifier: _identifier(type.element.name),
|
||||
typeArguments: const [],
|
||||
);
|
||||
} else {
|
||||
// TODO(scheglov) other types
|
||||
throw UnimplementedError('(${type.runtimeType}) $type');
|
||||
}
|
||||
}
|
||||
|
||||
macro.IdentifierImpl _identifier(String name) {
|
||||
return _IdentifierImpl(
|
||||
id: macro.RemoteInstance.uniqueId,
|
||||
name: name,
|
||||
);
|
||||
}
|
||||
|
||||
macro.TypeParameterDeclarationImpl _typeParameter(
|
||||
TypeParameterElement element,
|
||||
) {
|
||||
return macro.TypeParameterDeclarationImpl(
|
||||
id: macro.RemoteInstance.uniqueId,
|
||||
identifier: _identifier(element.name),
|
||||
bound: element.bound.mapOrNull(_dartType),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DeclarationBuilderFromNode {
|
||||
final Map<ast.ClassDeclaration, ClassDeclarationImpl> _classNodes =
|
||||
final Map<ast.ClassDeclaration, ClassDeclarationImpl> _classMap =
|
||||
Map.identity();
|
||||
|
||||
macro.ClassDeclarationImpl classDeclaration(
|
||||
ast.ClassDeclaration node,
|
||||
) {
|
||||
return _classNodes[node] ??= _classDeclaration(node);
|
||||
return _classMap[node] ??= _classDeclaration(node);
|
||||
}
|
||||
|
||||
ClassDeclarationImpl _classDeclaration(
|
||||
ast.ClassDeclaration node,
|
||||
) {
|
||||
assert(!_classNodes.containsKey(node));
|
||||
assert(!_classMap.containsKey(node));
|
||||
return ClassDeclarationImpl._(
|
||||
id: macro.RemoteInstance.uniqueId,
|
||||
identifier: _identifier(node.name),
|
||||
|
|
|
@ -6,6 +6,8 @@ import 'dart:async';
|
|||
|
||||
import 'package:_fe_analyzer_shared/src/macros/api.dart';
|
||||
|
||||
import 'introspect_shared.dart';
|
||||
|
||||
/*macro*/ class DeclarationTextMacro implements ClassTypesMacro {
|
||||
const DeclarationTextMacro();
|
||||
|
||||
|
@ -88,15 +90,14 @@ class _DeclarationPrinter {
|
|||
_sink.write('$name: ');
|
||||
|
||||
if (type != null) {
|
||||
_writeln(_typeStr(type));
|
||||
_writeln(type.asString);
|
||||
} else {
|
||||
_writeln('null');
|
||||
}
|
||||
}
|
||||
|
||||
void _writeTypeAnnotationLine(TypeAnnotation type) {
|
||||
var typeStr = _typeStr(type);
|
||||
_writelnWithIndent(typeStr);
|
||||
_writelnWithIndent(type.asString);
|
||||
}
|
||||
|
||||
void _writeTypeAnnotations(String name, Iterable<TypeAnnotation> elements) {
|
||||
|
@ -117,138 +118,4 @@ class _DeclarationPrinter {
|
|||
void _writeTypeParameters(Iterable<TypeParameterDeclaration> elements) {
|
||||
_writeElements('typeParameters', elements, _writeTypeParameter);
|
||||
}
|
||||
|
||||
static String _typeStr(TypeAnnotation type) {
|
||||
final buffer = StringBuffer();
|
||||
_TypeStringBuilder(buffer).write(type);
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class _TypeStringBuilder {
|
||||
final StringSink _sink;
|
||||
|
||||
_TypeStringBuilder(this._sink);
|
||||
|
||||
void write(TypeAnnotation type) {
|
||||
if (type is FunctionTypeAnnotation) {
|
||||
_writeFunctionTypeAnnotation(type);
|
||||
} else if (type is NamedTypeAnnotation) {
|
||||
_writeNamedTypeAnnotation(type);
|
||||
} else if (type is OmittedTypeAnnotation) {
|
||||
_sink.write('OmittedType');
|
||||
} else {
|
||||
throw UnimplementedError('(${type.runtimeType}) $type');
|
||||
}
|
||||
if (type.isNullable) {
|
||||
_sink.write('?');
|
||||
}
|
||||
}
|
||||
|
||||
void _writeFormalParameter(FunctionTypeParameter node) {
|
||||
final String closeSeparator;
|
||||
if (node.isNamed) {
|
||||
_sink.write('{');
|
||||
closeSeparator = '}';
|
||||
if (node.isRequired) {
|
||||
_sink.write('required ');
|
||||
}
|
||||
} else if (!node.isRequired) {
|
||||
_sink.write('[');
|
||||
closeSeparator = ']';
|
||||
} else {
|
||||
closeSeparator = '';
|
||||
}
|
||||
|
||||
write(node.type);
|
||||
if (node.name != null) {
|
||||
_sink.write(' ');
|
||||
_sink.write(node.name);
|
||||
}
|
||||
|
||||
_sink.write(closeSeparator);
|
||||
}
|
||||
|
||||
void _writeFunctionTypeAnnotation(FunctionTypeAnnotation type) {
|
||||
write(type.returnType);
|
||||
_sink.write(' Function');
|
||||
|
||||
_sink.writeList(
|
||||
elements: type.typeParameters,
|
||||
write: _writeTypeParameter,
|
||||
separator: ', ',
|
||||
open: '<',
|
||||
close: '>',
|
||||
);
|
||||
|
||||
_sink.write('(');
|
||||
var hasFormalParameter = false;
|
||||
for (final formalParameter in type.positionalParameters) {
|
||||
if (hasFormalParameter) {
|
||||
_sink.write(', ');
|
||||
}
|
||||
_writeFormalParameter(formalParameter);
|
||||
hasFormalParameter = true;
|
||||
}
|
||||
for (final formalParameter in type.namedParameters) {
|
||||
if (hasFormalParameter) {
|
||||
_sink.write(', ');
|
||||
}
|
||||
_writeFormalParameter(formalParameter);
|
||||
hasFormalParameter = true;
|
||||
}
|
||||
_sink.write(')');
|
||||
}
|
||||
|
||||
void _writeNamedTypeAnnotation(NamedTypeAnnotation type) {
|
||||
_sink.write(type.identifier.name);
|
||||
_sink.writeList(
|
||||
elements: type.typeArguments,
|
||||
write: write,
|
||||
separator: ', ',
|
||||
open: '<',
|
||||
close: '>',
|
||||
);
|
||||
}
|
||||
|
||||
void _writeTypeParameter(TypeParameterDeclaration node) {
|
||||
_sink.write(node.identifier.name);
|
||||
|
||||
final bound = node.bound;
|
||||
if (bound != null) {
|
||||
_sink.write(' extends ');
|
||||
write(bound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension on StringSink {
|
||||
void writeList<T>({
|
||||
required Iterable<T> elements,
|
||||
required void Function(T element) write,
|
||||
required String separator,
|
||||
String? open,
|
||||
String? close,
|
||||
}) {
|
||||
elements = elements.toList();
|
||||
if (elements.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (open != null) {
|
||||
this.write(open);
|
||||
}
|
||||
var isFirst = true;
|
||||
for (var element in elements) {
|
||||
if (isFirst) {
|
||||
isFirst = false;
|
||||
} else {
|
||||
this.write(separator);
|
||||
}
|
||||
write(element);
|
||||
}
|
||||
if (close != null) {
|
||||
this.write(close);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import 'dart:async';
|
|||
|
||||
import 'package:_fe_analyzer_shared/src/macros/api.dart';
|
||||
|
||||
import 'introspect_shared.dart';
|
||||
|
||||
const introspectMacro = IntrospectDeclarationsPhaseMacro();
|
||||
|
||||
/*macro*/ class IntrospectDeclarationsPhaseMacro
|
||||
|
@ -19,6 +21,7 @@ const introspectMacro = IntrospectDeclarationsPhaseMacro();
|
|||
) async {
|
||||
final printer = _DeclarationPrinter(
|
||||
classIntrospector: builder,
|
||||
typeResolver: builder,
|
||||
);
|
||||
await printer.writeClassDeclaration(declaration);
|
||||
final text = printer._sink.toString();
|
||||
|
@ -34,11 +37,13 @@ const introspectMacro = IntrospectDeclarationsPhaseMacro();
|
|||
|
||||
class _DeclarationPrinter {
|
||||
final ClassIntrospector classIntrospector;
|
||||
final TypeResolver typeResolver;
|
||||
final StringBuffer _sink = StringBuffer();
|
||||
String _indent = '';
|
||||
|
||||
_DeclarationPrinter({
|
||||
required this.classIntrospector,
|
||||
required this.typeResolver,
|
||||
});
|
||||
|
||||
Future<void> writeClassDeclaration(ClassDeclaration e) async {
|
||||
|
@ -55,10 +60,9 @@ class _DeclarationPrinter {
|
|||
await _withIndent(() => writeClassDeclaration(superclass));
|
||||
}
|
||||
|
||||
// TODO(scheglov) implement
|
||||
// _writeTypeParameters(e.typeParameters);
|
||||
// _writeTypeAnnotations('mixins', e.mixins);
|
||||
// _writeTypeAnnotations('interfaces', e.interfaces);
|
||||
await _writeTypeParameters(e.typeParameters);
|
||||
await _writeTypeAnnotations('mixins', e.mixins);
|
||||
await _writeTypeAnnotations('interfaces', e.interfaces);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -69,6 +73,21 @@ class _DeclarationPrinter {
|
|||
_indent = savedIndent;
|
||||
}
|
||||
|
||||
Future<void> _writeElements<T>(
|
||||
String name,
|
||||
Iterable<T> elements,
|
||||
Future<void> Function(T) f,
|
||||
) async {
|
||||
if (elements.isNotEmpty) {
|
||||
_writelnWithIndent(name);
|
||||
await _withIndent(() async {
|
||||
for (var element in elements) {
|
||||
await f(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _writeIf(bool flag, String str) {
|
||||
if (flag) {
|
||||
_sink.write(str);
|
||||
|
@ -83,4 +102,43 @@ class _DeclarationPrinter {
|
|||
_sink.write(_indent);
|
||||
_sink.writeln(line);
|
||||
}
|
||||
|
||||
void _writeTypeAnnotation(String name, TypeAnnotation? type) {
|
||||
_sink.write(_indent);
|
||||
_sink.write('$name: ');
|
||||
|
||||
if (type != null) {
|
||||
_writeln(type.asString);
|
||||
} else {
|
||||
_writeln('null');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _writeTypeAnnotationLine(TypeAnnotation type) async {
|
||||
_writelnWithIndent(type.asString);
|
||||
}
|
||||
|
||||
Future<void> _writeTypeAnnotations(
|
||||
String name,
|
||||
Iterable<TypeAnnotation> elements,
|
||||
) async {
|
||||
await _writeElements(name, elements, _writeTypeAnnotationLine);
|
||||
}
|
||||
|
||||
Future<void> _writeTypeParameter(TypeParameterDeclaration e) async {
|
||||
_writelnWithIndent(e.identifier.name);
|
||||
|
||||
await _withIndent(() async {
|
||||
var bound = e.bound;
|
||||
if (bound != null) {
|
||||
_writeTypeAnnotation('bound', bound);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _writeTypeParameters(
|
||||
Iterable<TypeParameterDeclaration> elements,
|
||||
) async {
|
||||
await _writeElements('typeParameters', elements, _writeTypeParameter);
|
||||
}
|
||||
}
|
||||
|
|
141
pkg/analyzer/test/src/summary/macro/introspect_shared.dart
Normal file
141
pkg/analyzer/test/src/summary/macro/introspect_shared.dart
Normal file
|
@ -0,0 +1,141 @@
|
|||
// 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:_fe_analyzer_shared/src/macros/api.dart';
|
||||
|
||||
class _TypeAnnotationStringBuilder {
|
||||
final StringSink _sink;
|
||||
|
||||
_TypeAnnotationStringBuilder(this._sink);
|
||||
|
||||
void write(TypeAnnotation type) {
|
||||
if (type is FunctionTypeAnnotation) {
|
||||
_writeFunctionTypeAnnotation(type);
|
||||
} else if (type is NamedTypeAnnotation) {
|
||||
_writeNamedTypeAnnotation(type);
|
||||
} else if (type is OmittedTypeAnnotation) {
|
||||
_sink.write('OmittedType');
|
||||
} else {
|
||||
throw UnimplementedError('(${type.runtimeType}) $type');
|
||||
}
|
||||
if (type.isNullable) {
|
||||
_sink.write('?');
|
||||
}
|
||||
}
|
||||
|
||||
void _writeFormalParameter(FunctionTypeParameter node) {
|
||||
final String closeSeparator;
|
||||
if (node.isNamed) {
|
||||
_sink.write('{');
|
||||
closeSeparator = '}';
|
||||
if (node.isRequired) {
|
||||
_sink.write('required ');
|
||||
}
|
||||
} else if (!node.isRequired) {
|
||||
_sink.write('[');
|
||||
closeSeparator = ']';
|
||||
} else {
|
||||
closeSeparator = '';
|
||||
}
|
||||
|
||||
write(node.type);
|
||||
if (node.name != null) {
|
||||
_sink.write(' ');
|
||||
_sink.write(node.name);
|
||||
}
|
||||
|
||||
_sink.write(closeSeparator);
|
||||
}
|
||||
|
||||
void _writeFunctionTypeAnnotation(FunctionTypeAnnotation type) {
|
||||
write(type.returnType);
|
||||
_sink.write(' Function');
|
||||
|
||||
_sink.writeList(
|
||||
elements: type.typeParameters,
|
||||
write: _writeTypeParameter,
|
||||
separator: ', ',
|
||||
open: '<',
|
||||
close: '>',
|
||||
);
|
||||
|
||||
_sink.write('(');
|
||||
var hasFormalParameter = false;
|
||||
for (final formalParameter in type.positionalParameters) {
|
||||
if (hasFormalParameter) {
|
||||
_sink.write(', ');
|
||||
}
|
||||
_writeFormalParameter(formalParameter);
|
||||
hasFormalParameter = true;
|
||||
}
|
||||
for (final formalParameter in type.namedParameters) {
|
||||
if (hasFormalParameter) {
|
||||
_sink.write(', ');
|
||||
}
|
||||
_writeFormalParameter(formalParameter);
|
||||
hasFormalParameter = true;
|
||||
}
|
||||
_sink.write(')');
|
||||
}
|
||||
|
||||
void _writeNamedTypeAnnotation(NamedTypeAnnotation type) {
|
||||
_sink.write(type.identifier.name);
|
||||
_sink.writeList(
|
||||
elements: type.typeArguments,
|
||||
write: write,
|
||||
separator: ', ',
|
||||
open: '<',
|
||||
close: '>',
|
||||
);
|
||||
}
|
||||
|
||||
void _writeTypeParameter(TypeParameterDeclaration node) {
|
||||
_sink.write(node.identifier.name);
|
||||
|
||||
final bound = node.bound;
|
||||
if (bound != null) {
|
||||
_sink.write(' extends ');
|
||||
write(bound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension on StringSink {
|
||||
void writeList<T>({
|
||||
required Iterable<T> elements,
|
||||
required void Function(T element) write,
|
||||
required String separator,
|
||||
String? open,
|
||||
String? close,
|
||||
}) {
|
||||
elements = elements.toList();
|
||||
if (elements.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (open != null) {
|
||||
this.write(open);
|
||||
}
|
||||
var isFirst = true;
|
||||
for (var element in elements) {
|
||||
if (isFirst) {
|
||||
isFirst = false;
|
||||
} else {
|
||||
this.write(separator);
|
||||
}
|
||||
write(element);
|
||||
}
|
||||
if (close != null) {
|
||||
this.write(close);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension E on TypeAnnotation {
|
||||
String get asString {
|
||||
final buffer = StringBuffer();
|
||||
_TypeAnnotationStringBuilder(buffer).write(this);
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
|
@ -65,6 +65,12 @@ class MacroElementsTest extends ElementsBaseTest {
|
|||
return code.replaceAll('/*macro*/', 'macro');
|
||||
}
|
||||
|
||||
String get _introspectSharedCode {
|
||||
return MacrosEnvironment.instance.packageAnalyzerFolder
|
||||
.getChildAssumingFile('test/src/summary/macro/introspect_shared.dart')
|
||||
.readAsStringSync();
|
||||
}
|
||||
|
||||
Future<void> setUp() async {
|
||||
writeTestPackageConfig(
|
||||
PackageConfigFileBuilder(),
|
||||
|
@ -1152,6 +1158,133 @@ library
|
|||
''');
|
||||
}
|
||||
|
||||
test_introspect_declarations_ClassDeclaration_imported_interfaces() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
class A {}
|
||||
class B {}
|
||||
class C implements A, B {}
|
||||
''');
|
||||
|
||||
await _assertIntrospectDeclarationsText(r'''
|
||||
import 'a.dart';
|
||||
|
||||
@introspectMacro
|
||||
class X extends C {}
|
||||
''', r'''
|
||||
class X
|
||||
superclass
|
||||
class C
|
||||
superclass
|
||||
class Object
|
||||
interfaces
|
||||
A
|
||||
B
|
||||
''');
|
||||
}
|
||||
|
||||
test_introspect_declarations_ClassDeclaration_imported_isAbstract() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
abstract class A {}
|
||||
''');
|
||||
|
||||
await _assertIntrospectDeclarationsText(r'''
|
||||
import 'a.dart';
|
||||
|
||||
@introspectMacro
|
||||
class X extends A {}
|
||||
''', r'''
|
||||
class X
|
||||
superclass
|
||||
abstract class A
|
||||
superclass
|
||||
class Object
|
||||
''');
|
||||
}
|
||||
|
||||
test_introspect_declarations_ClassDeclaration_imported_mixins() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
mixin M1 {}
|
||||
mixin M2 {}
|
||||
class C with M1, M2 {}
|
||||
''');
|
||||
|
||||
await _assertIntrospectDeclarationsText(r'''
|
||||
import 'a.dart';
|
||||
|
||||
@introspectMacro
|
||||
class X extends C {}
|
||||
''', r'''
|
||||
class X
|
||||
superclass
|
||||
class C
|
||||
superclass
|
||||
class Object
|
||||
mixins
|
||||
M1
|
||||
M2
|
||||
''');
|
||||
}
|
||||
|
||||
test_introspect_declarations_ClassDeclaration_imported_superclass() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
class A {}
|
||||
class B extends A {}
|
||||
''');
|
||||
|
||||
await _assertIntrospectDeclarationsText(r'''
|
||||
import 'a.dart';
|
||||
|
||||
@introspectMacro
|
||||
class X extends B {}
|
||||
''', r'''
|
||||
class X
|
||||
superclass
|
||||
class B
|
||||
superclass
|
||||
class A
|
||||
superclass
|
||||
class Object
|
||||
''');
|
||||
}
|
||||
|
||||
test_introspect_declarations_ClassDeclaration_imported_typeParameters() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
class A<T, U extends List<T>> {}
|
||||
''');
|
||||
|
||||
await _assertIntrospectDeclarationsText(r'''
|
||||
import 'a.dart';
|
||||
|
||||
@introspectMacro
|
||||
class X extends A {}
|
||||
''', r'''
|
||||
class X
|
||||
superclass
|
||||
class A
|
||||
superclass
|
||||
class Object
|
||||
typeParameters
|
||||
T
|
||||
U
|
||||
bound: List<T>
|
||||
''');
|
||||
}
|
||||
|
||||
test_introspect_declarations_ClassDeclaration_superclassOf() async {
|
||||
await _assertIntrospectDeclarationsText(r'''
|
||||
class A {}
|
||||
|
||||
@introspectMacro
|
||||
class X extends A {}
|
||||
''', r'''
|
||||
class X
|
||||
superclass
|
||||
class A
|
||||
superclass
|
||||
class Object
|
||||
''');
|
||||
}
|
||||
|
||||
test_introspect_declarations_ClassDeclaration_superclassOf_implicit() async {
|
||||
await _assertIntrospectDeclarationsText(r'''
|
||||
@introspectMacro
|
||||
|
@ -1163,18 +1296,14 @@ class X
|
|||
''');
|
||||
}
|
||||
|
||||
test_introspect_declarations_ClassDeclaration_superclassOf_local() async {
|
||||
test_introspect_declarations_ClassDeclaration_superclassOf_unresolved() async {
|
||||
await _assertIntrospectDeclarationsText(r'''
|
||||
class A<T> {}
|
||||
|
||||
@introspectMacro
|
||||
class X extends A<int> {}
|
||||
class X extends A {}
|
||||
''', r'''
|
||||
class X
|
||||
superclass
|
||||
class A
|
||||
superclass
|
||||
class Object
|
||||
class Object
|
||||
''');
|
||||
}
|
||||
|
||||
|
@ -1597,6 +1726,11 @@ class A {}
|
|||
/// the textual dump of the introspection information for the first
|
||||
/// declaration.
|
||||
Future<String> _getDeclarationText(String declarationCode) async {
|
||||
newFile(
|
||||
'$testPackageLibPath/introspect_shared.dart',
|
||||
_introspectSharedCode,
|
||||
);
|
||||
|
||||
newFile(
|
||||
'$testPackageLibPath/declaration_text.dart',
|
||||
_declarationTextCode,
|
||||
|
@ -1608,7 +1742,10 @@ import 'declaration_text.dart';
|
|||
@DeclarationTextMacro()
|
||||
$declarationCode
|
||||
''', preBuildSequence: [
|
||||
{'package:test/declaration_text.dart'}
|
||||
{
|
||||
'package:test/introspect_shared.dart',
|
||||
'package:test/declaration_text.dart',
|
||||
}
|
||||
]);
|
||||
|
||||
_assertNoErrorsForClassElement(
|
||||
|
@ -1626,6 +1763,11 @@ $declarationCode
|
|||
/// that contain textual dump of the introspection information for
|
||||
/// macro annotated declarations.
|
||||
Future<String> _getIntrospectDeclarationsText(String declarationCode) async {
|
||||
newFile(
|
||||
'$testPackageLibPath/introspect_shared.dart',
|
||||
_introspectSharedCode,
|
||||
);
|
||||
|
||||
newFile(
|
||||
'$testPackageLibPath/introspect_declarations_phase.dart',
|
||||
_introspectDeclarationsPhaseCode,
|
||||
|
@ -1633,10 +1775,12 @@ $declarationCode
|
|||
|
||||
var library = await buildLibrary('''
|
||||
import 'introspect_declarations_phase.dart';
|
||||
|
||||
$declarationCode
|
||||
''', preBuildSequence: [
|
||||
{'package:test/introspect_declarations_phase.dart'}
|
||||
{
|
||||
'package:test/introspect_shared.dart',
|
||||
'package:test/introspect_declarations_phase.dart',
|
||||
}
|
||||
]);
|
||||
|
||||
for (final class_ in library.definingCompilationUnit.classes) {
|
||||
|
|
Loading…
Reference in a new issue