mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 18:49:37 +00:00
Macro. Support for TypeAliasDeclaration.
Change-Id: I4b85cfaf154591434729ba9ad5f94a6cfc2d1033 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/354060 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Jake Macdonald <jakemac@google.com>
This commit is contained in:
parent
9fa1c16029
commit
9018d41706
|
@ -264,3 +264,22 @@ abstract interface class ExtensionTypeDefinitionMacro implements Macro {
|
||||||
FutureOr<void> buildDefinitionForExtensionType(
|
FutureOr<void> buildDefinitionForExtensionType(
|
||||||
ExtensionTypeDeclaration extension, TypeDefinitionBuilder builder);
|
ExtensionTypeDeclaration extension, TypeDefinitionBuilder builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The interface for [Macro]s that can be applied to any type alias
|
||||||
|
/// declaration, and want to contribute new type declarations to the program.
|
||||||
|
abstract interface class TypeAliasTypesMacro implements Macro {
|
||||||
|
FutureOr<void> buildTypesForTypeAlias(
|
||||||
|
TypeAliasDeclaration declaration,
|
||||||
|
TypeBuilder builder,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The interface for [Macro]s that can be applied to any type alias
|
||||||
|
/// declaration, and want to contribute new non-type declarations to the
|
||||||
|
/// program.
|
||||||
|
abstract interface class TypeAliasDeclarationsMacro implements Macro {
|
||||||
|
FutureOr<void> buildDeclarationsForTypeAlias(
|
||||||
|
TypeAliasDeclaration declaration,
|
||||||
|
DeclarationBuilder builder,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -204,6 +204,7 @@ enum DeclarationKind {
|
||||||
library,
|
library,
|
||||||
method,
|
method,
|
||||||
mixinType,
|
mixinType,
|
||||||
|
typeAlias,
|
||||||
variable,
|
variable,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,8 @@ Future<MacroExecutionResult> executeTypesMacro(
|
||||||
target.identifier as IdentifierImpl, introspector));
|
target.identifier as IdentifierImpl, introspector));
|
||||||
case (EnumValueDeclaration target, EnumValueTypesMacro macro):
|
case (EnumValueDeclaration target, EnumValueTypesMacro macro):
|
||||||
await macro.buildTypesForEnumValue(target, typeBuilder);
|
await macro.buildTypesForEnumValue(target, typeBuilder);
|
||||||
|
case (TypeAliasDeclaration target, TypeAliasTypesMacro macro):
|
||||||
|
await macro.buildTypesForTypeAlias(target, typeBuilder);
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedError('Unsupported macro type or invalid target:\n'
|
throw new UnsupportedError('Unsupported macro type or invalid target:\n'
|
||||||
'macro: $macro\ntarget: $target');
|
'macro: $macro\ntarget: $target');
|
||||||
|
@ -132,6 +134,8 @@ Future<MacroExecutionResult> executeDeclarationsMacro(Macro macro,
|
||||||
await macro.buildDeclarationsForFunction(target, topLevelBuilder);
|
await macro.buildDeclarationsForFunction(target, topLevelBuilder);
|
||||||
case (VariableDeclaration target, VariableDeclarationsMacro macro):
|
case (VariableDeclaration target, VariableDeclarationsMacro macro):
|
||||||
await macro.buildDeclarationsForVariable(target, topLevelBuilder);
|
await macro.buildDeclarationsForVariable(target, topLevelBuilder);
|
||||||
|
case (TypeAliasDeclaration target, TypeAliasDeclarationsMacro macro):
|
||||||
|
await macro.buildDeclarationsForTypeAlias(target, topLevelBuilder);
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedError('Unsupported macro type or invalid target:\n'
|
throw new UnsupportedError('Unsupported macro type or invalid target:\n'
|
||||||
'macro: $macro\ntarget: $target');
|
'macro: $macro\ntarget: $target');
|
||||||
|
|
|
@ -193,6 +193,20 @@ class MacroInstanceIdentifierImpl implements MacroInstanceIdentifier {
|
||||||
interfaces |= interfaceMask;
|
interfaces |= interfaceMask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case DeclarationKind.typeAlias:
|
||||||
|
switch (phase) {
|
||||||
|
case Phase.types:
|
||||||
|
if (macro is TypeAliasTypesMacro) {
|
||||||
|
interfaces |= interfaceMask;
|
||||||
|
}
|
||||||
|
case Phase.declarations:
|
||||||
|
if (macro is TypeAliasDeclarationsMacro) {
|
||||||
|
interfaces |= interfaceMask;
|
||||||
|
}
|
||||||
|
case Phase.definitions:
|
||||||
|
// Does not have definitions.
|
||||||
|
break;
|
||||||
|
}
|
||||||
case DeclarationKind.variable:
|
case DeclarationKind.variable:
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case Phase.types:
|
case Phase.types:
|
||||||
|
|
|
@ -343,6 +343,22 @@ void main() {
|
||||||
'class MyExtensionTypeOnMyClass {}'));
|
'class MyExtensionTypeOnMyClass {}'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('on type aliases', () async {
|
||||||
|
var result = await executor.executeTypesPhase(
|
||||||
|
simpleMacroInstanceId,
|
||||||
|
Fixtures.myTypeAlias,
|
||||||
|
TestTypePhaseIntrospector(),
|
||||||
|
);
|
||||||
|
expect(result.enumValueAugmentations, isEmpty);
|
||||||
|
expect(result.typeAugmentations, isEmpty);
|
||||||
|
expect(
|
||||||
|
result.libraryAugmentations.single.debugString().toString(),
|
||||||
|
equalsIgnoringWhitespace(
|
||||||
|
'class MyTypeAliasAliasedTypeMyClass {}',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('on mixins', () async {
|
test('on mixins', () async {
|
||||||
var result = await executor.executeTypesPhase(
|
var result = await executor.executeTypesPhase(
|
||||||
simpleMacroInstanceId,
|
simpleMacroInstanceId,
|
||||||
|
@ -594,6 +610,23 @@ class LibraryInfo {
|
||||||
expect(result.libraryAugmentations, isEmpty);
|
expect(result.libraryAugmentations, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('on type aliases', () async {
|
||||||
|
var result = await executor.executeDeclarationsPhase(
|
||||||
|
simpleMacroInstanceId,
|
||||||
|
Fixtures.myTypeAlias,
|
||||||
|
Fixtures.testDeclarationPhaseIntrospector,
|
||||||
|
);
|
||||||
|
expect(result.enumValueAugmentations, isEmpty);
|
||||||
|
expect(result.libraryAugmentations, hasLength(1));
|
||||||
|
expect(
|
||||||
|
result.libraryAugmentations.single.debugString().toString(),
|
||||||
|
equalsIgnoringWhitespace(
|
||||||
|
'List<String> get aliasedTypeFieldNames;',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(result.typeAugmentations, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
test('on mixins', () async {
|
test('on mixins', () async {
|
||||||
var result = await executor.executeDeclarationsPhase(
|
var result = await executor.executeDeclarationsPhase(
|
||||||
simpleMacroInstanceId,
|
simpleMacroInstanceId,
|
||||||
|
|
|
@ -14,7 +14,8 @@ void main() {
|
||||||
test('shouldExecute', () {
|
test('shouldExecute', () {
|
||||||
for (var kind in DeclarationKind.values) {
|
for (var kind in DeclarationKind.values) {
|
||||||
for (var phase in Phase.values) {
|
for (var phase in Phase.values) {
|
||||||
var instance = instancesByKindAndPhase[kind]![phase]!;
|
var instance = instancesByKindAndPhase[kind]?[phase];
|
||||||
|
if (instance == null) continue;
|
||||||
for (var otherKind in DeclarationKind.values) {
|
for (var otherKind in DeclarationKind.values) {
|
||||||
for (var otherPhase in Phase.values) {
|
for (var otherPhase in Phase.values) {
|
||||||
var expected = false;
|
var expected = false;
|
||||||
|
@ -42,7 +43,8 @@ void main() {
|
||||||
test('supportsDeclarationKind', () {
|
test('supportsDeclarationKind', () {
|
||||||
for (var kind in DeclarationKind.values) {
|
for (var kind in DeclarationKind.values) {
|
||||||
for (var phase in Phase.values) {
|
for (var phase in Phase.values) {
|
||||||
var instance = instancesByKindAndPhase[kind]![phase]!;
|
var instance = instancesByKindAndPhase[kind]?[phase];
|
||||||
|
if (instance == null) continue;
|
||||||
for (var otherKind in DeclarationKind.values) {
|
for (var otherKind in DeclarationKind.values) {
|
||||||
var expected = false;
|
var expected = false;
|
||||||
if (kind == otherKind) {
|
if (kind == otherKind) {
|
||||||
|
@ -154,6 +156,12 @@ final Map<DeclarationKind, Map<Phase, MacroInstanceIdentifierImpl>>
|
||||||
Phase.definitions: MacroInstanceIdentifierImpl(
|
Phase.definitions: MacroInstanceIdentifierImpl(
|
||||||
FakeMixinDefinitionMacro(), RemoteInstance.uniqueId),
|
FakeMixinDefinitionMacro(), RemoteInstance.uniqueId),
|
||||||
},
|
},
|
||||||
|
DeclarationKind.typeAlias: {
|
||||||
|
Phase.types: MacroInstanceIdentifierImpl(
|
||||||
|
FakeTypeAliasTypesMacro(), RemoteInstance.uniqueId),
|
||||||
|
Phase.declarations: MacroInstanceIdentifierImpl(
|
||||||
|
FakeTypeAliasDeclarationsMacro(), RemoteInstance.uniqueId),
|
||||||
|
},
|
||||||
DeclarationKind.variable: {
|
DeclarationKind.variable: {
|
||||||
Phase.types: MacroInstanceIdentifierImpl(
|
Phase.types: MacroInstanceIdentifierImpl(
|
||||||
FakeVariableTypesMacro(), RemoteInstance.uniqueId),
|
FakeVariableTypesMacro(), RemoteInstance.uniqueId),
|
||||||
|
@ -254,3 +262,8 @@ class FakeLibraryDeclarationsMacro extends Fake
|
||||||
|
|
||||||
class FakeLibraryDefinitionMacro extends Fake
|
class FakeLibraryDefinitionMacro extends Fake
|
||||||
implements LibraryDefinitionMacro {}
|
implements LibraryDefinitionMacro {}
|
||||||
|
|
||||||
|
class FakeTypeAliasTypesMacro extends Fake implements TypeAliasTypesMacro {}
|
||||||
|
|
||||||
|
class FakeTypeAliasDeclarationsMacro extends Fake
|
||||||
|
implements TypeAliasDeclarationsMacro {}
|
||||||
|
|
|
@ -69,6 +69,8 @@ class SimpleMacro
|
||||||
MixinTypesMacro,
|
MixinTypesMacro,
|
||||||
MixinDeclarationsMacro,
|
MixinDeclarationsMacro,
|
||||||
MixinDefinitionMacro,
|
MixinDefinitionMacro,
|
||||||
|
TypeAliasTypesMacro,
|
||||||
|
TypeAliasDeclarationsMacro,
|
||||||
VariableTypesMacro,
|
VariableTypesMacro,
|
||||||
VariableDeclarationsMacro,
|
VariableDeclarationsMacro,
|
||||||
VariableDefinitionMacro {
|
VariableDefinitionMacro {
|
||||||
|
@ -715,6 +717,32 @@ class LibraryInfo {
|
||||||
'];',
|
'];',
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<void> buildTypesForTypeAlias(
|
||||||
|
TypeAliasDeclaration extensionType, TypeBuilder builder) {
|
||||||
|
final representationType = extensionType.aliasedType as NamedTypeAnnotation;
|
||||||
|
final name = '${extensionType.identifier.name}AliasedType'
|
||||||
|
'${representationType.identifier.name}';
|
||||||
|
builder.declareType(name, DeclarationCode.fromString('class $name {}'));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<void> buildDeclarationsForTypeAlias(
|
||||||
|
TypeAliasDeclaration extensionType, DeclarationBuilder builder) async {
|
||||||
|
final dartCoreList =
|
||||||
|
// ignore: deprecated_member_use_from_same_package
|
||||||
|
await builder.resolveIdentifier(Uri.parse('dart:core'), 'List');
|
||||||
|
final dartCoreString =
|
||||||
|
// ignore: deprecated_member_use_from_same_package
|
||||||
|
await builder.resolveIdentifier(Uri.parse('dart:core'), 'String');
|
||||||
|
builder.declareInLibrary(DeclarationCode.fromParts([
|
||||||
|
NamedTypeAnnotationCode(name: dartCoreList, typeArguments: [
|
||||||
|
NamedTypeAnnotationCode(name: dartCoreString),
|
||||||
|
]),
|
||||||
|
' get aliasedTypeFieldNames;',
|
||||||
|
]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<FunctionBodyCode> _buildFunctionAugmentation(
|
Future<FunctionBodyCode> _buildFunctionAugmentation(
|
||||||
|
|
|
@ -687,6 +687,18 @@ class Fixtures {
|
||||||
typeParameters: [],
|
typeParameters: [],
|
||||||
representationType: myClassType);
|
representationType: myClassType);
|
||||||
|
|
||||||
|
static final myTypeAlias = TypeAliasDeclarationImpl(
|
||||||
|
id: RemoteInstance.uniqueId,
|
||||||
|
identifier: IdentifierImpl(
|
||||||
|
id: RemoteInstance.uniqueId,
|
||||||
|
name: 'MyTypeAlias',
|
||||||
|
),
|
||||||
|
library: Fixtures.library,
|
||||||
|
metadata: [],
|
||||||
|
typeParameters: [],
|
||||||
|
aliasedType: myClassType,
|
||||||
|
);
|
||||||
|
|
||||||
static final myGeneratedExtensionMethod = MethodDeclarationImpl(
|
static final myGeneratedExtensionMethod = MethodDeclarationImpl(
|
||||||
id: RemoteInstance.uniqueId,
|
id: RemoteInstance.uniqueId,
|
||||||
identifier:
|
identifier:
|
||||||
|
|
|
@ -95,7 +95,7 @@ import 'package:meta/meta.dart';
|
||||||
// TODO(scheglov): Clean up the list of implicitly analyzed files.
|
// TODO(scheglov): Clean up the list of implicitly analyzed files.
|
||||||
class AnalysisDriver {
|
class AnalysisDriver {
|
||||||
/// The version of data format, should be incremented on every format change.
|
/// The version of data format, should be incremented on every format change.
|
||||||
static const int DATA_VERSION = 346;
|
static const int DATA_VERSION = 347;
|
||||||
|
|
||||||
/// The number of exception contexts allowed to write. Once this field is
|
/// The number of exception contexts allowed to write. Once this field is
|
||||||
/// zero, we stop writing any new exception contexts in this process.
|
/// zero, we stop writing any new exception contexts in this process.
|
||||||
|
|
|
@ -125,6 +125,12 @@ class DeclarationByElementLocator extends UnifyingAstVisitor<void> {
|
||||||
if (node is VariableDeclaration && _hasOffset2(node.name)) {
|
if (node is VariableDeclaration && _hasOffset2(node.name)) {
|
||||||
result = node;
|
result = node;
|
||||||
}
|
}
|
||||||
|
} else if (element is TypeAliasElement) {
|
||||||
|
if (node is GenericTypeAlias) {
|
||||||
|
if (_hasOffset2(node.name)) {
|
||||||
|
result = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
|
|
|
@ -6736,7 +6736,7 @@ class TopLevelVariableElementImpl extends PropertyInducingElementImpl
|
||||||
///
|
///
|
||||||
/// Clients may not extend, implement or mix-in this class.
|
/// Clients may not extend, implement or mix-in this class.
|
||||||
class TypeAliasElementImpl extends _ExistingElementImpl
|
class TypeAliasElementImpl extends _ExistingElementImpl
|
||||||
with TypeParameterizedElementMixin
|
with TypeParameterizedElementMixin, MacroTargetElement
|
||||||
implements TypeAliasElement {
|
implements TypeAliasElement {
|
||||||
/// Is `true` if the element has direct or indirect reference to itself
|
/// Is `true` if the element has direct or indirect reference to itself
|
||||||
/// from anywhere except a class element or type parameter bounds.
|
/// from anywhere except a class element or type parameter bounds.
|
||||||
|
|
|
@ -932,12 +932,14 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void visitGenericTypeAlias(GenericTypeAlias node) {
|
void visitGenericTypeAlias(covariant GenericTypeAliasImpl node) {
|
||||||
|
var element = node.declaredElement as TypeAliasElementImpl;
|
||||||
_checkForBuiltInIdentifierAsName(
|
_checkForBuiltInIdentifierAsName(
|
||||||
node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME);
|
node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME);
|
||||||
_checkForMainFunction1(node.name, node.declaredElement!);
|
_checkForMainFunction1(node.name, node.declaredElement!);
|
||||||
_checkForTypeAliasCannotReferenceItself(
|
_checkForTypeAliasCannotReferenceItself(
|
||||||
node.name, node.declaredElement as TypeAliasElementImpl);
|
node.name, node.declaredElement as TypeAliasElementImpl);
|
||||||
|
_reportMacroDiagnostics(element);
|
||||||
super.visitGenericTypeAlias(node);
|
super.visitGenericTypeAlias(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6420,6 +6422,8 @@ class _MacroTypeAnnotationLocationConverter {
|
||||||
TypeAnnotationLocation location,
|
TypeAnnotationLocation location,
|
||||||
) {
|
) {
|
||||||
switch (location) {
|
switch (location) {
|
||||||
|
case AliasedTypeLocation():
|
||||||
|
return _aliasedType(location);
|
||||||
case ElementTypeLocation():
|
case ElementTypeLocation():
|
||||||
var element = location.element;
|
var element = location.element;
|
||||||
return libraryVerificationContext.declarationByElement(element);
|
return libraryVerificationContext.declarationByElement(element);
|
||||||
|
@ -6442,6 +6446,22 @@ class _MacroTypeAnnotationLocationConverter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_MacroSyntacticTypeAnnotationLocation? _aliasedType(
|
||||||
|
AliasedTypeLocation location,
|
||||||
|
) {
|
||||||
|
var nodeLocation = convert(location.parent);
|
||||||
|
if (nodeLocation == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var node = nodeLocation.entity;
|
||||||
|
switch (node) {
|
||||||
|
case GenericTypeAlias():
|
||||||
|
return nodeLocation.next(node.type);
|
||||||
|
default:
|
||||||
|
throw UnimplementedError('${node.runtimeType}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_MacroSyntacticTypeAnnotationLocation? _extendsClause(
|
_MacroSyntacticTypeAnnotationLocation? _extendsClause(
|
||||||
ExtendsClauseTypeLocation location,
|
ExtendsClauseTypeLocation location,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -149,6 +149,7 @@ class Tag {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TypeAnnotationLocationKind {
|
enum TypeAnnotationLocationKind {
|
||||||
|
aliasedType,
|
||||||
element,
|
element,
|
||||||
extendsClause,
|
extendsClause,
|
||||||
formalParameter,
|
formalParameter,
|
||||||
|
|
|
@ -2378,6 +2378,9 @@ class ResolutionReader {
|
||||||
TypeAnnotationLocation readTypeAnnotationLocation() {
|
TypeAnnotationLocation readTypeAnnotationLocation() {
|
||||||
var kind = readEnum(TypeAnnotationLocationKind.values);
|
var kind = readEnum(TypeAnnotationLocationKind.values);
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
case TypeAnnotationLocationKind.aliasedType:
|
||||||
|
var parent = readTypeAnnotationLocation();
|
||||||
|
return AliasedTypeLocation(parent);
|
||||||
case TypeAnnotationLocationKind.element:
|
case TypeAnnotationLocationKind.element:
|
||||||
var element = readElement()!;
|
var element = readElement()!;
|
||||||
return ElementTypeLocation(element);
|
return ElementTypeLocation(element);
|
||||||
|
@ -2603,6 +2606,7 @@ class TypeAliasElementLinkedData
|
||||||
element.metadata = reader._readAnnotationList(
|
element.metadata = reader._readAnnotationList(
|
||||||
unitElement: unitElement,
|
unitElement: unitElement,
|
||||||
);
|
);
|
||||||
|
element.macroDiagnostics = reader.readMacroDiagnostics();
|
||||||
_readTypeParameters(reader, element.typeParameters);
|
_readTypeParameters(reader, element.typeParameters);
|
||||||
element.aliasedElement = reader._readAliasedElement(unitElement);
|
element.aliasedElement = reader._readAliasedElement(unitElement);
|
||||||
element.aliasedType = reader.readRequiredType();
|
element.aliasedType = reader.readRequiredType();
|
||||||
|
|
|
@ -647,6 +647,7 @@ class BundleWriter {
|
||||||
TypeAliasElementFlags.write(_sink, element);
|
TypeAliasElementFlags.write(_sink, element);
|
||||||
|
|
||||||
_resolutionSink._writeAnnotationList(element.metadata);
|
_resolutionSink._writeAnnotationList(element.metadata);
|
||||||
|
_resolutionSink.writeMacroDiagnostics(element.macroDiagnostics);
|
||||||
|
|
||||||
_writeTypeParameters(element.typeParameters, () {
|
_writeTypeParameters(element.typeParameters, () {
|
||||||
_resolutionSink._writeAliasedElement(element.aliasedElement);
|
_resolutionSink._writeAliasedElement(element.aliasedElement);
|
||||||
|
@ -982,6 +983,9 @@ class ResolutionSink extends _SummaryDataWriter {
|
||||||
|
|
||||||
void writeTypeAnnotationLocation(TypeAnnotationLocation location) {
|
void writeTypeAnnotationLocation(TypeAnnotationLocation location) {
|
||||||
switch (location) {
|
switch (location) {
|
||||||
|
case AliasedTypeLocation():
|
||||||
|
writeEnum(TypeAnnotationLocationKind.aliasedType);
|
||||||
|
writeTypeAnnotationLocation(location.parent);
|
||||||
case ElementTypeLocation():
|
case ElementTypeLocation():
|
||||||
writeEnum(TypeAnnotationLocationKind.element);
|
writeEnum(TypeAnnotationLocationKind.element);
|
||||||
writeElement(location.element);
|
writeElement(location.element);
|
||||||
|
|
|
@ -218,8 +218,14 @@ class LibraryMacroApplier {
|
||||||
// TODO(scheglov): implement it
|
// TODO(scheglov): implement it
|
||||||
break;
|
break;
|
||||||
case ast.GenericTypeAliasImpl():
|
case ast.GenericTypeAliasImpl():
|
||||||
// TODO(scheglov): implement it
|
await _addAnnotations(
|
||||||
break;
|
libraryElement: libraryElement,
|
||||||
|
container: container,
|
||||||
|
targetNode: declaration,
|
||||||
|
targetNodeElement: declaration.declaredElement,
|
||||||
|
targetDeclarationKind: macro.DeclarationKind.typeAlias,
|
||||||
|
annotations: declaration.metadata,
|
||||||
|
);
|
||||||
case ast.MixinDeclarationImpl():
|
case ast.MixinDeclarationImpl():
|
||||||
final element = declaration.declaredElement!;
|
final element = declaration.declaredElement!;
|
||||||
final declarationElement = element.augmented?.declaration ?? element;
|
final declarationElement = element.augmented?.declaration ?? element;
|
||||||
|
|
|
@ -129,6 +129,8 @@ class DeclarationBuilder {
|
||||||
return fromNode.methodDeclaration(node);
|
return fromNode.methodDeclaration(node);
|
||||||
case ast.MixinDeclarationImpl():
|
case ast.MixinDeclarationImpl():
|
||||||
return fromNode.mixinDeclaration(node);
|
return fromNode.mixinDeclaration(node);
|
||||||
|
case ast.GenericTypeAliasImpl():
|
||||||
|
return fromNode.typeAliasDeclaration(node);
|
||||||
case ast.VariableDeclaration():
|
case ast.VariableDeclaration():
|
||||||
return fromNode.variableDeclaration(node);
|
return fromNode.variableDeclaration(node);
|
||||||
}
|
}
|
||||||
|
@ -579,6 +581,9 @@ class DeclarationBuilderFromElement {
|
||||||
final Map<ExecutableElement, MethodDeclarationImpl> _methodMap =
|
final Map<ExecutableElement, MethodDeclarationImpl> _methodMap =
|
||||||
Map.identity();
|
Map.identity();
|
||||||
|
|
||||||
|
final Map<TypeAliasElementImpl, TypeAliasDeclarationImpl> _typeAliasMap =
|
||||||
|
Map.identity();
|
||||||
|
|
||||||
final Map<TypeParameterElement, macro.TypeParameterDeclarationImpl>
|
final Map<TypeParameterElement, macro.TypeParameterDeclarationImpl>
|
||||||
_typeParameterDeclarationMap = Map.identity();
|
_typeParameterDeclarationMap = Map.identity();
|
||||||
|
|
||||||
|
@ -707,6 +712,12 @@ class DeclarationBuilderFromElement {
|
||||||
return _variableMap[element] ??= _topLevelVariableElement(element);
|
return _variableMap[element] ??= _topLevelVariableElement(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro.TypeAliasDeclarationImpl typeAliasElement(
|
||||||
|
TypeAliasElementImpl element,
|
||||||
|
) {
|
||||||
|
return _typeAliasMap[element] ??= _typeAliasElement(element);
|
||||||
|
}
|
||||||
|
|
||||||
/// See [macro.DeclarationPhaseIntrospector.typeDeclarationOf].
|
/// See [macro.DeclarationPhaseIntrospector.typeDeclarationOf].
|
||||||
macro.TypeDeclarationImpl typeDeclarationOf(Element element) {
|
macro.TypeDeclarationImpl typeDeclarationOf(Element element) {
|
||||||
switch (element) {
|
switch (element) {
|
||||||
|
@ -720,6 +731,8 @@ class DeclarationBuilderFromElement {
|
||||||
return extensionTypeElement(element);
|
return extensionTypeElement(element);
|
||||||
case MixinElementImpl():
|
case MixinElementImpl():
|
||||||
return mixinElement(element);
|
return mixinElement(element);
|
||||||
|
case TypeAliasElementImpl():
|
||||||
|
return typeAliasElement(element);
|
||||||
default:
|
default:
|
||||||
// TODO(scheglov): other elements
|
// TODO(scheglov): other elements
|
||||||
throw macro.MacroImplementationExceptionImpl(
|
throw macro.MacroImplementationExceptionImpl(
|
||||||
|
@ -1042,6 +1055,20 @@ class DeclarationBuilderFromElement {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeAliasDeclarationImpl _typeAliasElement(
|
||||||
|
TypeAliasElementImpl element,
|
||||||
|
) {
|
||||||
|
return TypeAliasDeclarationImpl._(
|
||||||
|
id: macro.RemoteInstance.uniqueId,
|
||||||
|
element: element,
|
||||||
|
identifier: identifier(element),
|
||||||
|
library: library(element),
|
||||||
|
metadata: _buildMetadata(element),
|
||||||
|
aliasedType: _dartType(element.aliasedType),
|
||||||
|
typeParameters: _typeParameterDeclarations(element.typeParameters),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
macro.TypeParameterImpl _typeParameter(
|
macro.TypeParameterImpl _typeParameter(
|
||||||
TypeParameterElement element,
|
TypeParameterElement element,
|
||||||
) {
|
) {
|
||||||
|
@ -1439,6 +1466,22 @@ class DeclarationBuilderFromNode {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro.TypeAliasDeclarationImpl typeAliasDeclaration(
|
||||||
|
ast.GenericTypeAliasImpl node,
|
||||||
|
) {
|
||||||
|
final element = node.declaredElement as TypeAliasElementImpl;
|
||||||
|
|
||||||
|
return TypeAliasDeclarationImpl._(
|
||||||
|
id: macro.RemoteInstance.uniqueId,
|
||||||
|
element: element,
|
||||||
|
identifier: _declaredIdentifier(node.name, element),
|
||||||
|
library: library(element),
|
||||||
|
metadata: _buildMetadata(element),
|
||||||
|
aliasedType: _typeAnnotationAliasedType(node),
|
||||||
|
typeParameters: _typeParameterDeclarations(node.typeParameters),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// See [macro.DeclarationPhaseIntrospector.typeDeclarationOf].
|
/// See [macro.DeclarationPhaseIntrospector.typeDeclarationOf].
|
||||||
macro.TypeDeclarationImpl typeDeclarationOf(ast.AstNode node) {
|
macro.TypeDeclarationImpl typeDeclarationOf(ast.AstNode node) {
|
||||||
switch (node) {
|
switch (node) {
|
||||||
|
@ -1791,6 +1834,17 @@ class DeclarationBuilderFromNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro.TypeAnnotationImpl _typeAnnotationAliasedType(
|
||||||
|
ast.GenericTypeAliasImpl node,
|
||||||
|
) {
|
||||||
|
final element = node.declaredElement as TypeAliasElementImpl;
|
||||||
|
var location = AliasedTypeLocation(
|
||||||
|
ElementTypeLocation(element),
|
||||||
|
);
|
||||||
|
|
||||||
|
return _typeAnnotation(node.type, location);
|
||||||
|
}
|
||||||
|
|
||||||
macro.TypeAnnotationImpl _typeAnnotationFunctionReturnType(
|
macro.TypeAnnotationImpl _typeAnnotationFunctionReturnType(
|
||||||
ast.FunctionDeclaration node,
|
ast.FunctionDeclaration node,
|
||||||
) {
|
) {
|
||||||
|
@ -2206,6 +2260,22 @@ class MixinDeclarationImpl extends macro.MixinDeclarationImpl
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TypeAliasDeclarationImpl extends macro.TypeAliasDeclarationImpl
|
||||||
|
implements HasElement {
|
||||||
|
@override
|
||||||
|
final TypeAliasElementImpl element;
|
||||||
|
|
||||||
|
TypeAliasDeclarationImpl._({
|
||||||
|
required super.id,
|
||||||
|
required super.identifier,
|
||||||
|
required super.library,
|
||||||
|
required super.metadata,
|
||||||
|
required super.typeParameters,
|
||||||
|
required super.aliasedType,
|
||||||
|
required this.element,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
abstract class TypeAnnotationWithLocation implements macro.TypeAnnotation {
|
abstract class TypeAnnotationWithLocation implements macro.TypeAnnotation {
|
||||||
TypeAnnotationLocation get location;
|
TypeAnnotationLocation get location;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,12 @@
|
||||||
import 'package:_fe_analyzer_shared/src/macros/api.dart' as macro;
|
import 'package:_fe_analyzer_shared/src/macros/api.dart' as macro;
|
||||||
import 'package:analyzer/dart/element/element.dart';
|
import 'package:analyzer/dart/element/element.dart';
|
||||||
|
|
||||||
|
final class AliasedTypeLocation extends TypeAnnotationLocation {
|
||||||
|
final TypeAnnotationLocation parent;
|
||||||
|
|
||||||
|
AliasedTypeLocation(this.parent);
|
||||||
|
}
|
||||||
|
|
||||||
final class ElementTypeLocation extends TypeAnnotationLocation {
|
final class ElementTypeLocation extends TypeAnnotationLocation {
|
||||||
final Element element;
|
final Element element;
|
||||||
|
|
||||||
|
|
|
@ -273,6 +273,16 @@ typedef F = void Function();
|
||||||
expect(result, isNull);
|
expect(result, isNull);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_genericTypeAlias() async {
|
||||||
|
await resolveTestCode(r'''
|
||||||
|
typedef A = List<int>;
|
||||||
|
''');
|
||||||
|
var element = findNode.genericTypeAlias('A').declaredElement!;
|
||||||
|
var result = await getElementDeclaration(element);
|
||||||
|
var node = result!.node as GenericTypeAlias;
|
||||||
|
expect(node.name.lexeme, 'A');
|
||||||
|
}
|
||||||
|
|
||||||
test_getter_class() async {
|
test_getter_class() async {
|
||||||
await resolveTestCode(r'''
|
await resolveTestCode(r'''
|
||||||
class A {
|
class A {
|
||||||
|
|
|
@ -743,6 +743,19 @@ class A {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
test_diagnostic_report_contextMessages_superClassMethods() async {
|
||||||
var a = newFile('$testPackageLibPath/a.dart', r'''
|
var a = newFile('$testPackageLibPath/a.dart', r'''
|
||||||
class A {
|
class A {
|
||||||
|
|
|
@ -743,6 +743,9 @@ class _ElementWriter {
|
||||||
void _writeMacroDiagnostics(Element e) {
|
void _writeMacroDiagnostics(Element e) {
|
||||||
void writeTypeAnnotationLocation(TypeAnnotationLocation location) {
|
void writeTypeAnnotationLocation(TypeAnnotationLocation location) {
|
||||||
switch (location) {
|
switch (location) {
|
||||||
|
case AliasedTypeLocation():
|
||||||
|
writeTypeAnnotationLocation(location.parent);
|
||||||
|
_sink.writelnWithIndent('AliasedTypeLocation');
|
||||||
case ElementTypeLocation():
|
case ElementTypeLocation():
|
||||||
_sink.writelnWithIndent('ElementTypeLocation');
|
_sink.writelnWithIndent('ElementTypeLocation');
|
||||||
_sink.withIndent(() {
|
_sink.withIndent(() {
|
||||||
|
@ -1370,6 +1373,8 @@ class _ElementWriter {
|
||||||
_writeReturnType(aliasedElement.returnType);
|
_writeReturnType(aliasedElement.returnType);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_writeMacroDiagnostics(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
_assertNonSyntheticElementSelf(e);
|
_assertNonSyntheticElementSelf(e);
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
// 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.
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:_fe_analyzer_shared/src/macros/api.dart';
|
import 'package:_fe_analyzer_shared/src/macros/api.dart';
|
||||||
|
|
||||||
/*macro*/ class AskFieldsWillThrow implements ClassDefinitionMacro {
|
/*macro*/ class AskFieldsWillThrow implements ClassDefinitionMacro {
|
||||||
|
@ -144,6 +146,7 @@ import 'package:_fe_analyzer_shared/src/macros/api.dart';
|
||||||
FunctionDeclarationsMacro,
|
FunctionDeclarationsMacro,
|
||||||
FieldDeclarationsMacro,
|
FieldDeclarationsMacro,
|
||||||
MethodDeclarationsMacro,
|
MethodDeclarationsMacro,
|
||||||
|
TypeAliasDeclarationsMacro,
|
||||||
VariableDeclarationsMacro {
|
VariableDeclarationsMacro {
|
||||||
final List<String> pathList;
|
final List<String> pathList;
|
||||||
|
|
||||||
|
@ -169,6 +172,11 @@ import 'package:_fe_analyzer_shared/src/macros/api.dart';
|
||||||
await _report(declaration, builder);
|
await _report(declaration, builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> buildDeclarationsForTypeAlias(declaration, builder) async {
|
||||||
|
await _report(declaration, builder);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
buildDeclarationsForVariable(declaration, builder) async {
|
buildDeclarationsForVariable(declaration, builder) async {
|
||||||
await _report(declaration, builder);
|
await _report(declaration, builder);
|
||||||
|
@ -248,6 +256,12 @@ import 'package:_fe_analyzer_shared/src/macros/api.dart';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (current is TypeAliasDeclaration) {
|
||||||
|
if (step == 'aliasedType') {
|
||||||
|
return current.aliasedType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (current is VariableDeclaration) {
|
if (current is VariableDeclaration) {
|
||||||
if (step == 'variableType') {
|
if (step == 'variableType') {
|
||||||
return current.type;
|
return current.type;
|
||||||
|
|
|
@ -19,6 +19,7 @@ import 'package:_fe_analyzer_shared/src/macros/api.dart';
|
||||||
LibraryDeclarationsMacro,
|
LibraryDeclarationsMacro,
|
||||||
MethodDeclarationsMacro,
|
MethodDeclarationsMacro,
|
||||||
MixinDeclarationsMacro,
|
MixinDeclarationsMacro,
|
||||||
|
TypeAliasDeclarationsMacro,
|
||||||
VariableDeclarationsMacro {
|
VariableDeclarationsMacro {
|
||||||
final Set<Object?> withDetailsFor;
|
final Set<Object?> withDetailsFor;
|
||||||
final bool withMetadata;
|
final bool withMetadata;
|
||||||
|
@ -163,6 +164,16 @@ import 'package:_fe_analyzer_shared/src/macros/api.dart';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> buildDeclarationsForTypeAlias(
|
||||||
|
TypeAliasDeclaration declaration,
|
||||||
|
DeclarationBuilder builder,
|
||||||
|
) async {
|
||||||
|
await _write(builder, declaration, (printer) async {
|
||||||
|
await printer.writeTypeAliasDeclaration(declaration);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> buildDeclarationsForVariable(
|
Future<void> buildDeclarationsForVariable(
|
||||||
VariableDeclaration declaration,
|
VariableDeclaration declaration,
|
||||||
|
@ -438,6 +449,8 @@ class _Printer {
|
||||||
await writeFunctionDeclaration(declaration);
|
await writeFunctionDeclaration(declaration);
|
||||||
case MixinDeclaration():
|
case MixinDeclaration():
|
||||||
await writeMixinDeclaration(declaration);
|
await writeMixinDeclaration(declaration);
|
||||||
|
case TypeAliasDeclaration():
|
||||||
|
await writeTypeAliasDeclaration(declaration);
|
||||||
case VariableDeclaration():
|
case VariableDeclaration():
|
||||||
await writeVariable(declaration);
|
await writeVariable(declaration);
|
||||||
default:
|
default:
|
||||||
|
@ -652,6 +665,24 @@ class _Printer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> writeTypeAliasDeclaration(TypeAliasDeclaration e) async {
|
||||||
|
if (!shouldWriteDetailsFor(e)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sink.writelnWithIndent('typedef ${e.identifier.name}');
|
||||||
|
|
||||||
|
await sink.withIndent(() async {
|
||||||
|
await _writeMetadata(e);
|
||||||
|
|
||||||
|
await _writeTypeParameters(e.typeParameters);
|
||||||
|
await _writeNamedTypeAnnotation(
|
||||||
|
'aliasedType',
|
||||||
|
e.aliasedType,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> writeVariable(VariableDeclaration e) async {
|
Future<void> writeVariable(VariableDeclaration e) async {
|
||||||
sink.writelnWithIndent(e.identifier.name);
|
sink.writelnWithIndent(e.identifier.name);
|
||||||
|
|
||||||
|
|
|
@ -6690,6 +6690,44 @@ library
|
||||||
''');
|
''');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_macroDiagnostics_report_atTypeAnnotation_typeAlias_aliasedType() async {
|
||||||
|
newFile(
|
||||||
|
'$testPackageLibPath/diagnostic.dart',
|
||||||
|
_getMacroCode('diagnostic.dart'),
|
||||||
|
);
|
||||||
|
|
||||||
|
final library = await buildLibrary(r'''
|
||||||
|
import 'diagnostic.dart';
|
||||||
|
|
||||||
|
@ReportAtTypeAnnotation([
|
||||||
|
'aliasedType',
|
||||||
|
])
|
||||||
|
typedef A = List<int>;
|
||||||
|
''');
|
||||||
|
|
||||||
|
configuration
|
||||||
|
..withConstructors = false
|
||||||
|
..withMetadata = false;
|
||||||
|
checkElementText(library, r'''
|
||||||
|
library
|
||||||
|
imports
|
||||||
|
package:test/diagnostic.dart
|
||||||
|
definingUnit
|
||||||
|
typeAliases
|
||||||
|
A @81
|
||||||
|
aliasedType: List<int>
|
||||||
|
macroDiagnostics
|
||||||
|
MacroDiagnostic
|
||||||
|
message: MacroDiagnosticMessage
|
||||||
|
message: Reported message
|
||||||
|
target: TypeAnnotationMacroDiagnosticTarget
|
||||||
|
ElementTypeLocation
|
||||||
|
element: self::@typeAlias::A
|
||||||
|
AliasedTypeLocation
|
||||||
|
severity: warning
|
||||||
|
''');
|
||||||
|
}
|
||||||
|
|
||||||
test_macroDiagnostics_report_contextMessages() async {
|
test_macroDiagnostics_report_contextMessages() async {
|
||||||
newFile(
|
newFile(
|
||||||
'$testPackageLibPath/diagnostic.dart',
|
'$testPackageLibPath/diagnostic.dart',
|
||||||
|
@ -9002,6 +9040,17 @@ foo
|
||||||
''');
|
''');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_unit_typeAlias() async {
|
||||||
|
newFile('$testPackageLibPath/a.dart', r'''
|
||||||
|
typedef A = List<int>;
|
||||||
|
''');
|
||||||
|
|
||||||
|
await _assertIntrospectText('A', r'''
|
||||||
|
typedef A
|
||||||
|
aliasedType: List<int>
|
||||||
|
''');
|
||||||
|
}
|
||||||
|
|
||||||
test_unit_variable() async {
|
test_unit_variable() async {
|
||||||
newFile('$testPackageLibPath/a.dart', r'''
|
newFile('$testPackageLibPath/a.dart', r'''
|
||||||
final foo = 0;
|
final foo = 0;
|
||||||
|
@ -11416,6 +11465,16 @@ class A
|
||||||
''');
|
''');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_typedef_modern_namedType() async {
|
||||||
|
await _assertIntrospectText(r'''
|
||||||
|
@Introspect()
|
||||||
|
typedef X = List<int>;
|
||||||
|
''', r'''
|
||||||
|
typedef X
|
||||||
|
aliasedType: List<int>
|
||||||
|
''');
|
||||||
|
}
|
||||||
|
|
||||||
test_unit_function() async {
|
test_unit_function() async {
|
||||||
await _assertIntrospectText(r'''
|
await _assertIntrospectText(r'''
|
||||||
@Introspect()
|
@Introspect()
|
||||||
|
|
|
@ -264,3 +264,22 @@ abstract interface class ExtensionTypeDefinitionMacro implements Macro {
|
||||||
FutureOr<void> buildDefinitionForExtensionType(
|
FutureOr<void> buildDefinitionForExtensionType(
|
||||||
ExtensionTypeDeclaration extension, TypeDefinitionBuilder builder);
|
ExtensionTypeDeclaration extension, TypeDefinitionBuilder builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The interface for [Macro]s that can be applied to any type alias
|
||||||
|
/// declaration, and want to contribute new type declarations to the program.
|
||||||
|
abstract interface class TypeAliasTypesMacro implements Macro {
|
||||||
|
FutureOr<void> buildTypesForTypeAlias(
|
||||||
|
TypeAliasDeclaration declaration,
|
||||||
|
TypeBuilder builder,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The interface for [Macro]s that can be applied to any type alias
|
||||||
|
/// declaration, and want to contribute new non-type declarations to the
|
||||||
|
/// program.
|
||||||
|
abstract interface class TypeAliasDeclarationsMacro implements Macro {
|
||||||
|
FutureOr<void> buildDeclarationsForTypeAlias(
|
||||||
|
TypeAliasDeclaration declaration,
|
||||||
|
DeclarationBuilder builder,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue