mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:29:47 +00:00
Revert "Add wrappers for macro arguments to help with serialization."
This reverts commit ea7e014c3c
.
Reason for revert: breaks Analyzer tests, CBuild regression.
Original change's description:
> Add wrappers for macro arguments to help with serialization.
>
> In particular this allows us to reproduce type arguments for collections in the
> macro expansion isolate.
>
> The type arguments have to be explicitly given for collection types,
> but this should be doable given they are all constants and only certain
> types are allowed.
>
> Bug: https://github.com/dart-lang/language/issues/2212
> Change-Id: I14a688ed294cf060c004849efa975b5bef053d5b
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/308202
> Reviewed-by: Bob Nystrom <rnystrom@google.com>
> Reviewed-by: Johnni Winther <johnniwinther@google.com>
> Commit-Queue: Jake Macdonald <jakemac@google.com>
> Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Bug: https://github.com/dart-lang/language/issues/2212
Change-Id: I402802c7a1c27f9aee3f23baef8c0deb71ec06e9
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/309284
Commit-Queue: Ilya Yanok <yanok@google.com>
Reviewed-by: Alexander Thomas <athom@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
This commit is contained in:
parent
c1969260e8
commit
396ed71267
|
@ -200,11 +200,9 @@ Future<SerializableResponse> _instantiateMacro(
|
|||
'macro class "\${request.name}".');
|
||||
}
|
||||
|
||||
var instance = Function.apply(constructor, [
|
||||
for (var argument in request.arguments.positional) argument.value,
|
||||
], {
|
||||
for (MapEntry<String, Argument> entry in request.arguments.named.entries)
|
||||
new Symbol(entry.key): entry.value.value,
|
||||
var instance = Function.apply(constructor, request.arguments.positional, {
|
||||
for (MapEntry<String, Object?> entry in request.arguments.named.entries)
|
||||
new Symbol(entry.key): entry.value,
|
||||
}) as Macro;
|
||||
var identifier = new MacroInstanceIdentifierImpl(instance, request.instanceId);
|
||||
_macroInstances[identifier] = instance;
|
||||
|
|
|
@ -2,16 +2,11 @@
|
|||
// 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:dart_internal/extract_type_arguments.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import 'api.dart';
|
||||
// ignore: unused_import
|
||||
import 'bootstrap.dart'; // For doc comments only.
|
||||
import 'executor/serialization.dart';
|
||||
|
||||
part 'executor/arguments.dart';
|
||||
|
||||
/// The interface used by Dart language implementations, in order to load
|
||||
/// and execute macros, as well as produce library augmentations from those
|
||||
/// macro applications.
|
||||
|
@ -91,6 +86,146 @@ abstract class MacroExecutor {
|
|||
Future<void> close();
|
||||
}
|
||||
|
||||
/// The arguments passed to a macro constructor.
|
||||
///
|
||||
/// All argument instances must be of type [Code] or a built-in value type that
|
||||
/// is serializable (num, bool, String, null, etc).
|
||||
class Arguments implements Serializable {
|
||||
final List<Object?> positional;
|
||||
|
||||
final Map<String, Object?> named;
|
||||
|
||||
Arguments(this.positional, this.named);
|
||||
|
||||
factory Arguments.deserialize(Deserializer deserializer) {
|
||||
deserializer
|
||||
..moveNext()
|
||||
..expectList();
|
||||
List<Object?> positionalArgs = [
|
||||
for (bool hasNext = deserializer.moveNext();
|
||||
hasNext;
|
||||
hasNext = deserializer.moveNext())
|
||||
_deserializeArg(deserializer, alreadyMoved: true),
|
||||
];
|
||||
deserializer
|
||||
..moveNext()
|
||||
..expectList();
|
||||
Map<String, Object?> namedArgs = {
|
||||
for (bool hasNext = deserializer.moveNext();
|
||||
hasNext;
|
||||
hasNext = deserializer.moveNext())
|
||||
deserializer.expectString(): _deserializeArg(deserializer),
|
||||
};
|
||||
return new Arguments(positionalArgs, namedArgs);
|
||||
}
|
||||
|
||||
static Object? _deserializeArg(Deserializer deserializer,
|
||||
{bool alreadyMoved = false}) {
|
||||
if (!alreadyMoved) deserializer.moveNext();
|
||||
_ArgumentKind kind = _ArgumentKind.values[deserializer.expectInt()];
|
||||
return switch (kind) {
|
||||
_ArgumentKind.nil => null,
|
||||
_ArgumentKind.string => (deserializer..moveNext()).expectString(),
|
||||
_ArgumentKind.bool => (deserializer..moveNext()).expectBool(),
|
||||
_ArgumentKind.int => (deserializer..moveNext()).expectInt(),
|
||||
_ArgumentKind.double => (deserializer..moveNext()).expectDouble(),
|
||||
_ArgumentKind.list => [
|
||||
for (bool hasNext = (deserializer
|
||||
..moveNext()
|
||||
..expectList())
|
||||
.moveNext();
|
||||
hasNext;
|
||||
hasNext = deserializer.moveNext())
|
||||
_deserializeArg(deserializer, alreadyMoved: true),
|
||||
],
|
||||
_ArgumentKind.set => {
|
||||
for (bool hasNext = (deserializer
|
||||
..moveNext()
|
||||
..expectList())
|
||||
.moveNext();
|
||||
hasNext;
|
||||
hasNext = deserializer.moveNext())
|
||||
_deserializeArg(deserializer, alreadyMoved: true),
|
||||
},
|
||||
_ArgumentKind.map => {
|
||||
for (bool hasNext = (deserializer
|
||||
..moveNext()
|
||||
..expectList())
|
||||
.moveNext();
|
||||
hasNext;
|
||||
hasNext = deserializer.moveNext())
|
||||
_deserializeArg(deserializer, alreadyMoved: true):
|
||||
_deserializeArg(deserializer),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
void serialize(Serializer serializer) {
|
||||
serializer.startList();
|
||||
for (Object? arg in positional) {
|
||||
_serializeArg(arg, serializer);
|
||||
}
|
||||
serializer.endList();
|
||||
|
||||
serializer.startList();
|
||||
for (MapEntry<String, Object?> arg in named.entries) {
|
||||
serializer.addString(arg.key);
|
||||
_serializeArg(arg.value, serializer);
|
||||
}
|
||||
serializer.endList();
|
||||
}
|
||||
|
||||
static void _serializeArg(Object? arg, Serializer serializer) {
|
||||
if (arg == null) {
|
||||
serializer.addInt(_ArgumentKind.nil.index);
|
||||
} else if (arg is String) {
|
||||
serializer
|
||||
..addInt(_ArgumentKind.string.index)
|
||||
..addString(arg);
|
||||
} else if (arg is int) {
|
||||
serializer
|
||||
..addInt(_ArgumentKind.int.index)
|
||||
..addInt(arg);
|
||||
} else if (arg is double) {
|
||||
serializer
|
||||
..addInt(_ArgumentKind.double.index)
|
||||
..addDouble(arg);
|
||||
} else if (arg is bool) {
|
||||
serializer
|
||||
..addInt(_ArgumentKind.bool.index)
|
||||
..addBool(arg);
|
||||
} else if (arg is List) {
|
||||
serializer
|
||||
..addInt(_ArgumentKind.list.index)
|
||||
..startList();
|
||||
for (Object? item in arg) {
|
||||
_serializeArg(item, serializer);
|
||||
}
|
||||
serializer.endList();
|
||||
} else if (arg is Set) {
|
||||
serializer
|
||||
..addInt(_ArgumentKind.set.index)
|
||||
..startList();
|
||||
for (Object? item in arg) {
|
||||
_serializeArg(item, serializer);
|
||||
}
|
||||
serializer.endList();
|
||||
} else if (arg is Map) {
|
||||
serializer
|
||||
..addInt(_ArgumentKind.map.index)
|
||||
..startList();
|
||||
for (MapEntry<Object?, Object?> entry in arg.entries) {
|
||||
_serializeArg(entry.key, serializer);
|
||||
_serializeArg(entry.value, serializer);
|
||||
}
|
||||
serializer.endList();
|
||||
} else {
|
||||
throw new UnsupportedError('Unsupported argument type $arg');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A resolved [Identifier], this is used when creating augmentation libraries
|
||||
/// to qualify identifiers where needed.
|
||||
class ResolvedIdentifier implements Identifier {
|
||||
|
@ -190,3 +325,15 @@ enum Phase {
|
|||
/// This phase allows augmenting existing declarations.
|
||||
definitions,
|
||||
}
|
||||
|
||||
/// Used for serializing and deserializing arguments.
|
||||
enum _ArgumentKind {
|
||||
string,
|
||||
bool,
|
||||
double,
|
||||
int,
|
||||
list,
|
||||
map,
|
||||
set,
|
||||
nil,
|
||||
}
|
||||
|
|
|
@ -1,424 +0,0 @@
|
|||
// Copyright (c) 2023, 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.
|
||||
|
||||
part of '../executor.dart';
|
||||
|
||||
/// Representation of an argument to a macro constructor.
|
||||
sealed class Argument implements Serializable {
|
||||
ArgumentKind get kind;
|
||||
|
||||
Object? get value;
|
||||
|
||||
Argument();
|
||||
|
||||
/// Reads the next argument from [Deserializer].
|
||||
///
|
||||
/// By default this will call `moveNext` on [deserializer] before reading the
|
||||
/// argument kind, but this can be skipped by passing `true` for
|
||||
/// [alreadyMoved].
|
||||
factory Argument.deserialize(Deserializer deserializer,
|
||||
{bool alreadyMoved = false}) {
|
||||
if (!alreadyMoved) deserializer.moveNext();
|
||||
final ArgumentKind kind = ArgumentKind.values[deserializer.expectInt()];
|
||||
return switch (kind) {
|
||||
ArgumentKind.string =>
|
||||
new StringArgument((deserializer..moveNext()).expectString()),
|
||||
ArgumentKind.bool =>
|
||||
new BoolArgument((deserializer..moveNext()).expectBool()),
|
||||
ArgumentKind.double =>
|
||||
new DoubleArgument((deserializer..moveNext()).expectDouble()),
|
||||
ArgumentKind.int =>
|
||||
new IntArgument((deserializer..moveNext()).expectInt()),
|
||||
ArgumentKind.list ||
|
||||
ArgumentKind.set =>
|
||||
new _IterableArgument._deserialize(kind, deserializer),
|
||||
ArgumentKind.map => new MapArgument._deserialize(deserializer),
|
||||
ArgumentKind.nil => new NullArgument(),
|
||||
// These are just for type arguments and aren't supported as actual args.\
|
||||
ArgumentKind.object ||
|
||||
ArgumentKind.dynamic ||
|
||||
ArgumentKind.num ||
|
||||
ArgumentKind.nullable =>
|
||||
throw new StateError('Argument kind $kind is not deserializable'),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
@mustBeOverridden
|
||||
@mustCallSuper
|
||||
void serialize(Serializer serializer) {
|
||||
serializer.addInt(kind.index);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType:$value';
|
||||
}
|
||||
|
||||
final class BoolArgument extends Argument {
|
||||
@override
|
||||
ArgumentKind get kind => ArgumentKind.bool;
|
||||
|
||||
@override
|
||||
final bool value;
|
||||
|
||||
BoolArgument(this.value);
|
||||
|
||||
@override
|
||||
void serialize(Serializer serializer) {
|
||||
super.serialize(serializer);
|
||||
serializer.addBool(value);
|
||||
}
|
||||
}
|
||||
|
||||
final class DoubleArgument extends Argument {
|
||||
@override
|
||||
ArgumentKind get kind => ArgumentKind.double;
|
||||
|
||||
@override
|
||||
final double value;
|
||||
|
||||
DoubleArgument(this.value);
|
||||
|
||||
@override
|
||||
void serialize(Serializer serializer) {
|
||||
super.serialize(serializer);
|
||||
serializer.addDouble(value);
|
||||
}
|
||||
}
|
||||
|
||||
final class IntArgument extends Argument {
|
||||
@override
|
||||
ArgumentKind get kind => ArgumentKind.int;
|
||||
|
||||
@override
|
||||
final int value;
|
||||
|
||||
IntArgument(this.value);
|
||||
|
||||
@override
|
||||
void serialize(Serializer serializer) {
|
||||
super.serialize(serializer);
|
||||
serializer.addInt(value);
|
||||
}
|
||||
}
|
||||
|
||||
final class NullArgument extends Argument {
|
||||
@override
|
||||
ArgumentKind get kind => ArgumentKind.nil;
|
||||
|
||||
@override
|
||||
Null get value => null;
|
||||
|
||||
@override
|
||||
void serialize(Serializer serializer) => super.serialize(serializer);
|
||||
}
|
||||
|
||||
final class StringArgument extends Argument {
|
||||
@override
|
||||
ArgumentKind get kind => ArgumentKind.string;
|
||||
|
||||
@override
|
||||
final String value;
|
||||
|
||||
StringArgument(this.value);
|
||||
|
||||
@override
|
||||
void serialize(Serializer serializer) {
|
||||
super.serialize(serializer);
|
||||
serializer.addString(value);
|
||||
}
|
||||
}
|
||||
|
||||
abstract base class _CollectionArgument extends Argument {
|
||||
/// Flat list of the actual reified type arguments for this list, in the order
|
||||
/// they would appear if written in code.
|
||||
///
|
||||
/// For nullable types, they should be preceded by an [ArgumentKind.nullable].
|
||||
///
|
||||
/// Note that nested type arguments appear here and are just flattened, so
|
||||
/// the type `List<Map<String, List<int>?>>` would have the type arguments:
|
||||
///
|
||||
/// [
|
||||
/// ArgumentKind.map,
|
||||
/// ArgumentKind.string,
|
||||
/// ArgumentKind.nullable,
|
||||
/// ArgumentKind.list,
|
||||
/// ArgumentKind.int,
|
||||
/// ]
|
||||
final List<ArgumentKind> _typeArguments;
|
||||
|
||||
_CollectionArgument(this._typeArguments);
|
||||
|
||||
/// Creates a one or two element list, based on [_typeArguments]. These lists
|
||||
/// each contain reified generic type arguments that match the serialized
|
||||
/// [_typeArguments].
|
||||
///
|
||||
/// You can extract the type arguments to build up the actual collection type
|
||||
/// that you need.
|
||||
///
|
||||
/// For an iterable, this will always have a single value, and for a map it
|
||||
/// will always have two values.
|
||||
List<List<Object?>> _extractTypeArguments() {
|
||||
List<List<Object?>> typedInstanceStack = [];
|
||||
|
||||
// We build up the list type backwards.
|
||||
for (ArgumentKind type in _typeArguments.reversed) {
|
||||
typedInstanceStack.add(switch (type) {
|
||||
ArgumentKind.bool => const <bool>[],
|
||||
ArgumentKind.double => const <double>[],
|
||||
ArgumentKind.int => const <int>[],
|
||||
ArgumentKind.map =>
|
||||
extractIterableTypeArgument(typedInstanceStack.removeLast(), <K>() {
|
||||
return extractIterableTypeArgument(typedInstanceStack.removeLast(),
|
||||
<V>() {
|
||||
return new List<Map<K, V>>.empty();
|
||||
});
|
||||
}) as List<Object?>,
|
||||
ArgumentKind.nil => const <Null>[],
|
||||
ArgumentKind.set =>
|
||||
extractIterableTypeArgument(typedInstanceStack.removeLast(), <S>() {
|
||||
return new List<Set<S>>.empty();
|
||||
}) as List<Object?>,
|
||||
ArgumentKind.string => const <String>[],
|
||||
ArgumentKind.list =>
|
||||
extractIterableTypeArgument(typedInstanceStack.removeLast(), <S>() {
|
||||
return new List<List<S>>.empty();
|
||||
}) as List<Object?>,
|
||||
ArgumentKind.object => const <Object>[],
|
||||
ArgumentKind.dynamic => const <dynamic>[],
|
||||
ArgumentKind.num => const <num>[],
|
||||
ArgumentKind.nullable =>
|
||||
extractIterableTypeArgument(typedInstanceStack.removeLast(), <S>() {
|
||||
return new List<S?>.empty();
|
||||
}) as List<Object?>,
|
||||
});
|
||||
}
|
||||
|
||||
return typedInstanceStack;
|
||||
}
|
||||
|
||||
@override
|
||||
void serialize(Serializer serializer) {
|
||||
super.serialize(serializer);
|
||||
serializer.startList();
|
||||
for (ArgumentKind typeArgument in _typeArguments) {
|
||||
serializer.addInt(typeArgument.index);
|
||||
}
|
||||
serializer.endList();
|
||||
}
|
||||
}
|
||||
|
||||
/// The base class for [ListArgument] and [SetArgument], most of the logic is
|
||||
/// the same.
|
||||
abstract base class _IterableArgument<T extends Iterable<Object?>>
|
||||
extends _CollectionArgument {
|
||||
/// These are the raw argument values for each entry in this iterable.
|
||||
final List<Argument> _arguments;
|
||||
|
||||
_IterableArgument(this._arguments, super._typeArguments);
|
||||
|
||||
factory _IterableArgument._deserialize(
|
||||
ArgumentKind kind, Deserializer deserializer) {
|
||||
deserializer
|
||||
..moveNext()
|
||||
..expectList();
|
||||
final List<ArgumentKind> typeArguments = [
|
||||
for (bool hasNext = deserializer.moveNext();
|
||||
hasNext;
|
||||
hasNext = deserializer.moveNext())
|
||||
ArgumentKind.values[deserializer.expectInt()],
|
||||
];
|
||||
deserializer
|
||||
..moveNext()
|
||||
..expectList();
|
||||
final List<Argument> values = [
|
||||
for (bool hasNext = deserializer.moveNext();
|
||||
hasNext;
|
||||
hasNext = deserializer.moveNext())
|
||||
new Argument.deserialize(deserializer, alreadyMoved: true),
|
||||
];
|
||||
return switch (kind) {
|
||||
ArgumentKind.list => new ListArgument(values, typeArguments),
|
||||
ArgumentKind.set => new SetArgument(values, typeArguments),
|
||||
_ => throw new UnsupportedError(
|
||||
'Could not deserialize argument of kind $kind'),
|
||||
} as _IterableArgument<T>;
|
||||
}
|
||||
|
||||
@override
|
||||
void serialize(Serializer serializer) {
|
||||
super.serialize(serializer);
|
||||
serializer.startList();
|
||||
for (Argument argument in _arguments) {
|
||||
argument.serialize(serializer);
|
||||
}
|
||||
serializer.endList();
|
||||
}
|
||||
}
|
||||
|
||||
final class ListArgument extends _IterableArgument<List<Object?>> {
|
||||
@override
|
||||
ArgumentKind get kind => ArgumentKind.list;
|
||||
|
||||
/// Materializes all the `_arguments` as actual values.
|
||||
@override
|
||||
List<Object?> get value {
|
||||
return extractIterableTypeArgument(_extractTypeArguments().single, <S>() {
|
||||
return <S>[for (Argument arg in _arguments) arg.value as S];
|
||||
}) as List<Object?>;
|
||||
}
|
||||
|
||||
ListArgument(super._arguments, super._typeArguments);
|
||||
|
||||
@override
|
||||
void serialize(Serializer serializer) => super.serialize(serializer);
|
||||
}
|
||||
|
||||
final class SetArgument extends _IterableArgument<Set<Object?>> {
|
||||
@override
|
||||
ArgumentKind get kind => ArgumentKind.set;
|
||||
|
||||
/// Materializes all the `_arguments` as actual values.
|
||||
@override
|
||||
Set<Object?> get value {
|
||||
return extractIterableTypeArgument(_extractTypeArguments().single, <S>() {
|
||||
return <S>{for (Argument arg in _arguments) arg.value as S};
|
||||
}) as Set<Object?>;
|
||||
}
|
||||
|
||||
SetArgument(super._arguments, super._typeArguments);
|
||||
|
||||
@override
|
||||
void serialize(Serializer serializer) => super.serialize(serializer);
|
||||
}
|
||||
|
||||
final class MapArgument extends _CollectionArgument {
|
||||
@override
|
||||
ArgumentKind get kind => ArgumentKind.map;
|
||||
|
||||
/// These are the raw argument values for the entries in this map.
|
||||
final Map<Argument, Argument> _arguments;
|
||||
|
||||
/// Materializes all the `_arguments` as actual values.
|
||||
@override
|
||||
Map<Object?, Object?> get value {
|
||||
// We should have exactly two type arguments, the key and value types.
|
||||
final List<List<Object?>> extractedTypes = _extractTypeArguments();
|
||||
assert(extractedTypes.length == 2);
|
||||
return extractIterableTypeArgument(extractedTypes.removeLast(), <K>() {
|
||||
return extractIterableTypeArgument(extractedTypes.removeLast(), <V>() {
|
||||
return <K, V>{
|
||||
for (MapEntry<Argument, Argument> argument in _arguments.entries)
|
||||
argument.key.value as K: argument.value.value as V,
|
||||
};
|
||||
});
|
||||
}) as Map<Object?, Object?>;
|
||||
}
|
||||
|
||||
MapArgument(this._arguments, super._typeArguments);
|
||||
|
||||
factory MapArgument._deserialize(Deserializer deserializer) {
|
||||
deserializer
|
||||
..moveNext()
|
||||
..expectList();
|
||||
final List<ArgumentKind> typeArguments = [
|
||||
for (bool hasNext = deserializer.moveNext();
|
||||
hasNext;
|
||||
hasNext = deserializer.moveNext())
|
||||
ArgumentKind.values[deserializer.expectInt()],
|
||||
];
|
||||
deserializer
|
||||
..moveNext()
|
||||
..expectList();
|
||||
final Map<Argument, Argument> arguments = {
|
||||
for (bool hasNext = deserializer.moveNext();
|
||||
hasNext;
|
||||
hasNext = deserializer.moveNext())
|
||||
new Argument.deserialize(deserializer, alreadyMoved: true):
|
||||
new Argument.deserialize(deserializer),
|
||||
};
|
||||
return new MapArgument(arguments, typeArguments);
|
||||
}
|
||||
|
||||
@override
|
||||
void serialize(Serializer serializer) {
|
||||
super.serialize(serializer);
|
||||
serializer.startList();
|
||||
for (MapEntry<Argument, Argument> argument in _arguments.entries) {
|
||||
argument.key.serialize(serializer);
|
||||
argument.value.serialize(serializer);
|
||||
}
|
||||
serializer.endList();
|
||||
}
|
||||
}
|
||||
|
||||
/// The arguments passed to a macro constructor.
|
||||
///
|
||||
/// All argument instances must be of type [Code] or a built-in value type that
|
||||
/// is serializable (num, bool, String, null, etc).
|
||||
class Arguments implements Serializable {
|
||||
final List<Argument> positional;
|
||||
|
||||
final Map<String, Argument> named;
|
||||
|
||||
Arguments(this.positional, this.named);
|
||||
|
||||
factory Arguments.deserialize(Deserializer deserializer) {
|
||||
deserializer
|
||||
..moveNext()
|
||||
..expectList();
|
||||
final List<Argument> positionalArgs = [
|
||||
for (bool hasNext = deserializer.moveNext();
|
||||
hasNext;
|
||||
hasNext = deserializer.moveNext())
|
||||
new Argument.deserialize(deserializer, alreadyMoved: true),
|
||||
];
|
||||
deserializer
|
||||
..moveNext()
|
||||
..expectList();
|
||||
final Map<String, Argument> namedArgs = {
|
||||
for (bool hasNext = deserializer.moveNext();
|
||||
hasNext;
|
||||
hasNext = deserializer.moveNext())
|
||||
deserializer.expectString(): new Argument.deserialize(deserializer),
|
||||
};
|
||||
return new Arguments(positionalArgs, namedArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void serialize(Serializer serializer) {
|
||||
serializer.startList();
|
||||
for (Argument arg in positional) {
|
||||
arg.serialize(serializer);
|
||||
}
|
||||
serializer.endList();
|
||||
|
||||
serializer.startList();
|
||||
for (MapEntry<String, Argument> arg in named.entries) {
|
||||
serializer.addString(arg.key);
|
||||
arg.value.serialize(serializer);
|
||||
}
|
||||
serializer.endList();
|
||||
}
|
||||
}
|
||||
|
||||
/// Used for serializing and deserializing arguments.
|
||||
///
|
||||
/// Note that the `nullable` variants, as well as `object`, `dynamic`, and `num`
|
||||
/// are only used for type arguments. Instances should have an argument kind
|
||||
/// that matches their their actual value.
|
||||
enum ArgumentKind {
|
||||
bool,
|
||||
string,
|
||||
double,
|
||||
int,
|
||||
list,
|
||||
map,
|
||||
set,
|
||||
nil,
|
||||
object,
|
||||
dynamic,
|
||||
num,
|
||||
nullable,
|
||||
}
|
|
@ -7,7 +7,6 @@ environment:
|
|||
sdk: ^3.0.0
|
||||
|
||||
dependencies:
|
||||
dart_internal: ^0.2.7
|
||||
meta: ^1.0.2
|
||||
|
||||
# We use 'any' version constraints here as we get our package versions from
|
||||
|
|
|
@ -92,7 +92,7 @@ void main() {
|
|||
reason: 'Can create an instance with no arguments.');
|
||||
|
||||
instanceId = await executor.instantiateMacro(
|
||||
macroUri, macroName, '', Arguments([IntArgument(1)], {}));
|
||||
macroUri, macroName, '', Arguments([1], {}));
|
||||
expect(instanceId, isNotNull,
|
||||
reason: 'Can create an instance with positional arguments.');
|
||||
|
||||
|
@ -101,33 +101,23 @@ void main() {
|
|||
macroName,
|
||||
'named',
|
||||
Arguments([], {
|
||||
'myBool': BoolArgument(true),
|
||||
'myDouble': DoubleArgument(1.0),
|
||||
'myInt': IntArgument(1),
|
||||
'myList': ListArgument([
|
||||
IntArgument(1),
|
||||
IntArgument(2),
|
||||
IntArgument(3),
|
||||
], [
|
||||
ArgumentKind.nullable,
|
||||
ArgumentKind.int
|
||||
]),
|
||||
'mySet': SetArgument([
|
||||
BoolArgument(true),
|
||||
NullArgument(),
|
||||
MapArgument({StringArgument('a'): DoubleArgument(1.0)},
|
||||
[ArgumentKind.string, ArgumentKind.double]),
|
||||
], [
|
||||
ArgumentKind.nullable,
|
||||
ArgumentKind.object,
|
||||
]),
|
||||
'myMap': MapArgument({
|
||||
StringArgument('x'): IntArgument(1),
|
||||
}, [
|
||||
ArgumentKind.string,
|
||||
ArgumentKind.int
|
||||
]),
|
||||
'myString': StringArgument('a'),
|
||||
'myBool': true,
|
||||
'myDouble': 1.0,
|
||||
'myInt': 1,
|
||||
'myList': [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
],
|
||||
'mySet': {
|
||||
true,
|
||||
null,
|
||||
{'a': 1.0}
|
||||
},
|
||||
'myMap': {
|
||||
'x': 1,
|
||||
},
|
||||
'myString': 'a',
|
||||
}));
|
||||
expect(instanceId, isNotNull,
|
||||
reason: 'Can create an instance with named arguments.');
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:_fe_analyzer_shared/src/macros/api.dart';
|
||||
import 'package:_fe_analyzer_shared/src/macros/executor.dart';
|
||||
import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart';
|
||||
import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart';
|
||||
import 'package:_fe_analyzer_shared/src/macros/executor/serialization.dart';
|
||||
import 'package:_fe_analyzer_shared/src/macros/executor/serialization_extensions.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../util.dart';
|
||||
|
@ -156,8 +156,7 @@ void main() {
|
|||
]) {
|
||||
group('with mode $mode', () {
|
||||
test('NamedTypeAnnotation', () {
|
||||
expectSerializationEquality<TypeAnnotationImpl>(
|
||||
fooType, mode, RemoteInstance.deserialize);
|
||||
expectSerializationEquality(fooType, mode);
|
||||
});
|
||||
|
||||
final fooNamedParam = ParameterDeclarationImpl(
|
||||
|
@ -215,8 +214,7 @@ void main() {
|
|||
returnType: fooType,
|
||||
typeParameters: [zapTypeParam],
|
||||
);
|
||||
expectSerializationEquality<TypeAnnotationImpl>(
|
||||
functionType, mode, RemoteInstance.deserialize);
|
||||
expectSerializationEquality(functionType, mode);
|
||||
});
|
||||
|
||||
test('FunctionDeclaration', () {
|
||||
|
@ -233,8 +231,7 @@ void main() {
|
|||
positionalParameters: [],
|
||||
returnType: fooType,
|
||||
typeParameters: []);
|
||||
expectSerializationEquality<DeclarationImpl>(
|
||||
function, mode, RemoteInstance.deserialize);
|
||||
expectSerializationEquality(function, mode);
|
||||
});
|
||||
|
||||
test('MethodDeclaration', () {
|
||||
|
@ -253,8 +250,7 @@ void main() {
|
|||
typeParameters: [zapTypeParam],
|
||||
definingType: fooType.identifier,
|
||||
isStatic: false);
|
||||
expectSerializationEquality<DeclarationImpl>(
|
||||
method, mode, RemoteInstance.deserialize);
|
||||
expectSerializationEquality(method, mode);
|
||||
});
|
||||
|
||||
test('ConstructorDeclaration', () {
|
||||
|
@ -274,8 +270,7 @@ void main() {
|
|||
definingType: fooType.identifier,
|
||||
isFactory: true,
|
||||
);
|
||||
expectSerializationEquality<DeclarationImpl>(
|
||||
constructor, mode, RemoteInstance.deserialize);
|
||||
expectSerializationEquality(constructor, mode);
|
||||
});
|
||||
|
||||
test('VariableDeclaration', () {
|
||||
|
@ -288,8 +283,7 @@ void main() {
|
|||
isLate: true,
|
||||
type: barType,
|
||||
);
|
||||
expectSerializationEquality<DeclarationImpl>(
|
||||
bar, mode, RemoteInstance.deserialize);
|
||||
expectSerializationEquality(bar, mode);
|
||||
});
|
||||
|
||||
test('FieldDeclaration', () {
|
||||
|
@ -304,8 +298,7 @@ void main() {
|
|||
definingType: fooType.identifier,
|
||||
isStatic: false,
|
||||
);
|
||||
expectSerializationEquality<DeclarationImpl>(
|
||||
bar, mode, RemoteInstance.deserialize);
|
||||
expectSerializationEquality(bar, mode);
|
||||
});
|
||||
|
||||
var objectType = NamedTypeAnnotationImpl(
|
||||
|
@ -341,8 +334,7 @@ void main() {
|
|||
superclass: objectType,
|
||||
typeParameters: [zapTypeParam],
|
||||
);
|
||||
expectSerializationEquality<DeclarationImpl>(
|
||||
fooClass, mode, RemoteInstance.deserialize);
|
||||
expectSerializationEquality(fooClass, mode);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -355,8 +347,7 @@ void main() {
|
|||
mixins: [serializableType],
|
||||
typeParameters: [zapTypeParam],
|
||||
);
|
||||
expectSerializationEquality<DeclarationImpl>(
|
||||
fooEnum, mode, RemoteInstance.deserialize);
|
||||
expectSerializationEquality(fooEnum, mode);
|
||||
});
|
||||
|
||||
test('EnumValueDeclaration', () {
|
||||
|
@ -366,8 +357,7 @@ void main() {
|
|||
definingEnum:
|
||||
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'MyEnum'),
|
||||
);
|
||||
expectSerializationEquality<DeclarationImpl>(
|
||||
entry, mode, RemoteInstance.deserialize);
|
||||
expectSerializationEquality(entry, mode);
|
||||
});
|
||||
|
||||
test('MixinDeclaration', () {
|
||||
|
@ -381,8 +371,7 @@ void main() {
|
|||
superclassConstraints: [serializableType],
|
||||
typeParameters: [zapTypeParam],
|
||||
);
|
||||
expectSerializationEquality<DeclarationImpl>(
|
||||
mixin, mode, RemoteInstance.deserialize);
|
||||
expectSerializationEquality(mixin, mode);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -399,8 +388,7 @@ void main() {
|
|||
IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
|
||||
typeArguments: [barType]),
|
||||
);
|
||||
expectSerializationEquality<DeclarationImpl>(
|
||||
typeAlias, mode, RemoteInstance.deserialize);
|
||||
expectSerializationEquality(typeAlias, mode);
|
||||
});
|
||||
|
||||
/// Transitively tests [RecordField]
|
||||
|
@ -427,135 +415,17 @@ void main() {
|
|||
),
|
||||
],
|
||||
);
|
||||
expectSerializationEquality<TypeAnnotationImpl>(
|
||||
recordType, mode, RemoteInstance.deserialize);
|
||||
expectSerializationEquality(recordType, mode);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
group('Arguments', () {
|
||||
test('can create properly typed collections', () {
|
||||
withSerializationMode(SerializationMode.jsonClient, () {
|
||||
final parsed = Arguments.deserialize(deserializerFactory([
|
||||
// positional args
|
||||
[
|
||||
// int
|
||||
ArgumentKind.int.index,
|
||||
1,
|
||||
// List<int>
|
||||
ArgumentKind.list.index,
|
||||
[ArgumentKind.int.index],
|
||||
[
|
||||
ArgumentKind.int.index,
|
||||
1,
|
||||
ArgumentKind.int.index,
|
||||
2,
|
||||
ArgumentKind.int.index,
|
||||
3,
|
||||
],
|
||||
// List<Set<String>>
|
||||
ArgumentKind.list.index,
|
||||
[ArgumentKind.set.index, ArgumentKind.string.index],
|
||||
[
|
||||
// Set<String>
|
||||
ArgumentKind.set.index,
|
||||
[ArgumentKind.string.index],
|
||||
[
|
||||
ArgumentKind.string.index,
|
||||
'hello',
|
||||
ArgumentKind.string.index,
|
||||
'world',
|
||||
]
|
||||
],
|
||||
// Map<int, List<String>>
|
||||
ArgumentKind.map.index,
|
||||
[
|
||||
ArgumentKind.int.index,
|
||||
ArgumentKind.nullable.index,
|
||||
ArgumentKind.list.index,
|
||||
ArgumentKind.string.index
|
||||
],
|
||||
[
|
||||
// key: int
|
||||
ArgumentKind.int.index,
|
||||
4,
|
||||
// value: List<String>
|
||||
ArgumentKind.list.index,
|
||||
[ArgumentKind.string.index],
|
||||
[
|
||||
ArgumentKind.string.index,
|
||||
'zip',
|
||||
],
|
||||
ArgumentKind.int.index,
|
||||
5,
|
||||
ArgumentKind.nil.index,
|
||||
]
|
||||
],
|
||||
// named args
|
||||
[],
|
||||
]));
|
||||
expect(parsed.positional.length, 4);
|
||||
expect(parsed.positional.first.value, 1);
|
||||
expect(parsed.positional[1].value, [1, 2, 3]);
|
||||
expect(parsed.positional[1].value, isA<List<int>>());
|
||||
expect(parsed.positional[2].value, [
|
||||
{'hello', 'world'}
|
||||
]);
|
||||
expect(parsed.positional[2].value, isA<List<Set<String>>>());
|
||||
expect(
|
||||
parsed.positional[3].value,
|
||||
{
|
||||
4: ['zip'],
|
||||
5: null,
|
||||
},
|
||||
);
|
||||
expect(parsed.positional[3].value, isA<Map<int, List<String>?>>());
|
||||
});
|
||||
});
|
||||
|
||||
group('can be serialized and deserialized', () {
|
||||
for (var mode in [
|
||||
SerializationMode.byteDataServer,
|
||||
SerializationMode.jsonServer
|
||||
]) {
|
||||
test('with mode $mode', () {
|
||||
final arguments = Arguments([
|
||||
MapArgument({
|
||||
StringArgument('hello'): ListArgument(
|
||||
[BoolArgument(true), NullArgument()],
|
||||
[ArgumentKind.nullable, ArgumentKind.bool]),
|
||||
}, [
|
||||
ArgumentKind.string,
|
||||
ArgumentKind.list,
|
||||
ArgumentKind.nullable,
|
||||
ArgumentKind.bool
|
||||
]),
|
||||
], {
|
||||
'a': SetArgument([
|
||||
MapArgument({
|
||||
IntArgument(1): StringArgument('1'),
|
||||
}, [
|
||||
ArgumentKind.int,
|
||||
ArgumentKind.string
|
||||
])
|
||||
], [
|
||||
ArgumentKind.map,
|
||||
ArgumentKind.int,
|
||||
ArgumentKind.string
|
||||
])
|
||||
});
|
||||
expectSerializationEquality(arguments, mode, Arguments.deserialize);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Serializes [serializable] in server mode, then deserializes it in client
|
||||
/// mode, and checks that all the fields are the same.
|
||||
void expectSerializationEquality<T extends Serializable>(T serializable,
|
||||
SerializationMode serverMode, T deserialize(Deserializer deserializer)) {
|
||||
void expectSerializationEquality(
|
||||
Serializable serializable, SerializationMode serverMode) {
|
||||
late Object? serialized;
|
||||
withSerializationMode(serverMode, () {
|
||||
var serializer = serializerFactory();
|
||||
|
@ -564,18 +434,14 @@ void expectSerializationEquality<T extends Serializable>(T serializable,
|
|||
});
|
||||
withSerializationMode(_clientModeForServerMode(serverMode), () {
|
||||
var deserializer = deserializerFactory(serialized);
|
||||
var deserialized = deserialize(deserializer);
|
||||
|
||||
expect(
|
||||
serializable,
|
||||
(switch (deserialized) {
|
||||
Declaration() => deepEqualsDeclaration(deserialized as Declaration),
|
||||
TypeAnnotation() =>
|
||||
deepEqualsTypeAnnotation(deserialized as TypeAnnotation),
|
||||
Arguments() => deepEqualsArguments(deserialized),
|
||||
_ =>
|
||||
throw new UnsupportedError('Unsupported object type $deserialized'),
|
||||
}));
|
||||
var deserialized = (deserializer..moveNext()).expectRemoteInstance();
|
||||
if (deserialized is Declaration) {
|
||||
expect(serializable, deepEqualsDeclaration(deserialized));
|
||||
} else if (deserialized is TypeAnnotation) {
|
||||
expect(serializable, deepEqualsTypeAnnotation(deserialized));
|
||||
} else {
|
||||
throw new UnsupportedError('Unsupported object type $deserialized');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -583,7 +449,8 @@ void expectSerializationEquality<T extends Serializable>(T serializable,
|
|||
Object? roundTrip<Declaration>(Object? serialized) {
|
||||
return withSerializationMode(_clientModeForServerMode(serializationMode), () {
|
||||
var deserializer = deserializerFactory(serialized);
|
||||
var instance = RemoteInstance.deserialize(deserializer);
|
||||
var instance =
|
||||
RemoteInstance.deserialize<NamedTypeAnnotationImpl>(deserializer);
|
||||
var serializer = serializerFactory();
|
||||
instance.serialize(serializer);
|
||||
return serializer.result;
|
||||
|
|
|
@ -175,10 +175,6 @@ Matcher deepEqualsDeclaration(Declaration declaration) =>
|
|||
Matcher deepEqualsTypeAnnotation(TypeAnnotation declaration) =>
|
||||
_DeepEqualityMatcher(declaration);
|
||||
|
||||
/// Checks if two [Arguments]s are identical
|
||||
Matcher deepEqualsArguments(Arguments arguments) =>
|
||||
_DeepEqualityMatcher(arguments);
|
||||
|
||||
/// Checks if two [Declaration]s, [TypeAnnotation]s, or [Code] objects are of
|
||||
/// the same type and all their fields are equal.
|
||||
class _DeepEqualityMatcher extends Matcher {
|
||||
|
@ -191,11 +187,10 @@ class _DeepEqualityMatcher extends Matcher {
|
|||
|
||||
@override
|
||||
bool matches(item, Map matchState) {
|
||||
// For type promotion.
|
||||
final instance = this.instance;
|
||||
if (!equals(item.runtimeType).matches(instance.runtimeType, matchState)) {
|
||||
if (item.runtimeType != instance.runtimeType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (instance is Declaration || instance is TypeAnnotation) {
|
||||
var instanceReflector = reflect(instance);
|
||||
var itemReflector = reflect(item);
|
||||
|
@ -211,52 +206,47 @@ class _DeepEqualityMatcher extends Matcher {
|
|||
var instanceValue = instanceField.reflectee;
|
||||
var itemValue = itemField.reflectee;
|
||||
|
||||
if (!_DeepEqualityMatcher(instanceValue)
|
||||
.matches(itemValue, matchState)) {
|
||||
return false;
|
||||
// Handle lists of things
|
||||
if (instanceValue is List) {
|
||||
if (!_listEquals(instanceValue, itemValue, matchState)) {
|
||||
return false;
|
||||
}
|
||||
} else if (instanceValue is Declaration ||
|
||||
instanceValue is Code ||
|
||||
instanceValue is TypeAnnotation) {
|
||||
// Handle nested declarations and code objects
|
||||
if (!_DeepEqualityMatcher(instanceValue)
|
||||
.matches(itemValue, matchState)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Handles basic values and identity
|
||||
if (instanceValue != itemValue) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (instance is Code) {
|
||||
item as Code;
|
||||
if (!_DeepEqualityMatcher(instance.parts)
|
||||
.matches(item.parts, matchState)) {
|
||||
if (!_listEquals(
|
||||
(instance as Code).parts, (item as Code).parts, matchState)) {
|
||||
return false;
|
||||
}
|
||||
} else if (instance is Arguments) {
|
||||
item as Arguments;
|
||||
if (!equals(instance.positional.length)
|
||||
.matches(item.positional.length, matchState)) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < instance.positional.length; i++) {
|
||||
if (!_DeepEqualityMatcher(instance.positional[i].value)
|
||||
.matches(item.positional[i].value, matchState)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (instance.named.length != item.named.length) return false;
|
||||
if (!equals(instance.named.keys).matches(item.named.keys, matchState)) {
|
||||
return false;
|
||||
}
|
||||
for (var key in instance.named.keys) {
|
||||
if (!_DeepEqualityMatcher(instance.named[key]!.value)
|
||||
.matches(item.named[key]!.value, matchState)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (instance is List) {
|
||||
item as List;
|
||||
if (!equals(instance.length).matches(item.length, matchState)) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < instance.length; i++) {
|
||||
if (!_DeepEqualityMatcher(instance[i]).matches(item[i], matchState)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Handles basic values and identity
|
||||
if (!equals(instance).matches(item, matchState)) {
|
||||
if (instance != item) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _listEquals(List instanceValue, List itemValue, Map matchState) {
|
||||
if (instanceValue.length != itemValue.length) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < instanceValue.length; i++) {
|
||||
if (!_DeepEqualityMatcher(instanceValue[i])
|
||||
.matches(itemValue[i], matchState)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,47 +22,6 @@ import 'package:analyzer/src/summary2/macro_application_error.dart';
|
|||
import 'package:analyzer/src/summary2/macro_declarations.dart';
|
||||
import 'package:analyzer/src/util/performance/operation_performance.dart';
|
||||
|
||||
/// The full list of [macro.ArgumentKind]s for this dart type (includes the type
|
||||
/// itself as well as type arguments, in source order with
|
||||
/// [macro.ArgumentKind.nullable] modifiers preceding the nullable types).
|
||||
List<macro.ArgumentKind> _dartTypeArgumentKinds(DartType dartType) => [
|
||||
if (dartType.nullabilitySuffix == NullabilitySuffix.question)
|
||||
macro.ArgumentKind.nullable,
|
||||
switch (dartType) {
|
||||
DartType(isDartCoreBool: true) => macro.ArgumentKind.bool,
|
||||
DartType(isDartCoreDouble: true) => macro.ArgumentKind.double,
|
||||
DartType(isDartCoreInt: true) => macro.ArgumentKind.int,
|
||||
DartType(isDartCoreNum: true) => macro.ArgumentKind.num,
|
||||
DartType(isDartCoreNull: true) => macro.ArgumentKind.nil,
|
||||
DartType(isDartCoreObject: true) => macro.ArgumentKind.object,
|
||||
DartType(isDartCoreString: true) => macro.ArgumentKind.string,
|
||||
// TODO: Support nested type arguments for collections.
|
||||
DartType(isDartCoreList: true) => macro.ArgumentKind.list,
|
||||
DartType(isDartCoreMap: true) => macro.ArgumentKind.map,
|
||||
DartType(isDartCoreSet: true) => macro.ArgumentKind.set,
|
||||
DynamicType() => macro.ArgumentKind.dynamic,
|
||||
_ =>
|
||||
throw UnsupportedError('Unsupported macro type argument $dartType'),
|
||||
},
|
||||
if (dartType is ParameterizedType) ...[
|
||||
for (var type in dartType.typeArguments)
|
||||
..._dartTypeArgumentKinds(type),
|
||||
]
|
||||
];
|
||||
|
||||
List<macro.ArgumentKind> _typeArgumentsForNode(TypedLiteral node) {
|
||||
if (node.typeArguments == null) {
|
||||
return [
|
||||
// TODO: Use inferred type here.
|
||||
macro.ArgumentKind.dynamic,
|
||||
];
|
||||
}
|
||||
return [
|
||||
for (var type in node.typeArguments!.arguments.map((arg) => arg.type!))
|
||||
..._dartTypeArgumentKinds(type),
|
||||
];
|
||||
}
|
||||
|
||||
class LibraryMacroApplier {
|
||||
final DeclarationBuilder declarationBuilder;
|
||||
final LibraryBuilder libraryBuilder;
|
||||
|
@ -384,8 +343,8 @@ class LibraryMacroApplier {
|
|||
required int annotationIndex,
|
||||
required ArgumentList node,
|
||||
}) {
|
||||
final positional = <macro.Argument>[];
|
||||
final named = <String, macro.Argument>{};
|
||||
final positional = <Object?>[];
|
||||
final named = <String, Object?>{};
|
||||
for (var i = 0; i < node.arguments.length; ++i) {
|
||||
final argument = node.arguments[i];
|
||||
final evaluation = _ArgumentEvaluation(
|
||||
|
@ -445,43 +404,38 @@ class _ArgumentEvaluation {
|
|||
required this.argumentIndex,
|
||||
});
|
||||
|
||||
macro.Argument evaluate(Expression node) {
|
||||
Object? evaluate(Expression node) {
|
||||
if (node is AdjacentStrings) {
|
||||
return macro.StringArgument(node.strings.map(evaluate).join(''));
|
||||
return node.strings.map(evaluate).join('');
|
||||
} else if (node is BooleanLiteral) {
|
||||
return macro.BoolArgument(node.value);
|
||||
return node.value;
|
||||
} else if (node is DoubleLiteral) {
|
||||
return macro.DoubleArgument(node.value);
|
||||
return node.value;
|
||||
} else if (node is IntegerLiteral) {
|
||||
return macro.IntArgument(node.value!);
|
||||
return node.value;
|
||||
} else if (node is ListLiteral) {
|
||||
final typeArguments = _typeArgumentsForNode(node);
|
||||
return macro.ListArgument(
|
||||
node.elements.cast<Expression>().map(evaluate).toList(),
|
||||
typeArguments);
|
||||
return node.elements.cast<Expression>().map(evaluate).toList();
|
||||
} else if (node is NullLiteral) {
|
||||
return macro.NullArgument();
|
||||
return null;
|
||||
} else if (node is PrefixExpression &&
|
||||
node.operator.type == TokenType.MINUS) {
|
||||
final operandValue = evaluate(node.operand);
|
||||
if (operandValue is macro.DoubleArgument) {
|
||||
return macro.DoubleArgument(-operandValue.value);
|
||||
} else if (operandValue is macro.IntArgument) {
|
||||
return macro.IntArgument(-operandValue.value);
|
||||
if (operandValue is double) {
|
||||
return -operandValue;
|
||||
} else if (operandValue is int) {
|
||||
return -operandValue;
|
||||
}
|
||||
} else if (node is SetOrMapLiteral) {
|
||||
return _setOrMapLiteral(node);
|
||||
} else if (node is SimpleStringLiteral) {
|
||||
return macro.StringArgument(node.value);
|
||||
return node.value;
|
||||
}
|
||||
_throwError(node, 'Not supported: ${node.runtimeType}');
|
||||
}
|
||||
|
||||
macro.Argument _setOrMapLiteral(SetOrMapLiteral node) {
|
||||
final typeArguments = _typeArgumentsForNode(node);
|
||||
|
||||
Object _setOrMapLiteral(SetOrMapLiteral node) {
|
||||
if (node.elements.every((e) => e is Expression)) {
|
||||
final result = <macro.Argument>[];
|
||||
final result = <Object?>{};
|
||||
for (final element in node.elements) {
|
||||
if (element is! Expression) {
|
||||
_throwError(element, 'Expression expected');
|
||||
|
@ -489,10 +443,10 @@ class _ArgumentEvaluation {
|
|||
final value = evaluate(element);
|
||||
result.add(value);
|
||||
}
|
||||
return macro.SetArgument(result, typeArguments);
|
||||
return result;
|
||||
}
|
||||
|
||||
final result = <macro.Argument, macro.Argument>{};
|
||||
final result = <Object?, Object?>{};
|
||||
for (final element in node.elements) {
|
||||
if (element is! MapLiteralEntry) {
|
||||
_throwError(element, 'MapLiteralEntry expected');
|
||||
|
@ -501,7 +455,7 @@ class _ArgumentEvaluation {
|
|||
final value = evaluate(element.value);
|
||||
result[key] = value;
|
||||
}
|
||||
return macro.MapArgument(result, typeArguments);
|
||||
return result;
|
||||
}
|
||||
|
||||
Never _throwError(AstNode node, String message) {
|
||||
|
|
|
@ -83,18 +83,16 @@ class _NoArgumentsNode implements _Node {
|
|||
}
|
||||
|
||||
class _ArgumentsNode implements _Node {
|
||||
final List<macro.Argument> positionalArguments;
|
||||
final Map<String, macro.Argument> namedArguments;
|
||||
final List<Object?> positionalArguments;
|
||||
final Map<String, Object?> namedArguments;
|
||||
|
||||
_ArgumentsNode(this.positionalArguments, this.namedArguments);
|
||||
}
|
||||
|
||||
class _PrimitiveValueNode implements _Node {
|
||||
Object? get value => argument.value;
|
||||
final Object? value;
|
||||
|
||||
final macro.Argument argument;
|
||||
|
||||
_PrimitiveValueNode(this.argument);
|
||||
_PrimitiveValueNode(this.value);
|
||||
}
|
||||
|
||||
class _TokenNode implements _Node {
|
||||
|
@ -111,11 +109,9 @@ class _NamedArgumentIdentifierNode implements _Node {
|
|||
|
||||
class _NamedArgumentNode implements _Node {
|
||||
final String name;
|
||||
final macro.Argument argument;
|
||||
final Object? value;
|
||||
|
||||
Object? get value => argument.value;
|
||||
|
||||
_NamedArgumentNode(this.name, this.argument);
|
||||
_NamedArgumentNode(this.name, this.value);
|
||||
}
|
||||
|
||||
class _MacroListener implements Listener {
|
||||
|
@ -271,15 +267,15 @@ class _MacroListener implements Listener {
|
|||
pushUnsupported();
|
||||
return;
|
||||
}
|
||||
List<macro.Argument> positionalArguments = [];
|
||||
Map<String, macro.Argument> namedArguments = {};
|
||||
List<Object?> positionalArguments = [];
|
||||
Map<String, Object?> namedArguments = {};
|
||||
for (int i = 0; i < count; i++) {
|
||||
_Node node = pop();
|
||||
if (node is _PrimitiveValueNode) {
|
||||
positionalArguments.add(node.argument);
|
||||
positionalArguments.add(node.value);
|
||||
} else if (node is _NamedArgumentNode &&
|
||||
!namedArguments.containsKey(node.name)) {
|
||||
namedArguments[node.name] = node.argument;
|
||||
namedArguments[node.name] = node.value;
|
||||
} else {
|
||||
_unsupported();
|
||||
}
|
||||
|
@ -321,7 +317,7 @@ class _MacroListener implements Listener {
|
|||
_Node name = pop();
|
||||
if (name is _NamedArgumentIdentifierNode &&
|
||||
value is _PrimitiveValueNode) {
|
||||
push(new _NamedArgumentNode(name.name, value.argument));
|
||||
push(new _NamedArgumentNode(name.name, value.value));
|
||||
} else {
|
||||
pushUnsupported();
|
||||
}
|
||||
|
@ -339,25 +335,22 @@ class _MacroListener implements Listener {
|
|||
|
||||
@override
|
||||
void handleLiteralNull(Token token) {
|
||||
push(new _PrimitiveValueNode(new macro.NullArgument()));
|
||||
push(new _PrimitiveValueNode(null));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleLiteralBool(Token token) {
|
||||
push(new _PrimitiveValueNode(
|
||||
new macro.BoolArgument(token.lexeme == 'true')));
|
||||
push(new _PrimitiveValueNode(token.lexeme == 'true'));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleLiteralDouble(Token token) {
|
||||
push(new _PrimitiveValueNode(
|
||||
new macro.DoubleArgument(double.parse(token.lexeme))));
|
||||
push(new _PrimitiveValueNode(double.parse(token.lexeme)));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleLiteralInt(Token token) {
|
||||
push(new _PrimitiveValueNode(
|
||||
new macro.IntArgument(int.parse(token.lexeme))));
|
||||
push(new _PrimitiveValueNode(int.parse(token.lexeme)));
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -378,7 +371,7 @@ class _MacroListener implements Listener {
|
|||
if (unrecognized) {
|
||||
pushUnsupported();
|
||||
} else {
|
||||
push(new _PrimitiveValueNode(new macro.StringArgument(text)));
|
||||
push(new _PrimitiveValueNode(text));
|
||||
}
|
||||
} else {
|
||||
pushUnsupported();
|
||||
|
@ -412,8 +405,7 @@ class _MacroListener implements Listener {
|
|||
if (unrecognized) {
|
||||
pushUnsupported();
|
||||
} else {
|
||||
push(new _PrimitiveValueNode(
|
||||
new macro.StringArgument(values.reversed.join())));
|
||||
push(new _PrimitiveValueNode(values.reversed.join()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import 'utils/io_utils.dart' show computeRepoDirUri;
|
|||
final Uri repoDir = computeRepoDirUri();
|
||||
|
||||
Set<String> allowlistedExternalDartFiles = {
|
||||
"pkg/dart_internal/lib/extract_type_arguments.dart",
|
||||
"third_party/pkg/package_config/lib/package_config.dart",
|
||||
"third_party/pkg/package_config/lib/package_config_types.dart",
|
||||
"third_party/pkg/package_config/lib/src/discovery.dart",
|
||||
|
|
|
@ -14,10 +14,6 @@
|
|||
{
|
||||
"name": "_fe_analyzer_shared",
|
||||
"rootUri": "../../../../../_fe_analyzer_shared/lib/"
|
||||
},
|
||||
{
|
||||
"name": "dart_internal",
|
||||
"rootUri": "../../../../../dart_internal/lib/"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -4,28 +4,28 @@
|
|||
|
||||
/*library:
|
||||
Declarations Order:
|
||||
Class1:SequenceMacro.new(IntArgument:0)
|
||||
Class2:SequenceMacro.new(IntArgument:1)
|
||||
Class2:SequenceMacro.new(IntArgument:0)
|
||||
Class3.method:SequenceMacro.new(IntArgument:1)
|
||||
Class3:SequenceMacro.new(IntArgument:0)
|
||||
Class4.method:SequenceMacro.new(IntArgument:3)
|
||||
Class4.method2:SequenceMacro.new(IntArgument:5)
|
||||
Class4.method2:SequenceMacro.new(IntArgument:4)
|
||||
Class4:SequenceMacro.new(IntArgument:2)
|
||||
Class4:SequenceMacro.new(IntArgument:1)
|
||||
Class4:SequenceMacro.new(IntArgument:0)
|
||||
Class5a:SequenceMacro.new(IntArgument:0)
|
||||
Class5b:SequenceMacro.new(IntArgument:0)
|
||||
Class5c:SequenceMacro.new(IntArgument:0)
|
||||
Class6c:SequenceMacro.new(IntArgument:0)
|
||||
Class6a:SequenceMacro.new(IntArgument:0)
|
||||
Class6b:SequenceMacro.new(IntArgument:0)
|
||||
Class6d:SequenceMacro.new(IntArgument:0)
|
||||
Class7a:SequenceMacro.new(IntArgument:0)
|
||||
Class7b:SequenceMacro.new(IntArgument:0)
|
||||
Class7c:SequenceMacro.new(IntArgument:0)
|
||||
Class7d:SequenceMacro.new(IntArgument:0)*/
|
||||
Class1:SequenceMacro.new(0)
|
||||
Class2:SequenceMacro.new(1)
|
||||
Class2:SequenceMacro.new(0)
|
||||
Class3.method:SequenceMacro.new(1)
|
||||
Class3:SequenceMacro.new(0)
|
||||
Class4.method:SequenceMacro.new(3)
|
||||
Class4.method2:SequenceMacro.new(5)
|
||||
Class4.method2:SequenceMacro.new(4)
|
||||
Class4:SequenceMacro.new(2)
|
||||
Class4:SequenceMacro.new(1)
|
||||
Class4:SequenceMacro.new(0)
|
||||
Class5a:SequenceMacro.new(0)
|
||||
Class5b:SequenceMacro.new(0)
|
||||
Class5c:SequenceMacro.new(0)
|
||||
Class6c:SequenceMacro.new(0)
|
||||
Class6a:SequenceMacro.new(0)
|
||||
Class6b:SequenceMacro.new(0)
|
||||
Class6d:SequenceMacro.new(0)
|
||||
Class7a:SequenceMacro.new(0)
|
||||
Class7b:SequenceMacro.new(0)
|
||||
Class7c:SequenceMacro.new(0)
|
||||
Class7d:SequenceMacro.new(0)*/
|
||||
|
||||
import 'package:macro/macro.dart';
|
||||
|
||||
|
|
|
@ -7,20 +7,20 @@
|
|||
package:_fe_analyzer_shared/src/macros/api.dart|package:macro/macro.dart,
|
||||
main.dart],
|
||||
macroInstanceIds=[
|
||||
package:macro/macro.dart/Macro4/(BoolArgument:false),
|
||||
package:macro/macro.dart/Macro4/(BoolArgument:false,named:BoolArgument:true),
|
||||
package:macro/macro.dart/Macro4/(BoolArgument:true),
|
||||
package:macro/macro.dart/Macro4/(DoubleArgument:3.14),
|
||||
package:macro/macro.dart/Macro4/(DoubleArgument:3.14,named:DoubleArgument:1.41),
|
||||
package:macro/macro.dart/Macro4/(IntArgument:42),
|
||||
package:macro/macro.dart/Macro4/(IntArgument:87,named:IntArgument:42),
|
||||
package:macro/macro.dart/Macro4/(NullArgument:null),
|
||||
package:macro/macro.dart/Macro4/(NullArgument:null,named:NullArgument:null),
|
||||
package:macro/macro.dart/Macro4/(StringArgument:bar,named:StringArgument:baz),
|
||||
package:macro/macro.dart/Macro4/(StringArgument:foo),
|
||||
package:macro/macro.dart/Macro4/(StringArgument:foobar),
|
||||
package:macro/macro.dart/Macro4/(StringArgument:foobar,named:StringArgument:boz_qux),
|
||||
package:macro/macro.dart/Macro4/(StringArgument:qux,named:StringArgument:boz)],
|
||||
package:macro/macro.dart/Macro4/(3.14),
|
||||
package:macro/macro.dart/Macro4/(3.14,named:1.41),
|
||||
package:macro/macro.dart/Macro4/(42),
|
||||
package:macro/macro.dart/Macro4/(87,named:42),
|
||||
package:macro/macro.dart/Macro4/(bar,named:baz),
|
||||
package:macro/macro.dart/Macro4/(false),
|
||||
package:macro/macro.dart/Macro4/(false,named:true),
|
||||
package:macro/macro.dart/Macro4/(foo),
|
||||
package:macro/macro.dart/Macro4/(foobar),
|
||||
package:macro/macro.dart/Macro4/(foobar,named:boz_qux),
|
||||
package:macro/macro.dart/Macro4/(null),
|
||||
package:macro/macro.dart/Macro4/(null,named:null),
|
||||
package:macro/macro.dart/Macro4/(qux,named:boz),
|
||||
package:macro/macro.dart/Macro4/(true)],
|
||||
macrosAreApplied,
|
||||
macrosAreAvailable,
|
||||
neededPrecompilations=[package:macro/macro.dart=Macro1(named/new)|Macro2(named/new)|Macro3(named/new)|Macro4(new)]
|
||||
|
@ -29,49 +29,49 @@
|
|||
import 'package:macro/macro.dart';
|
||||
|
||||
/*member: function1:appliedMacros=[
|
||||
Macro4.new(NullArgument:null),
|
||||
Macro4.new(NullArgument:null,named:NullArgument:null)]*/
|
||||
Macro4.new(null),
|
||||
Macro4.new(null,named:null)]*/
|
||||
@Macro4(null)
|
||||
@Macro4(null, named: null)
|
||||
function1() {}
|
||||
|
||||
/*member: function2:appliedMacros=[
|
||||
Macro4.new(IntArgument:42),
|
||||
Macro4.new(IntArgument:87,named:IntArgument:42)]*/
|
||||
Macro4.new(42),
|
||||
Macro4.new(87,named:42)]*/
|
||||
@Macro4(42)
|
||||
@Macro4(87, named: 42)
|
||||
function2() {}
|
||||
|
||||
/*member: function3:appliedMacros=[
|
||||
Macro4.new(BoolArgument:false,named:BoolArgument:true),
|
||||
Macro4.new(BoolArgument:true)]*/
|
||||
Macro4.new(false,named:true),
|
||||
Macro4.new(true)]*/
|
||||
@Macro4(true)
|
||||
@Macro4(false, named: true)
|
||||
function3() {}
|
||||
|
||||
/*member: function4:appliedMacros=[Macro4.new(BoolArgument:false)]*/
|
||||
/*member: function4:appliedMacros=[Macro4.new(false)]*/
|
||||
@Macro4(false)
|
||||
function4() {}
|
||||
|
||||
/*member: function5:appliedMacros=[
|
||||
Macro4.new(StringArgument:bar,named:StringArgument:baz),
|
||||
Macro4.new(StringArgument:foo),
|
||||
Macro4.new(StringArgument:qux,named:StringArgument:boz)]*/
|
||||
Macro4.new(bar,named:baz),
|
||||
Macro4.new(foo),
|
||||
Macro4.new(qux,named:boz)]*/
|
||||
@Macro4("foo")
|
||||
@Macro4("bar", named: "baz")
|
||||
@Macro4(named: "boz", "qux")
|
||||
function5() {}
|
||||
|
||||
/*member: function6:appliedMacros=[
|
||||
Macro4.new(DoubleArgument:3.14),
|
||||
Macro4.new(DoubleArgument:3.14,named:DoubleArgument:1.41)]*/
|
||||
Macro4.new(3.14),
|
||||
Macro4.new(3.14,named:1.41)]*/
|
||||
@Macro4(3.14)
|
||||
@Macro4(3.14, named: 1.41)
|
||||
function6() {}
|
||||
|
||||
/*member: function7:appliedMacros=[
|
||||
Macro4.new(StringArgument:foobar),
|
||||
Macro4.new(StringArgument:foobar,named:StringArgument:boz_qux)]*/
|
||||
Macro4.new(foobar),
|
||||
Macro4.new(foobar,named:boz_qux)]*/
|
||||
@Macro4("foo" "bar")
|
||||
@Macro4("foo" "bar", named: "boz" "_" "qux")
|
||||
function7() {}
|
||||
|
|
|
@ -381,7 +381,6 @@ dereferencing
|
|||
deregister
|
||||
descent
|
||||
descriptive
|
||||
deserializable
|
||||
deserializer
|
||||
deserializers
|
||||
deserializes
|
||||
|
@ -903,7 +902,6 @@ masks
|
|||
master
|
||||
matchers
|
||||
materialize
|
||||
materializes
|
||||
matters
|
||||
mature
|
||||
mb
|
||||
|
@ -1250,7 +1248,6 @@ regenerations
|
|||
regis
|
||||
registering
|
||||
rehash
|
||||
reified
|
||||
reindexed
|
||||
reinstate
|
||||
reissued
|
||||
|
|
Loading…
Reference in a new issue